Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Changelog

## 0.2.0

- Offline Kiro-compatible spec creation: `spec new` renders plain-Markdown
templates for feature and bugfix specs — no model, no API key, no network.
- Requirements-first, design-first, quick, and bugfix workflows with an
explicit state machine and per-stage approval gates.
- Deterministic spec analysis: `spec analyze` reports structural and
consistency problems (placeholders, missing criteria, malformed EARS,
vague wording, task-plan gaps) with error/warning/info levels and
`--strict` mode. Same bytes, same findings, every time.
- Approval state and document hashing: `spec approve` records the SHA-256 of
the exact approved file bytes in versioned sidecar state
(`.specbridge/state/specs/<name>.json`, schema 1.0.0). Approved Markdown
files are never rewritten.
- Stale approval detection: `spec status`, `spec list`, and `doctor` report
approved files that changed after approval and invalidate dependent
approvals in memory; re-approving repairs the hash and cascades honestly.
- Approval revocation: `spec approve --revoke` clears a stage and every
approval that depended on it, keeping all files.
- Existing Kiro workspace support: specs without SpecBridge state stay fully
usable (reported as `unmanaged`); the first successful approval initializes
sidecar state with `origin: existing-kiro-workspace`.
- `spec status` (new), plus extended `spec list` (mode/status/approval
health), `spec show` (`--state`, `--analysis`, `--status`), and `doctor`
(sidecar validation, orphan and stale state detection).
- No model or API key required for any v0.2 command; `.kiro` files carry no
SpecBridge metadata and the byte-identical no-op round trip is unchanged.

## 0.1.0

- Read-only Kiro compatibility: workspace detection, steering discovery,
spec discovery and classification, tolerant Markdown parsers.
- `doctor`, `steering list/show`, `spec list/show/context`, `compat check`.
- Line-preserving document model with a byte-identical no-op round-trip
guarantee and a surgical checkbox patcher.
- Deterministic drift-check library primitives, runner interfaces with an
offline mock runner, terminal/JSON/HTML report helpers.
100 changes: 79 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,22 +137,68 @@ Result: OK — workspace is ready for SpecBridge

## CLI

Working today (v0.1 — read-only, fully offline, no API key):
Working today (fully offline, no model, no API key):

| Command | What it does |
| --- | --- |
| `specbridge doctor` | Workspace health + compatibility report (never modifies files) |
| `specbridge doctor` | Workspace health, compatibility, and sidecar-state report |
| `specbridge steering list` | List steering files with inclusion modes |
| `specbridge steering show <name>` | Print a steering file |
| `specbridge spec list` | List specs with type, files, task progress, sidecar state |
| `specbridge spec show <name>` | Spec summary; `--file`, `--raw`, `--json` |
| `specbridge spec new <name>` | **v0.2** — create a Kiro-compatible spec from offline templates |
| `specbridge spec analyze <name>` | **v0.2** — deterministic structural/consistency analysis |
| `specbridge spec approve <name> --stage <s>` | **v0.2** — record (or `--revoke`) a stage approval with a byte-exact hash |
| `specbridge spec status <name>` | **v0.2** — workflow status, stage approvals, stale detection |
| `specbridge spec list` | List specs with type, mode, files, progress, approval health |
| `specbridge spec show <name>` | Spec summary; `--file`, `--raw`, `--state`, `--analysis`, `--status`, `--json` |
| `specbridge spec context <name>` | Agent-ready context (`--format json`, `--target claude-code`) |
| `specbridge compat check [name]` | Prove the byte-identical no-op round trip |

Planned commands (`spec new/analyze/approve/run/sync/verify/export`) are
registered, marked "(planned)" in `--help`, and exit with an honest error —
see the [roadmap](docs/roadmap.md). Every command supports `--help` with
examples.
Planned commands (`spec run/sync/verify/export`) are registered, marked
"(planned)" in `--help`, and exit with an honest error — see the
[roadmap](docs/roadmap.md). Every command supports `--help` with examples.

## Spec authoring and approval (v0.2)

Create specs, gate them through explicit approvals, and detect when an
approved document changes — all offline, no LLM anywhere:

```sh
specbridge doctor

specbridge spec new notification-preferences \
--mode requirements-first \
--description "Allow users to choose email and push notification preferences."

specbridge spec analyze notification-preferences --stage requirements

specbridge spec approve notification-preferences --stage requirements

specbridge spec status notification-preferences
```

