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
33 changes: 22 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ Shared code (`packages/core`, `packages/webui`) is reused in two delivery
forms: a standalone tool (browser + local REST/WS server) and a VS Code
extension (Webview + direct `core` import in the extension host, without HTTP
where possible). See `docs/adr/0001-shared-core-two-delivery-targets.md` for
the full rationale and `openspec/specs/` (after the first `apply`) for the
detailed behavioral contract of each part.
the full rationale and `openspec/specs/` for the detailed behavioral
contract of each part.

```mermaid
flowchart TD
Expand Down Expand Up @@ -295,15 +295,26 @@ npm run start --workspace @openspec-ui/cli -- validate --cwd . --format text

1. Read `docs/adr/0001-*.md` — the architecture decisions and rejected
alternatives.
2. Start with `openspec/changes/execution-core/`: `server`, `webui`, and
`extension` depend on the contract defined there (the unified
command/event protocol and the security model).
3. Then `shared-ui`, followed by `standalone-app` and `vscode-extension` in
parallel.
4. For each change: run `openspec change validate --strict <id>` before
marking tasks done; run `openspec archive <id> --yes` only after a live
verification (see `operations.archive.guidance` in `openspec/config.yaml`) —
not earlier.
2. Read `openspec/README.md` — the runbook for this repository's governed
change workflow.
3. The four foundational changes (`execution-core`, `shared-ui`,
`standalone-app`, `vscode-extension`) are already implemented; find them
under `openspec/changes/archive/`. Run `openspec list` to see what is
currently active in `openspec/changes/`.
4. Every further repository modification — code, tests, docs, or tooling —
follows the same cycle:

```mermaid
flowchart LR
A["openspec/changes/&lt;id&gt;/<br/>proposal.md + tasks.md"] --> B["Implement tasks.md;<br/>tsc / eslint / vitest green"]
B --> C["openspec change validate<br/>--strict &lt;id&gt;"]
C --> D["openspec archive &lt;id&gt;<br/>(after live verification)"]
D --> E["openspec/changes/archive/<br/>+ openspec/specs/ updated"]
```

See `operations.apply.guidance` and `operations.archive.guidance` in
`openspec/config.yaml` for exactly what must be verified at each step —
archiving before live verification is out of process.

## Change Governance

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
schema: spec-driven
created: 2026-08-24
skip_specs: true
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
## Why

Raised directly during a repository review session on 2026-08-24 (the user's
own observation that OpenSpec's governed workflow is not understood by
newcomers): `README.md`'s "Getting Started" section (lines 294-306) still
tells a new reader to "Start with `openspec/changes/execution-core/`", then
`shared-ui`, `standalone-app`, `vscode-extension`. All four of those changes
are already implemented and archived under `openspec/changes/archive/`
(`2026-08-13-execution-core`, `2026-08-13-shared-ui`,
`2026-08-13-standalone-app`, `2026-08-13-vscode-extension`) — the directories
this section tells a reader to open no longer exist at that path. A newcomer
following this section hits a dead end, which actively works against the
goal of making the governed OpenSpec workflow understandable. The adjacent
"Architecture at a Glance" section (line 108) has the same staleness: it
describes `openspec/specs/` as populated "after the first `apply`", but the
first `apply` happened long ago and `openspec/specs/` already holds 14
capability specs.

## What Changes

- Rewrite `README.md`'s "Getting Started" section to describe the workflow
that actually applies today: the four foundational changes are already
done; every further repository modification (code, tests, docs, tooling)
follows the same governed cycle (propose → implement `tasks.md` → `openspec
change validate --strict <id>` → `openspec archive <id>` after live
verification), with a short diagram of that cycle and a pointer to `openspec
list` to see what is currently active.
- Drop the now-inaccurate "(after the first `apply`)" qualifier in
"Architecture at a Glance" (line 108).
- No change to any other README section, to `openspec/README.md`, or to
`openspec/config.yaml`.

## Capabilities

### New Capabilities

(none)

### Modified Capabilities

(none; this is a documentation-only change)

## Impact

- `README.md`
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
## 1. Rewrite the stale onboarding narrative

- [x] 1.1 Replace `README.md`'s "Getting Started" section: remove the
"start with `execution-core`" bootstrap sequence (already archived) and
describe the current propose/implement/validate/archive cycle, with a
pointer to `openspec list` for what is currently active.
- [x] 1.2 Remove the "(after the first `apply`)" qualifier in "Architecture
at a Glance" now that `openspec/specs/` is populated.

## 2. Verification

- [x] 2.1 Every path and command referenced in the rewritten section
actually exists / runs (`openspec/README.md`, `openspec/config.yaml`,
`openspec list`, `openspec change validate --strict`, `openspec archive`).
- [x] 2.2 `npm run lint:english` passes (no new Cyrillic introduced).
- [x] 2.3 Run `openspec change validate --strict refresh-readme-getting-started`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
schema: spec-driven
created: 2026-08-24
skip_specs: true
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
## Why

Found during a repository review session on 2026-08-24, confirmed by the
existing `npm run lint` output: `readStoredValue` in
`packages/webui/src/standalone-entry.tsx` is unused
(`@typescript-eslint/no-unused-vars`). Its sibling `writeStoredValue` calls
(lines persisting `cwd`/`changeDir` to `localStorage` on every change) are
therefore write-only — nothing ever reads the persisted values back. This
diverges from the equivalent extension bootstrap
(`packages/webui/src/extension-context.ts`'s `resolveInitialDashboardContext`,
consumed by `packages/webui/src/extension-entry.tsx`), which does restore
`cwd`/`changeDir` from storage as a fallback. In the standalone app, when the
`/api/workspace-root` sync fails (the existing `workspaceRootSyncError` state,
rendered at `standalone-entry.tsx`'s "Workspace root sync failed" note), the
`cwd`/`changeDir` inputs stay blank instead of falling back to the
last-known values already sitting in `localStorage`.

## What Changes

- Initialize the `cwd`/`changeDir` state in `StandaloneApp`
(`packages/webui/src/standalone-entry.tsx`) from
`readStoredValue(STORAGE_KEYS.cwd)` / `readStoredValue(STORAGE_KEYS.changeDir)`
instead of `""`, matching the fallback pattern already used by the
extension bootstrap.
- No change to `writeStoredValue` call sites, `STORAGE_KEYS`, or the
`/api/workspace-root` sync effect, which still overwrites these fields on a
successful sync — this only changes what the fields show before that sync
resolves or if it fails.

## Capabilities

### New Capabilities

(none)

### Modified Capabilities

(none; `openspec/specs/standalone-app/spec.md` does not document a
`localStorage` fallback scenario for `cwd`/`changeDir` — this restores
already-intended, already-shipped-but-inert behavior rather than changing a
specified one)

## Impact

- `packages/webui/src/standalone-entry.tsx`
- `packages/webui/package.json` (patch version bump)
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
## 1. Restore the localStorage fallback

- [x] 1.1 In `packages/webui/src/standalone-entry.tsx`, initialize `cwd` from
`readStoredValue(STORAGE_KEYS.cwd)` and `changeDir` from
`readStoredValue(STORAGE_KEYS.changeDir)`.
- [x] 1.2 Bump `packages/webui/package.json` to the next patch version.

## 2. Verification

- [x] 2.1 `npm run lint --workspace @openspec-ui/webui` no longer reports
`readStoredValue` as unused.
- [x] 2.2 `npm run typecheck` and `npm run test` pass workspace-wide.
- [x] 2.3 Run `openspec change validate --strict restore-standalone-workspace-fallback`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
schema: spec-driven
created: 2026-08-24
skip_specs: true
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
## Why

A repository review session on 2026-08-24 found that `CLAUDE.md`'s mandatory
English-only policy ("All code comments, descriptions, and markdown files in
this repository must be written in English only") is enforced by
`scripts/check-english.mjs` (`npm run lint:english`), but that script's
`scripts/english-policy-baseline.json` grandfathers in every line of
Cyrillic text that existed when the policy was introduced. The baseline held
635 lines across 73 tracked files — comments, JSDoc, and a handful of test
fixture strings — silently exempted from a policy that is supposed to apply
repo-wide. This is baseline debt: the check passes, but the policy is not
actually met for pre-existing content.

## What Changes

- Translate all 635 previously baselined lines, across all 73 affected
files, from Russian to English, preserving technical meaning exactly
(not a rewrite or a summary — a faithful translation of comments,
JSDoc, and the two archived-change markdown notes files).
- Where a baselined line's Russian text was itself the value under test
(`packages/core/src/change-state.test.ts`'s fixture markdown,
`packages/webui/src/markdown.test.tsx`/`SpecsSearch.test.tsx`/
`SpecsTree.test.tsx`/`RequirementView.test.tsx`/`ChangeRelations.test.tsx`'s
sample strings, `packages/core/src/security.test.ts`'s and
`packages/core/src/agent-runner.test.ts`'s prompt-injection fixture text),
translate the fixture content too and update the corresponding assertions
in the same file so the test keeps checking the same behavior. None of the
635 lines were left untouched — every baselined line was either a
translatable comment/JSDoc/doc line, or fixture text whose language is
incidental to what the test verifies (substring/shape checks, not a
byte-for-byte external contract). `packages/core/src/openspec-fixtures/show.json`
(explicitly exempt from scanning, a real `openspec` CLI capture) and
`scripts/check-english.test.mjs` (Cyrillic is the intentional subject of
that file's own scanner tests, marked `english-policy-allow`) were correctly
never baselined and were left as-is.
- `packages/core/src/agents/shared.ts`'s `commandInstruction()` also
returned Russian text for the `plan`/`implement`/`review`/`status`/
`cancel` command kinds — this is not a comment, it is the literal
instruction prefix sent to CLI agents (Claude/Copilot/Codex/Gemini/local
LLM) as part of the real prompt. The `list`/`show`/`validate` branches of
the same `switch` were already in English, so the function was internally
inconsistent before this change. Translated the remaining branches to
English to match, which is a small runtime behavior change (the literal
text sent to CLI agents for those five command kinds) beyond pure comment
translation — flagged explicitly here since it is not "no behavior change"
in the strictest sense, even though no test asserts the exact string and
all CLI agents understand English at least as well as Russian.
- Regenerate `scripts/english-policy-baseline.json` via
`node scripts/check-english.mjs --write-baseline` after all translations
were complete, so it now reflects the true remaining state (empty — no
Cyrillic remains in scanned files outside the two exempt cases above).

## Capabilities

### New Capabilities

(none)

### Modified Capabilities

(none; `.openspec.yaml` sets `skip_specs: true`. Primarily comment/doc/test-
fixture-text translation; the one exception —
`commandInstruction()`'s runtime prompt text — does not change any command
or event in the protocol defined in `packages/core`, so it does not rise to
a specified capability change)

## Impact

- `eslint.config.js`
- `openspec/changes/archive/2026-08-13-standalone-app/smoke-test-notes.md`
- `openspec/changes/archive/2026-08-13-vscode-extension/TEST-NOTES.md`
- `packages/core/src/agent-runner.ts`, `agent-runner.test.ts`
- `packages/core/src/agents/claude.ts`, `codex.ts`, `copilot.ts`, `gemini.ts`,
`local-llm.ts`, `registry.ts`, `shared.ts`, `shared.test.ts`
- `packages/core/src/browser.ts`, `change-state.ts`, `change-state.test.ts`,
`default-runners.ts`, `git.ts`, `index.ts`, `openspec.ts`,
`openspec.test.ts`, `protocol.ts`, `security.ts`, `security.test.ts`
- `packages/extension/scripts/build-options.mjs`
- `packages/extension/src/commands.ts`, `config.ts`, `extension.ts`,
`run-controller.ts`, `vitest.config.ts`
- `packages/extension/src/native/diff.ts`, `git.ts`, `open-doc.ts`
- `packages/extension/src/test-utils/vscode-mock.ts`
- `packages/extension/src/test/run.mjs`, `test/suite/extension.test.ts`,
`test/suite/index.ts`
- `packages/extension/src/webview/ai-panel.ts`
- `packages/server/scripts/build-client.mjs`, `client-build-options.mjs`
- `packages/server/src/cli.ts`, `index.ts`, `rest.ts`, `server.ts`,
`server.test.ts`, `static.ts`, `static.test.ts`, `websocket.ts`, `wire.ts`
- `packages/webui/src/components/AiPanel.tsx`, `ArchiveList.tsx`,
`ChangeDiff.tsx`, `ChangeRelations.tsx`, `ChangeRelations.test.tsx`,
`ChangesList.tsx`, `RequirementView.tsx`, `RequirementView.test.tsx`,
`SpecsSearch.tsx`, `SpecsSearch.test.tsx`, `SpecsTree.tsx`,
`SpecsTree.test.tsx`, `TasksChecklist.tsx`
- `packages/webui/src/extension-entry.tsx`, `index.ts`, `markdown.tsx`,
`markdown.test.tsx`, `standalone-entry.tsx`, `types.ts`
- `packages/webui/src/transport/contract.test.ts`,
`fetch-transport.ts`, `fetch-transport.test.ts`,
`message-bridge-transport.ts`, `types.ts`
- `scripts/english-policy-baseline.json` (regenerated to reflect zero
remaining Cyrillic lines in scanned files)
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
## 1. Translate `packages/core`

- [x] 1.1 Translate comments in `git.ts`, `index.ts`, `browser.ts`,
`default-runners.ts`, `change-state.ts`, `change-state.test.ts`,
`openspec.ts`, `openspec.test.ts`, `protocol.ts`.
- [x] 1.2 Translate `security.ts` (39 baselined lines: allowlist/cwd-sandbox
decision messages, the `prepareAgentContext` data/instructions header,
audit-log JSDoc) faithfully, preserving the security-invariant wording;
update `security.test.ts`'s matching assertions and its
prompt-injection fixture text to stay consistent with the translated
implementation strings it checks against.
- [x] 1.3 Translate `agent-runner.ts`/`agent-runner.test.ts`, including the
fallback failure-reason strings and the prompt-injection scenario text
in the test.
- [x] 1.4 Translate `agents/claude.ts`, `codex.ts`, `copilot.ts`, `gemini.ts`,
`local-llm.ts`, `registry.ts`, `shared.ts` (including the per-command
`commandInstruction()` prompt strings — a runtime behavior change, see
proposal.md's "What Changes"), `shared.test.ts`.

## 2. Translate `packages/server`

- [x] 2.1 Translate comments in `cli.ts`, `index.ts`, `websocket.ts`,
`wire.ts`, `rest.ts`, `static.ts`, `server.ts`, `static.test.ts`,
`server.test.ts`, `scripts/build-client.mjs`,
`scripts/client-build-options.mjs`.

## 3. Translate `packages/extension`

- [x] 3.1 Translate comments in `config.ts`, `commands.ts`, `extension.ts`,
`native/diff.ts`, `native/git.ts`, `native/open-doc.ts`,
`run-controller.ts`, `test-utils/vscode-mock.ts`, `webview/ai-panel.ts`.
- [x] 3.2 Translate comments in `test/suite/index.ts`,
`test/suite/extension.test.ts`, `test/run.mjs`, `vitest.config.ts`,
`scripts/build-options.mjs`.

## 4. Translate `packages/webui`

- [x] 4.1 Translate comments in `types.ts`, `transport/types.ts`, `index.ts`,
`transport/message-bridge-transport.ts`, `transport/fetch-transport.ts`,
`transport/fetch-transport.test.ts`, `transport/contract.test.ts`.
- [x] 4.2 Translate comments in `standalone-entry.tsx`,
`extension-entry.tsx`, `markdown.tsx`; translate `markdown.test.tsx`'s
sample strings and update its matching assertions.
- [x] 4.3 Translate `components/TasksChecklist.tsx`,
`components/RequirementView.tsx`, `components/RequirementView.test.tsx`
(sample requirement text + assertions), `components/SpecsSearch.tsx`,
`components/SpecsSearch.test.tsx` (fixture specs + query strings +
assertions), `components/SpecsTree.tsx`, `components/SpecsTree.test.tsx`
(fixture specs), `components/ChangesList.tsx`, `components/ChangeDiff.tsx`,
`components/ChangeRelations.tsx`, `components/ChangeRelations.test.tsx`
(fixture proposal text + assertions), `components/ArchiveList.tsx`,
`components/AiPanel.tsx`.

## 5. Repo-level files

- [x] 5.1 Translate `eslint.config.js`'s comment.
- [x] 5.2 Translate
`openspec/changes/archive/2026-08-13-standalone-app/smoke-test-notes.md`
and `openspec/changes/archive/2026-08-13-vscode-extension/TEST-NOTES.md`
in full (both are historical live-test notes from archived changes; no
functional content, safe to translate wholesale).

## 6. Baseline and verification

- [x] 6.1 Confirm no file was skipped: `packages/core/src/openspec-fixtures/show.json`
stays untouched (explicitly exempt from scanning — a captured real
`openspec` CLI response) and `scripts/check-english.test.mjs` stays
untouched (its Cyrillic lines are the intentional subject of the
scanner's own tests, marked `english-policy-allow`, and were never
baselined in the first place).
- [x] 6.2 Regenerate `scripts/english-policy-baseline.json` via
`node scripts/check-english.mjs --write-baseline` after all translations
above are complete.
- [x] 6.3 `npm run lint:english` passes (0 violations, empty baseline).
- [x] 6.4 `npm run typecheck` passes workspace-wide.
- [x] 6.5 `npm run test` passes workspace-wide (test:english + all package
test suites — 435 tests total, 0 failures).
- [x] 6.6 `openspec change validate --strict translate-legacy-comments-to-english`
passes.
- [x] 6.7 Reviewed independently (diff read for the highest-risk files —
`security.ts`/`security.test.ts`, `agents/shared.ts`, a sample
fixture+assertion pair in `SpecsSearch.test.tsx`) and re-ran
`typecheck`/`lint`/`test` from a clean checkout of the merged result, not
just trusting the translating agent's self-report.
Loading
Loading