How it fits together:

- **Templates, not generation.** `spec new` renders plain-Markdown templates
(feature: requirements-first / design-first / quick; bugfix: report + fix
design + plan). Generated placeholders like `<role>` are machine-
recognizable, so a fresh template cannot be approved by accident —
`spec analyze` reports them as errors until you write real content.
- **Approval is recorded, never inferred.** `spec approve` runs the
deterministic analyzer (errors block, warnings do not), then stores the
SHA-256 of the exact file bytes plus a timestamp in
`.specbridge/state/specs/<name>.json`. The Markdown file is never touched.
- **Stale approvals are caught.** Change one byte of an approved file and
`spec status` / `spec list` / `doctor` report `STALE_APPROVAL`, including
which dependent approvals are now invalid. Read-only commands never
rewrite state; re-approving is the explicit repair.
- **Existing Kiro projects just work.** Specs without SpecBridge state are
reported as `unmanaged` and stay fully usable; the first successful
approval initializes sidecar state (`origin: existing-kiro-workspace`).

Details: [spec authoring](docs/spec-authoring.md) ·
[deterministic analysis](docs/spec-analysis.md) ·
[approval workflow](docs/approval-workflow.md) ·
[sidecar state](docs/sidecar-state.md).

## Compatibility guarantees

Expand Down Expand Up @@ -195,13 +241,15 @@ guessing when none exists.
([examples/requirements-first-project](examples/requirements-first-project))
- **Design-first** — design → requirements → tasks
([examples/design-first-project](examples/design-first-project))
- **Quick** — all files generated in one step
- **Quick** — all files generated in one step, approvals in any order
([examples/quick-spec-project](examples/quick-spec-project))
- **Bugfix** — `bugfix.md` (Current/Expected/Unchanged Behavior…) + design + tasks
([examples/bugfix-spec-project](examples/bugfix-spec-project))

`specbridge spec new` (template mode, offline; runner mode optional) arrives
in Phase E.
All four are created offline by `specbridge spec new` (since v0.2) and gated
by `spec approve` — see [docs/approval-workflow.md](docs/approval-workflow.md).
Runner-assisted content generation is a separate, later phase and will always
be opt-in.

## Claude Code integration

Expand Down Expand Up @@ -269,35 +317,45 @@ Configuration lives in `.specbridge/config.json`
trusted project configuration, never from model output.
- Logs never include secrets or environment variables.

## Limitations (v0.1)
## Limitations (v0.2)

- Read-only: spec creation, approval, task execution, sync, and drift
verification CLI commands are not implemented yet (they fail honestly).
- Files that are not valid UTF-8 are read best-effort and never edited.
- Task execution, sync, drift-verification CLI, and export are not
implemented yet (they fail honestly; the drift library primitives exist).
- `spec new` renders offline templates only — no model writes content in
v0.2, by design. Runner-assisted generation is a future opt-in.
- Analysis is deterministic and structural; it cannot judge whether
requirements are *good*, only whether they are well-formed and complete.
- Workflow order cannot be inferred without sidecar state (reported as
`unknown` — by design).
`unknown` — by design); the first approval of an existing Kiro spec infers
it only when unambiguous.
- Files that are not valid UTF-8 are read best-effort and never edited.
- The GitHub Action is a preview and needs specbridge installed in the workflow.
- Setext (`===` underline) headings are not recognized as section boundaries;
the bytes are preserved regardless.

## Roadmap

Phase 1 (this release): read-only compatibility, doctor, listing, context,
round-trip proof. Next: spec workflow (E), runner adapters (F), task
execution with evidence (G), sync + drift verification (H), GitHub Action
(I), Claude Code skill polish (J), optional MCP server (K).
v0.1: read-only compatibility, doctor, listing, context, round-trip proof.
v0.2 (this release): offline spec authoring, deterministic analysis,
hash-based approvals, stale-approval detection. Next: runner adapters (F),
task execution with evidence (G), sync + drift verification (H), GitHub
Action (I), Claude Code skill polish (J), optional MCP server (K).
Full detail: [docs/roadmap.md](docs/roadmap.md).

## Documentation

[Architecture](docs/architecture.md) ·
[Kiro compatibility](docs/kiro-compatibility.md) ·
[Spec authoring](docs/spec-authoring.md) ·
[Spec analysis](docs/spec-analysis.md) ·
[Approval workflow](docs/approval-workflow.md) ·
[Sidecar state](docs/sidecar-state.md) ·
[Spec drift](docs/spec-drift.md) ·
[Runner adapters](docs/runner-adapters.md) ·
[Claude Code integration](docs/claude-code-integration.md) ·
[Migration from Kiro](docs/migration-from-kiro.md) (spoiler: there is none) ·
[Roadmap](docs/roadmap.md)
[Roadmap](docs/roadmap.md) ·
[Changelog](CHANGELOG.md)

## License and trademarks

Expand Down
95 changes: 95 additions & 0 deletions docs/approval-workflow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# Approval workflow (`spec approve`, `spec status`)

SpecBridge treats approval as an explicit, recorded decision — never an
inference. A stage is approved only when sidecar state says so; a file
existing (or looking finished) proves nothing.

```sh
specbridge spec approve notification-preferences --stage requirements
specbridge spec approve notification-preferences --stage design
specbridge spec approve login-timeout-fix --stage bugfix
specbridge spec approve notification-preferences --stage requirements --revoke
specbridge spec status notification-preferences
```

## Workflow state machines

Statuses advance as stages are approved. `spec status` shows the effective
status; `STALE_APPROVAL` appears when a recorded approval no longer holds.

| Workflow | Statuses |
| --- | --- |
| Feature, requirements-first | `REQUIREMENTS_DRAFT → REQUIREMENTS_APPROVED → DESIGN_DRAFT → DESIGN_APPROVED → TASKS_DRAFT → READY_FOR_IMPLEMENTATION` |
| Feature, design-first | `DESIGN_DRAFT → DESIGN_APPROVED → REQUIREMENTS_DRAFT → REQUIREMENTS_APPROVED → TASKS_DRAFT → READY_FOR_IMPLEMENTATION` |
| Quick | `READY_FOR_REVIEW → READY_FOR_IMPLEMENTATION` |
| Bugfix | `BUGFIX_DRAFT → BUGFIX_APPROVED → DESIGN_DRAFT → DESIGN_APPROVED → TASKS_DRAFT → READY_FOR_IMPLEMENTATION` |

In practice a `<STAGE>_APPROVED` status is transient: approving a stage
immediately unblocks the next one, whose draft status takes over. The
`_APPROVED` values remain valid stored states (hand-edited or reconstructed
state can express them).

## Prerequisites

| Workflow | Rule |
| --- | --- |
| requirements-first | requirements → design → tasks, strictly in order |
| design-first | design → requirements → tasks, strictly in order |
| quick | requirements and design in either order; tasks needs both |
| bugfix | bugfix → design → tasks (design-first bugfixes start with the fix design) |

An approval is blocked (exit `1`) when a prerequisite is unapproved **or**
approved-but-stale, when deterministic analysis of the stage reports errors
(unresolved placeholders included), or — for tasks — until every earlier
stage holds. Warnings never block. Usage mistakes (unknown spec, stage that
does not exist for the spec type) exit `2`.

## What approval records

Approval hashes the **exact file bytes** (SHA-256 — CRLF vs LF, BOMs, and
trailing newlines all count) and stores hash + timestamp in
`.specbridge/state/specs/<name>.json`. The Markdown file itself is never
rewritten, reformatted, or annotated.

## Stale approvals

Every read of a managed spec (`spec status`, `spec list`, `spec show`,
`doctor`, and the gates inside `spec approve`/`spec analyze`) re-hashes the
approved files:

- a changed file → effective status `modified-after-approval`
- approvals that depended on it → effectively stale too
- the overall effective status → `STALE_APPROVAL`

Read-only commands only *report* this — they never rewrite state. The repair
is an explicit re-approval:

```sh
specbridge spec approve <name> --stage requirements
```

Re-approving a stage whose content changed also invalidates dependent
approvals persistently (they were made against different content) and says
so. Re-approving identical bytes keeps them.

## Revocation

`--revoke` sets the stage back to draft, clears its hash and timestamp, and
invalidates every approval that depended on it. Files are never deleted or
modified; the command reports exactly which approvals were invalidated.

## Existing Kiro projects (unmanaged specs)

Specs created by Kiro have no SpecBridge state. They list, show, and analyze
normally; `spec status` reports `Approval state: unmanaged` with the
suggested first command. The first **successful** approval initializes
sidecar state:

- spec type is inferred from the files (`bugfix.md` → bugfix),
- workflow mode is inferred only when unambiguous: approving the document
stage first → requirements-first (the default in the absence of contrary
evidence); approving design first → design-first; approving tasks first is
refused with guidance,
- `origin` is recorded as `existing-kiro-workspace`.

A blocked approval initializes nothing — failed commands do not write.
15 changes: 10 additions & 5 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,18 @@ instead of duplicating logic.

| Package | Responsibility |
| --- | --- |
| `@specbridge/core` | Shared types, errors, workspace detection, path-safety guards, atomic writes, sidecar state (`.specbridge/`) |
| `@specbridge/core` | Shared types, errors, workspace detection, path-safety guards, atomic writes, hashing, versioned sidecar state (`.specbridge/`) |
| `@specbridge/compat-kiro` | Everything `.kiro`: line-preserving Markdown model, steering loader, spec discovery/classification, tolerant parsers, round-trip writer, workspace analysis, agent-context assembly |
| `@specbridge/workflow` | v0.2 authoring and approval engine: spec-name validation, offline templates, atomic spec creation, deterministic analyzers, workflow state machine, approval hashing + stale detection, sidecar audits |
| `@specbridge/drift` | Deterministic drift primitives: git-diff parsing, impact areas, requirement/task coverage, evidence storage, report assembly |
| `@specbridge/runners` | Model/agent adapters behind one `AgentRunner` interface (mock implemented; CLI runners detection-only in v0.1) |
| `@specbridge/runners` | Model/agent adapters behind one `AgentRunner` interface (mock implemented; CLI runners detection-only) |
| `@specbridge/reporting` | Terminal formatting, JSON report envelope, self-contained HTML rendering |
| `specbridge` (packages/cli) | Commander-based CLI wiring the above together |

Dependency direction (arrows = "may import"):

```
cli ──▶ compat-kiro ──▶ core
cli ──▶ workflow ──▶ compat-kiro ──▶ core
cli ──▶ reporting ──▶ core
drift ─▶ compat-kiro, core (cli wires drift in Phase H)
runners ─▶ core (cli wires runners in Phase F)
Expand All @@ -40,12 +41,16 @@ runners ─▶ core (cli wires runners in Phase F)
`error`) and the bytes are preserved. A file with zero recognized
structure is still a valid file.
4. **Deterministic by default.** Default commands are offline and produce
deterministic output (no timestamps or random ids in v0.1 reports), which
keeps them testable and CI-friendly. Model invocation is always explicit
deterministic output; analysis of the same bytes always yields the same
findings, and the only nondeterminism in sidecar state is the timestamp
(behind an injectable clock in tests). Model invocation is always explicit
and never required.
5. **Honest stubs.** Documented-but-unimplemented commands and runners exist,
are labeled "(planned)", and exit with `NOT_IMPLEMENTED` errors. Nothing
pretends to work.
6. **Approval is recorded, never inferred.** A stage is approved only when
sidecar state holds a hash of the exact approved bytes; read paths
recompute staleness in memory and never rewrite state.

## Data flow of a typical command

Expand Down
14 changes: 14 additions & 0 deletions docs/kiro-compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,20 @@ Strategy. British spellings and common variants match.
from files** — the layout is identical. SpecBridge reads it from sidecar
state when present and reports `unknown` otherwise. It never guesses.

## What SpecBridge writes (v0.2)

`spec new` is the only v0.2 command that writes into `.kiro`, and only to
create a **new** spec directory. Generated files are plain Markdown with LF
endings and a trailing newline — no front matter, no HTML comments, no
SpecBridge metadata of any kind — so Kiro opens them like any hand-written
spec. Existing spec directories are never overwritten (no `--force` exists),
and creation is atomic: a failure leaves no partial directory.

Approvals (`spec approve`) write **only** to `.specbridge/`; the approved
Markdown file is hashed byte-exactly and left untouched. `doctor` actively
scans for SpecBridge metadata inside `.kiro` files and reports any hit as an
error.

## The round-trip guarantee

For every file SpecBridge can decode as UTF-8:
Expand Down
Loading
Loading