silvermoon 0.2.1 → 0.3.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -30,8 +30,8 @@ npx skills add <path-to-running-silvermoon>/skills --skill silvermoon --agent un
30
30
 
31
31
  If the repository root contains `package.json`, Silvermoon requires valid JSON
32
32
  and an exact `devDependencies.silvermoon` value of `^<running-version>`.
33
- Follow the setup report's package-manager-specific command, then install the
34
- root dependencies and register the project-local canonical skill:
33
+ Follow all commands in the setup report in order; then register the
34
+ project-local canonical skill:
35
35
 
36
36
  ```sh
37
37
  npx skills add ./node_modules/silvermoon/skills --skill silvermoon --agent universal --yes --copy
@@ -125,6 +125,14 @@ the resolved content language and can therefore differ from `outputLanguage`.
125
125
  Without a temporary override, Chinese content tags use `zh-CN` output and all
126
126
  other content tags use the built-in `en-US` output.
127
127
 
128
+ The resolved content language applies to natural-language content throughout
129
+ `Idea.md`, `Implementation.md`, `Deployment.md`, same-world supporting files,
130
+ and `ledger.md`. Canonical headings, stable IDs, paths, CLI options, and schema
131
+ fields are machine contracts and remain unchanged. `create-idea` localizes
132
+ built-in English and Chinese scaffolds; for another canonical language tag its
133
+ next step names the fallback template language and requires the Agent to
134
+ replace every natural-language placeholder before continuing.
135
+
128
136
  ## Inspect The Local Idea Inventory
129
137
 
130
138
  Use the dedicated read-only query when the question is which ideas exist,
@@ -153,8 +161,8 @@ fetches or contacts the configured primary. Staged, unstaged, and untracked
153
161
  idea changes are therefore visible when they form a valid snapshot. Invalid
154
162
  query arguments fail with exit `2` before repository or trace access; an
155
163
  untrusted project or layout exits `1` instead of returning a partial list.
156
- The command has no temporary `--language` option and uses the project's
157
- resolved output language.
164
+ Use `--language en|en-US|zh|zh-CN` to override only the output language for
165
+ this invocation; without it, the project's resolved output language is used.
158
166
 
159
167
  ## Create The First Idea
160
168
 
@@ -191,13 +199,17 @@ Then ask what comes next with the generated ULID or an exact unique alias:
191
199
  silvermoon whats-next <idea>
192
200
  ```
193
201
 
194
- Default Markdown renders only the self-contained response. Add `--json` when a
195
- programmatic consumer needs the complete
196
- `intention / observation / actions / response` report. Read every problem and
197
- execute applicable `response.nextSteps` in order; `actions` contains only
198
- side effects Silvermoon already attempted. Run the same command again only
199
- after an expected repository change, an unexpected input change, or a newly
200
- arrived external result.
202
+ The default human audience opens the bundled `tui-md` view only when stdin and
203
+ stdout are both TTYs; press `q`, `Esc`, or `Ctrl+C` to exit. Pipes,
204
+ redirections, and other non-TTY uses receive raw Markdown. Agents should add
205
+ `--audience agent` to receive the same raw response Markdown even when attached
206
+ to a TTY. Add `--json` when a programmatic consumer needs the complete
207
+ `intention / observation / actions / response` report; an explicitly supplied
208
+ `--audience` cannot be combined with `--json`. Read every problem and execute
209
+ applicable `response.nextSteps` in order; `actions` contains only side effects
210
+ Silvermoon already attempted. Run the same command again only after an expected
211
+ repository change, an unexpected input change, or a newly arrived external
212
+ result.
201
213
 
202
214
  ## Make Decisions Explicit
203
215
 
@@ -15,31 +15,108 @@ Use the smallest check that covers a change:
15
15
 
16
16
  ```sh
17
17
  pnpm sync:skills # refresh the generated universal skill copy
18
- pnpm lint:markdown # Markdown lint and link checks
19
- pnpm test # fast unit and repository contract tests
18
+ pnpm check:sanity # offline pure logic and lightweight contracts
19
+ pnpm check:commit # worktree tests plus staged metadata validation
20
+ pnpm lint:markdown # Markdown lint (contract tests check links)
21
+ pnpm test # complete unit/runtime and repository contracts
20
22
  pnpm test:integration # real filesystem and Git behavior
21
23
  pnpm test:e2e # packed and installed CLI behavior
22
24
  pnpm check # complete release-grade validation
23
- pnpm check:skills # skill discovery and structure
25
+ pnpm check:release # same complete release-grade validation
26
+ pnpm check:skills:local # local skill copy consistency, no discovery
27
+ pnpm check:skills # local consistency and external skill discovery
24
28
  ```
25
29
 
30
+ ## Validation tiers
31
+
32
+ | Scenario | Responsibility |
33
+ | --- | --- |
34
+ | Edit / Agent iteration | `check:sanity`: CLI syntax, pure unit tests, schema and API contracts; add change-specific tests |
35
+ | Before commit | `check:commit`: sanity, local contracts and Markdown, skill consistency, Git/CLI smoke, whitespace, staged Silvermoon metadata |
36
+ | Ordinary CI | Unconditional sanity then complete unit/runtime on Ubuntu/Windows/macOS, Node 22/24; complete contracts and integration, static checks and skill discovery |
37
+ | Before delivery / release | `check` or `check:release`: every release-grade gate including package contents, installed-package E2E and external discovery |
38
+ | After publication | The existing release workflow's `verify-npm-release.mjs`: registry identity, integrity, provenance, README and CDN |
39
+
40
+ `test:unit` includes `test/runtime` so moving filesystem, Git and terminal
41
+ tests out of sanity does not remove matrix coverage. `check:quick` retains its
42
+ original syntax plus complete unit/runtime and contract meaning, not a new
43
+ sanity alias. No assertions are duplicated into a second suite. The sanity
44
+ worker guard rejects real child processes and network I/O; it does not block
45
+ the Node test runner from creating workers. Terminal integration stays in
46
+ runtime, outside sanity.
47
+
48
+ Each CI matrix job runs the actual `pnpm check:sanity` entrypoint before the
49
+ complete unit/runtime suite. Passing `test:unit` alone does not prove the
50
+ sanity I/O boundary: it intentionally permits runtime tests. Tests that call
51
+ real Git, even only to compare pure logic with Git's behavior, belong in
52
+ `test/runtime`, not `test/unit`. Keep their assertions and platform coverage
53
+ when splitting mixed-cost files; never disable the sanity guard to admit them.
54
+
55
+ `check:commit` always prints its scope: tests validate the **worktree**, while
56
+ `silvermoon check --staged` validates **staged Silvermoon metadata only**.
57
+ With partial staging these are different candidates; a passing command does
58
+ not prove staged code passed the tests. Align index and worktree and rerun
59
+ before claiming exact-candidate evidence. The command never stages, stashes,
60
+ installs a hook or changes Git configuration.
61
+
62
+ CI adds package contents and installed-package E2E unless every changed path
63
+ is known idea metadata under `.silvermoon/ideas/<ULID>/`. Everything else,
64
+ including shipped docs, dependencies/locks, CLI entries, skills, tests,
65
+ scripts, workflows and unknown paths, requires package validation. The
66
+ selector uses the full base/head diff and both endpoints of renames; missing
67
+ history, malformed or empty changes conservatively require validation with
68
+ an explicit reason. Core jobs never use path filtering. Run
69
+ `node scripts/ci-package-risk.mjs --full` to inspect the full decision;
70
+ `workflow_dispatch` executes the full CI set, and local `check:release` always
71
+ executes package/E2E regardless of the diff.
72
+
73
+ `check:skills:local` needs no external discovery tool.
74
+ `check:skills:discover` runs `npx skills add . --list` and can use the network;
75
+ `check:skills` runs both in order. Missing tools and failed external checks
76
+ are errors, not successful skips. No validation entrypoint publishes npm.
77
+
26
78
  `pnpm check` runs the independent release-grade checks concurrently and waits
27
79
  for all of them before reporting every failure. Run the narrower commands above
28
80
  while iterating, then use `pnpm check` before delivery.
29
81
 
82
+ Each full check reports `CHECK_DURATION` for every gate and `CHECK_TOTAL` for
83
+ the complete run. These values use a monotonic clock and are diagnostic, not
84
+ machine-independent budgets. To compare performance, record the Node.js and
85
+ pnpm versions and test counts, run `pnpm check` once to warm the checkout, then
86
+ repeat it five times and compare the median under the same machine and checkout
87
+ conditions. Keep each sample; do not count network, queueing, or cache
88
+ fluctuations in installed-package smoke tests as code performance gains.
89
+
30
90
  Edit the canonical skill only under `skills/silvermoon`, then run
31
91
  `pnpm sync:skills`. The checked-in `.agents/skills/silvermoon` directory is a
32
92
  generated copy so repository skill discovery works without symbolic-link
33
93
  support. `pnpm check:skills` rejects a stale or manually edited copy.
34
94
  The repository-only publish skill is maintained directly under
35
95
  `.agents/skills/publish`; it is not part of the generated copy or npm package.
36
- For documentation and skill changes, run `pnpm lint:markdown`,
37
- `pnpm check:skills`, and `node --test test/contract/skill.test.mjs`.
96
+ For documentation and skill iteration, run `pnpm lint:markdown`,
97
+ `pnpm check:skills:local`, and relevant contract tests; run external
98
+ `pnpm check:skills` before skill delivery.
38
99
 
39
- Run `pnpm check` after CLI, schema, repository model, release, or skill changes.
100
+ Run `pnpm check` before delivery of CLI, schema, repository model, release,
101
+ or skill changes, not after every edit.
40
102
  Documentation work must also preserve Markdown links, package contents,
41
103
  installed-package rendering surfaces, and `git diff --check`.
42
104
 
105
+ ## GitHub Actions Dependencies
106
+
107
+ Every external action under `.github/workflows` is pinned to a full commit SHA
108
+ with its exact semantic version in an inline comment. Never replace a pin with
109
+ a movable major tag. Dependabot checks the `github-actions` ecosystem weekly
110
+ and proposes reviewable SHA/version updates; do not auto-merge those PRs.
111
+ Review the upstream release and action ownership, then require the complete CI
112
+ gate before merging.
113
+
114
+ The branch ruleset depends only on the stable `Required checks` job name. That
115
+ aggregate job fails unless package-risk selection, unit, contract, and
116
+ integration jobs succeed, and it requires package validation to succeed when
117
+ risk selection enables it. Keep this name and fail-closed behavior synchronized
118
+ with `.github/rulesets/main.json`.
119
+
43
120
  ## Documentation Ownership
44
121
 
45
122
  - [Getting Started](./getting-started.md) owns installation, configuration,
@@ -64,7 +64,8 @@ the release namespace.
64
64
  ## Publish a version
65
65
 
66
66
  1. Update the selected package's `version` in its committed `package.json`.
67
- 2. Run `pnpm install --frozen-lockfile` and `pnpm check`. The complete check
67
+ 2. Run `pnpm install --frozen-lockfile` and `pnpm check` (or `pnpm check:release`).
68
+ Neither validation command publishes a package. The complete check
68
69
  includes unit, contract, integration, package contents, installed-package
69
70
  E2E, and skill discovery.
70
71
  3. Merge the version change to `main`; do not tag an unmerged branch or local
@@ -95,9 +96,16 @@ The [`publish-npm.yml`](../.github/workflows/publish-npm.yml) workflow then:
95
96
  3. runs the allowlisted release planner and confirms the version is absent
96
97
  from npm, or records that an exact-version rerun must skip publication;
97
98
  4. runs `pnpm test:unit`, `pnpm test:contract`, `pnpm test:integration`, and
98
- `pnpm check:skills`;
99
+ `pnpm check:skills`, Markdown/whitespace and checked-out Silvermoon snapshot
100
+ validation, all unconditionally;
99
101
  5. creates an isolated `git archive` staging tree and generates commit-pinned
100
102
  English and Chinese package READMEs without changing the tagged checkout;
103
+ the repository READMEs use canonical `./assets/...` image paths so branch,
104
+ pull-request, and local previews show the current checkout, while staging
105
+ converts those images to release-commit-pinned jsDelivr URLs and converts
106
+ ordinary relative document links to commit-pinned GitHub blob URLs;
107
+ repository artwork remains available at those immutable URLs but is
108
+ excluded from the npm tarball;
101
109
  6. records the tagged commit as `gitHead` and the canonical `README.md` content
102
110
  in the isolated package manifest, creates one tarball, records its path,
103
111
  SHA-256, npm shasum, registry integrity, and complete file list, then passes
@@ -114,8 +122,12 @@ The [`publish-npm.yml`](../.github/workflows/publish-npm.yml) workflow then:
114
122
 
115
123
  The post-publication verifier requires the exact version and dist-tag, matching
116
124
  tarball and registry `gitHead`, registry integrity and tarball bytes, both
117
- tarball READMEs, npm publish and SLSA provenance attestations, tagged Git
118
- commit, and commit-pinned jsDelivr SVG responses to match the candidate.
125
+ tarball READMEs, MIT license, homepage, bugs and repository metadata, npm
126
+ publish and SLSA provenance attestations, tagged Git commit, and commit-pinned
127
+ jsDelivr SVG responses to match the candidate.
128
+ README generation rejects traversal, non-canonical paths, and relative resources
129
+ outside the approved `./assets/...` image namespace rather than guessing a
130
+ published destination.
119
131
  Releases on the `latest` dist-tag additionally require npm's package-level
120
132
  README to match the candidate; prerelease channels leave that `latest` package
121
133
  page state unchanged. A successful run prints `VERIFY_NPM_RELEASE_OK` with the
@@ -126,6 +138,23 @@ Release runs are serialized within this repository. The registry preflight and
126
138
  publisher could still win that interval; npm then atomically rejects the
127
139
  duplicate publication without replacing the existing version.
128
140
 
141
+ ### GitHub Release
142
+
143
+ Prepare release notes in the repository before creating the immutable tag.
144
+ After the trusted-publishing workflow succeeds and its verifier proves the npm
145
+ result, create the GitHub Release from the already-existing tag. For `0.3.0`:
146
+
147
+ ```sh
148
+ gh release create npm/silvermoon/v0.3.0 \
149
+ --verify-tag \
150
+ --title "Silvermoon 0.3.0" \
151
+ --notes-file .github/release-notes/0.3.0.md
152
+ ```
153
+
154
+ Do not let a release command create, move, or replace the tag. The GitHub
155
+ Release, npm version, provenance, changelog, and release notes must resolve to
156
+ the same commit before deployment acceptance.
157
+
129
158
  ## Failure behavior
130
159
 
131
160
  Publication stops before `npm publish` when the tag is malformed, the release
@@ -22,7 +22,7 @@ The shared observation exposes the resolved content preference as
22
22
  `configuration.preferredLanguage` and the built-in rendering locale as
23
23
  `outputLanguage`. Response next steps use the content preference for world
24
24
  entries, same-world supporting artifacts, and the ledger. A caller may use
25
- `--language en-US|zh-CN` to override only Silvermoon-owned output for one
25
+ `--language en|en-US|zh|zh-CN` to override only Silvermoon-owned output for one
26
26
  `whats-next` invocation. Commands, identifiers, schema fields, protocol
27
27
  markers, and verbatim tool output retain their original form.
28
28
 
@@ -103,8 +103,8 @@ For `create-idea`, `--language` normalizes any valid BCP 47 tag and writes it
103
103
  to the new idea's `status.yaml` as a persistent content-language preference.
104
104
  Without the option, creation writes no language field and the idea dynamically
105
105
  inherits project, user, or `en-US` defaults. This is distinct from the
106
- non-persistent `en-US|zh-CN` output override accepted by `whats-next` and
107
- `check`.
106
+ non-persistent `en|en-US|zh|zh-CN` output override accepted by `list-ideas`,
107
+ `whats-next`, and `check`.
108
108
 
109
109
  The generated files remain untracked for review. Complete `Idea.md`, optionally
110
110
  add a concise unique alias, inspect every path, and publish the initial idea
@@ -118,9 +118,13 @@ unpublished local candidate, and never treat publication as approval.
118
118
  ## Follow One Report
119
119
 
120
120
  Treat `intention`, `observation`, `actions`, and `response` as one immutable
121
- report for every command. Default output renders only `response`; `--json`
122
- serializes all four projections and retains `actions: []` when no side effect
123
- was attempted. Actions are historical facts. Future work appears only in
121
+ report for every command. The implicit `human` audience uses the bundled
122
+ `tui-md` view only when both stdin and stdout are TTYs; `q`, `Esc`, and
123
+ `Ctrl+C` exit the view. Human pipelines and redirections receive raw response
124
+ Markdown. `--audience agent` always emits that raw Markdown without TUI control
125
+ sequences. `--json` serializes all four projections and retains `actions: []`
126
+ when no side effect was attempted; an explicit `--audience` conflicts with
127
+ `--json`. Actions are historical facts. Future work appears only in
124
128
  `response.nextSteps`.
125
129
 
126
130
  Project setup takes precedence over repository synchronization, which takes
@@ -195,7 +199,7 @@ returned. Exit status `0` means the chosen project snapshot is valid; `1`
195
199
  means invalid or unavailable and must block the commit; `2` means invalid CLI
196
200
  usage. Do not treat the existence of a report as permission to commit.
197
201
 
198
- `check --language en-US|zh-CN` changes only Silvermoon-owned report framing.
202
+ `check --language en|en-US|zh|zh-CN` changes only Silvermoon-owned report framing.
199
203
  It is orthogonal to every check target and never changes the selected snapshot,
200
204
  validation conclusion, problems, or exit status.
201
205
 
package/docs/reference.md CHANGED
@@ -112,13 +112,24 @@ inherited and is never written back. Dialogue project status presents this
112
112
  effective value as `content language` (`内容语言`).
113
113
 
114
114
  Every command observation also exposes an independent `outputLanguage`.
115
- Silvermoon's built-in output locales are exactly `en-US` and `zh-CN`.
116
- `whats-next --language <tag>` and `check --language <tag>` normalize casing
117
- before enforcing that allowlist, apply only to the current invocation, and
118
- take display precedence over content language. Without an explicit output
119
- override, content tags beginning with `zh` select `zh-CN`; every other content
120
- tag selects `en-US`. Output selection never writes configuration or idea
121
- status.
115
+ Silvermoon's built-in output locales are `en-US` and `zh-CN`; short aliases
116
+ `en` and `zh` are accepted and normalize to those locales.
117
+ `list-ideas`, `whats-next`, and `check` accept `--language
118
+ <en|en-US|zh|zh-CN>`, normalize casing, and apply the override only to the
119
+ current invocation. It takes display precedence over content language. Without
120
+ an explicit output override, content tags beginning with `zh` select `zh-CN`;
121
+ every other content tag selects `en-US`. Output selection never writes
122
+ configuration or idea status.
123
+
124
+ The effective content language governs natural-language prose, comments,
125
+ short titles, and placeholders in all three world contracts, their same-world
126
+ supporting files, and `ledger.md`. Canonical headings, stable IDs, paths, CLI
127
+ options, and schema fields remain unchanged. `create-idea` provides localized
128
+ scaffolds for built-in English and Chinese templates; for another canonical
129
+ BCP 47 tag it reports the explicit fallback template language and requires the
130
+ Agent to replace natural-language placeholders with the effective content
131
+ language. Selected-idea `whats-next` instructions repeat the effective content
132
+ language even when a temporary output-language override is active.
122
133
 
123
134
  State is derived in order:
124
135
 
@@ -130,13 +141,27 @@ State is derived in order:
130
141
  `deploymentRevision`.
131
142
  5. `completed` when all three revisions match.
132
143
 
144
+ ## Experimental JavaScript Package API
145
+
146
+ The package root export is available for programmatic reuse, but remains
147
+ experimental for every Silvermoon `0.x` release. A minor release before
148
+ `1.0.0` may add, remove, rename, or change exported JavaScript functions and
149
+ classes without a deprecation period. Patch releases are intended for
150
+ compatible fixes. Consumers that import from `silvermoon` should pin the exact
151
+ package version and review the changelog before upgrading.
152
+
153
+ This boundary applies only to the root JavaScript export. The CLI, versioned
154
+ JSON Schemas, trace versions, and repository file contracts keep their own
155
+ documented compatibility rules. The package does not yet promise stable
156
+ TypeScript declarations or a stable `1.0.0` JavaScript API.
157
+
133
158
  ## Public Commands
134
159
 
135
160
  ```sh
136
- silvermoon list-ideas [--state <state>] [--all] [--query <text>] [--created-since <RFC3339>] [--created-before <RFC3339>] [--sort <newest|oldest>] [--limit <positive-integer>] [--trace <file.trace.jsonl>]
137
- silvermoon whats-next [idea] [--language <en-US|zh-CN>] [--trace <file.trace.jsonl>]
138
- silvermoon create-idea [--language <tag>] [--trace <file.trace.jsonl>]
139
- silvermoon check [--remote | --commit <revision> | --staged | --worktree] [--language <en-US|zh-CN>] [--trace <file.trace.jsonl>]
161
+ silvermoon list-ideas [--state <state>] [--all] [--query <text>] [--created-since <RFC3339>] [--created-before <RFC3339>] [--sort <newest|oldest>] [--limit <positive-integer>] [--language <en|en-US|zh|zh-CN>] [--audience <human|agent>] [--trace <file.trace.jsonl>]
162
+ silvermoon whats-next [idea] [--language <en|en-US|zh|zh-CN>] [--audience <human|agent>] [--trace <file.trace.jsonl>]
163
+ silvermoon create-idea [--language <tag>] [--audience <human|agent>] [--trace <file.trace.jsonl>]
164
+ silvermoon check [--remote | --commit <revision> | --staged | --worktree] [--language <en|en-US|zh|zh-CN>] [--audience <human|agent>] [--trace <file.trace.jsonl>]
140
165
  ```
141
166
 
142
167
  Every valid invocation starts one ordered domain-message stream with
@@ -211,11 +236,40 @@ neither field. The public observation intentionally omits content so the
211
236
  response is the only rendered payload while still remaining a deterministic
212
237
  projection.
213
238
 
214
- Default Markdown renders only `response`, never the intention, observation, or
215
- action history. It begins with the answer, then includes only relevant idea
216
- references, inventory details, validation details, problems, next steps, and
217
- blockquoted guidance. `--json` serializes the four projections from the same
218
- domain stream; there is no YAML output or second reasoning path. A trustworthy
239
+ Audience selection is independent of report construction. When `--audience` is
240
+ omitted, the audience is `human`: stdin and stdout must both be TTYs for the
241
+ bundled `tui-md` view to start. That view supports scrolling; drag to select
242
+ text and press `y` to copy it. On local Windows terminals, the built-in
243
+ PowerShell clipboard command is used when the terminal clipboard protocol is
244
+ unavailable. Copy feedback temporarily replaces the shortcut hint, using a
245
+ muted green for success or amber for problems, then clears after about three
246
+ seconds without shifting the document. If copying fails, the
247
+ view displays a diagnostic; terminal-native selection may be available with
248
+ Shift+drag. Exit with `q`, `Esc`, or `Ctrl+C`.
249
+ The TUI document uses the available terminal width rather than a fixed
250
+ 100-column limit. Tables that fit the view measure Chinese characters by
251
+ terminal cells so wide screens do not wrap otherwise-fitting columns; tables
252
+ too wide for the screen retain horizontal navigation.
253
+ If either stream is not a TTY, human output is raw
254
+ Markdown. `--audience agent` always emits raw Markdown without TUI control
255
+ sequences. On Windows, TUI frames use Node's terminal stream for UTF-8 output
256
+ without changing the console code page. Both Markdown paths render only
257
+ `response`, never the intention, observation, or action history, and derive their
258
+ content from the same command report. They begin with the answer, then include
259
+ only relevant idea references,
260
+ inventory details, validation details, problems, next steps, and blockquoted
261
+ guidance. Text reports render problems as a Markdown table. `list-ideas` and
262
+ `whats-next` active choices use the same `Alias / ID`, state, created, title
263
+ columns: an alias replaces the ID in that column when present. Structured
264
+ dates in these lists and any displayed creation-time filter bounds are short
265
+ relative times (just now, minutes, hours, days); after seven days they show a
266
+ local calendar date without a time.
267
+ Future dates are labelled as upcoming, not as elapsed. JSON retains exact
268
+ UTC timestamps and all filtering still uses the exact values.
269
+
270
+ `--json` without an explicitly selected audience serializes the four
271
+ projections from the same domain stream; explicit `--json --audience ...` is a
272
+ usage error. There is no YAML output or second reasoning path. A trustworthy
219
273
  blocked report still exits `0` for `whats-next` and `create-idea`.
220
274
  `list-ideas` exits `0` only for a trustworthy inventory (including an empty
221
275
  result) and exits `1` for setup or layout unavailability. `check` exits `0`
@@ -235,15 +289,53 @@ monotonic `sequence`, and UTC timestamp:
235
289
  - `channel: "telemetry"` records paired `span-start` and `span-end` events,
236
290
  parent span IDs, monotonic `durationMs`, and success or error status.
237
291
 
238
- Action telemetry carries the corresponding action ID. Trace projection never
239
- includes guidance or file content, Git arguments/stdout/stderr, environment
240
- data, credentials, tokens, or unbounded error text. Turning trace off, replacing
241
- the domain sink with a no-op, or deleting every telemetry event does not change
242
- the domain stream or final report. The path is relative to the caller's working
243
- directory when not absolute. Events are buffered so a trace inside the
244
- repository cannot affect that invocation's worktree observation. The file is
245
- written after measured command work finishes and uses exclusive creation, so
246
- an existing normalized target is never overwritten.
292
+ The root `command.*` span starts after Commander has parsed the invocation and
293
+ covers domain dispatch through JSON or Markdown output. Its safe attributes
294
+ identify the renderer; executable invocations also include the monotonic
295
+ `bootstrapDurationMs` from process entry through dispatch. Non-interactive
296
+ output has a child `output.render` span. Human TUI rendering remains outside
297
+ the command span so waiting for input is not reported as automated command
298
+ work.
299
+
300
+ Action telemetry carries the corresponding action ID. All production
301
+ subprocesses use the trace-aware runner. Git subprocesses emit `git.command`
302
+ with only the subcommand, argument count, network classification, exit code,
303
+ and signal; neither Git arguments nor process input or output are recorded.
304
+ Trace projection never includes guidance or file content, environment data,
305
+ credentials, tokens, or unbounded error text. Turning trace off, replacing the
306
+ domain sink with a no-op, or deleting every telemetry event does not change the
307
+ domain stream or final report.
308
+
309
+ The path is relative to the caller's working directory when not absolute.
310
+ Events are buffered so a trace inside the repository cannot affect that
311
+ invocation's worktree observation. After the command span ends, a root
312
+ `trace.flush` span covers exclusive file creation and the durable write of all
313
+ preceding events; its final span-end record is appended as the trace trailer.
314
+ Flush and close failures are returned as command errors. An existing normalized
315
+ target is never overwritten.
316
+
317
+ ### Reproducible performance traces
318
+
319
+ Performance comparisons use a disposable clean clone pinned to one commit and
320
+ tree on the same machine and storage volume. When a command needs the primary,
321
+ map the canonical primary URL to a local bare repository with Git `insteadOf`;
322
+ do not replace the configured URL or skip the command's normal fetch. Prove the
323
+ clone clean before and after every sample. For `create-idea`, remove only the
324
+ exact idea path returned by that sample, then prove the clone clean again.
325
+
326
+ Benchmark this matrix: default and `--all` inventory; bare and selected aligned
327
+ navigation; creation; and HEAD, staged, worktree, and remote checks. Run one
328
+ unrecorded warm-up followed by five independent JSON invocations with unique
329
+ trace files. Retain every measured sample rather than removing network, cache,
330
+ or timing outliers.
331
+
332
+ Use the matching `command.*` span-end duration as total command work. Network
333
+ duration is the sum of child `git.command` span-end durations whose safe
334
+ `network` attribute is `true`; subtract that sum from each individual total
335
+ before calculating a non-network median. Report all five totals, all five
336
+ network/non-network decompositions where applicable, median, minimum, maximum,
337
+ Git process count, `snapshot.materialize*` count, and inventory candidate/title
338
+ read counts. Keep raw traces outside the measured repository.
247
339
 
248
340
  Unsupported output locales, empty values, invalid BCP 47 tags, and invalid
249
341
  `list-ideas` filters are usage errors with exit status `2`, before repository
@@ -260,12 +352,16 @@ Observations are discriminated by command intent and `state`:
260
352
  safety checks fail. It includes `root`, `version`, `configuration`, and at
261
353
  least one `problem`, but no idea inventory or remote synchronization facts.
262
354
  - Bare `whats-next` returns `navigation-ready` with `ideas.counts` and
263
- `ideas.activeIdeas` (possibly empty). It never selects a candidate.
355
+ `ideas.activeIdeas` (possibly empty). Each active item includes `id`,
356
+ lifecycle `state`, UTC `createdAt`, and optional alias/title read from the
357
+ current idea document; missing titles render as `-`. It never selects a
358
+ candidate.
264
359
  - Selected `whats-next` returns `idea-selected` with only `selectedIdea`
265
360
  (`id`, optional `alias`, lifecycle `state`), including terminal ideas.
266
- Unknown selectors return `idea-not-found` with `candidates`, not a
267
- fabricated selected idea. An actionable selection may also contain
268
- snapshot-bound guidance provenance; captured content is in the response.
361
+ Unknown selectors return `idea-not-found` with the same enriched active
362
+ `candidates`, not a fabricated selected idea. An actionable selection may
363
+ also contain snapshot-bound guidance provenance; captured content is in
364
+ the response.
269
365
  - `phase-guidance-invalid` means command readiness reached the current
270
366
  actionable phase, but that phase's optional file exists and is invalid. It
271
367
  contains problems and repair instructions, not lifecycle instructions or
@@ -287,7 +383,8 @@ Observations are discriminated by command intent and `state`:
287
383
 
288
384
  Dialogue versions have `version.type: "worktree"`. When present, `ideas.counts` has
289
385
  `preparing`, `implementing`, `deploying`, `completed`, and `abandoned`;
290
- `activeIdeas` contains only minimal references for the first three states.
386
+ `activeIdeas` contains only minimal references for the first three states
387
+ outside navigation; navigation enriches those references after readiness.
291
388
  Problems have only stable `type` and natural-language `summary`; remediation
292
389
  belongs in `response.nextSteps`.
293
390
 
@@ -328,7 +425,9 @@ The query validates Git presence, configuration, canonical skill, and the
328
425
  complete idea layout before filtering. It reads staged, unstaged, and
329
426
  untracked idea changes from the current worktree snapshot but never checks
330
427
  worktree hygiene, branch, upstream, or primary ancestry, and never fetches or
331
- accesses the network. It has no temporary `--language` option.
428
+ accesses the network. `list-ideas --language <en|en-US|zh|zh-CN>` overrides only
429
+ Silvermoon-owned output for that invocation; without it, the project's
430
+ resolved output language is used.
332
431
 
333
432
  ## Validation Targets
334
433
 
@@ -411,7 +510,7 @@ Like every public command, `check --json` contains all four projections:
411
510
  reports `commit: null` and a problem. Staged and worktree versions only
412
511
  contain `type`.
413
512
 
414
- `--language en-US|zh-CN` is orthogonal to every target. It changes only
513
+ `--language en|en-US|zh|zh-CN` is orthogonal to every target. It changes only
415
514
  Silvermoon-owned natural-language framing and leaves the target, snapshot,
416
515
  validation state, problems, and exit status unchanged.
417
516
 
@@ -28,7 +28,9 @@ primary moves, reobserve instead of replaying approval or acceptance.
28
28
  Choose the entry command from the user's intent. Explicit inventory requests
29
29
  use `silvermoon list-ideas`; explicit new-idea requests use
30
30
  `silvermoon create-idea` even when unrelated active ideas exist; all navigation
31
- uses `silvermoon whats-next [idea]`. Add `--json` only for a programmatic
31
+ uses `silvermoon whats-next [idea]`. Agents should append `--audience agent`
32
+ to report commands and hygiene retries to avoid the human TUI on dual-TTY
33
+ streams. Add `--json` instead only for a programmatic
32
34
  consumer. All three apply the same project and complete idea-layout checks,
33
35
  but their repository readiness differs. `list-ideas` reads the valid local
34
36
  worktree snapshot without hygiene, branch, upstream, network, or ancestry
@@ -39,21 +41,37 @@ explicit creation, perform only that blocking action and then retry
39
41
  `create-idea` so active-idea selection cannot replace the pending create
40
42
  intent.
41
43
 
42
- Use `--language en-US|zh-CN` with `whats-next` or `check` only when the user
43
- explicitly requests a temporary output locale. Preserve the canonical option
44
- on every hygiene retry. It never changes the content language recorded in
45
- project, user, or idea configuration. `create-idea --language <tag>` remains a
46
- separate persistent content-language choice and accepts any canonical BCP 47
47
- tag.
44
+ Use `--language en|en-US|zh|zh-CN` with `list-ideas`, `whats-next`, or `check` only
45
+ when the user explicitly requests a temporary output locale. Preserve the
46
+ canonical option on every hygiene retry. It never changes the content language
47
+ recorded in project, user, or idea configuration. `create-idea --language
48
+ <tag>` remains a separate persistent content-language choice and accepts any
49
+ canonical BCP 47 tag.
48
50
 
49
- ## Decisions And Publication
51
+ ## Decisions And Synchronization
50
52
 
51
53
  `whats-next` may fetch after local readiness passes, but it does not move the
52
54
  worktree, index, branches, or named refs. Human approvals, implementation
53
55
  acceptance, deployment acceptance, and abandonment are ordinary edits to one
54
- idea `status.yaml` after an explicit decision. Validate the candidate and
55
- publish a normal non-force commit. Prefer status-only decision commits when
56
- practical.
56
+ idea `status.yaml` after an explicit decision.
57
+
58
+ Before requesting a human decision, validate the candidate, synchronize its
59
+ normal non-force commit to primary, confirm reachability from the refreshed
60
+ primary, and reobserve the exact world revision and effective content language.
61
+ This synchronization is Agent work and does not require a lifecycle decision.
62
+ Keep the review message short: use that language to state the review focus and
63
+ exact decision question, and provide local plus commit-pinned remote links to
64
+ the canonical contract, same-world supporting files, ledger, evidence, and key
65
+ deliverables. Durable detail belongs in those repository files, not in the
66
+ chat message. Render this index as ordinary assistant Markdown. When using an
67
+ interactive decision tool, put only the exact question and choices in that
68
+ tool; local workspace links in tool-owned surfaces may fail even when the
69
+ files exist. In VS Code on Windows, ordinary-message local links use absolute
70
+ drive paths with forward slashes and never `file://` URIs.
71
+
72
+ After an explicit decision, change only the corresponding status fact,
73
+ validate it, prefer a status-only commit when practical, synchronize it to
74
+ primary, and reobserve the resulting lifecycle state.
57
75
 
58
76
  The required idea-root `ledger.md` is the Agent continuation surface. After
59
77
  repository hygiene and lifecycle routing, combine the reported
@@ -80,12 +98,18 @@ branches.
80
98
 
81
99
  ## Repository Checks
82
100
 
83
- - Run `pnpm test` for the fast unit-and-contract developer suite.
101
+ - Iterate with `pnpm check:sanity` and change-specific tests. Run
102
+ `pnpm check:commit` before committing; see the
103
+ [validation tiers](./maintaining.md#validation-tiers).
104
+ - `pnpm test` and `pnpm check:quick` retain the complete unit/runtime and
105
+ contract suites, including real runtime behavior; they are not sanity aliases.
84
106
  - Run `pnpm test:integration` for real filesystem and Git behavior, and
85
107
  `pnpm test:e2e` for the installed package.
86
- - Run `pnpm check` after CLI, schema, repository model, release, or skill
87
- changes; it remains the complete release-grade validation entrypoint.
88
- - Run `pnpm check:skills` after skill changes.
108
+ - Run `pnpm check` (or `pnpm check:release`) before delivery of CLI, schema,
109
+ repository model, release, or skill changes. It remains the complete
110
+ release-grade validation entrypoint, not the per-edit default.
111
+ - Run `pnpm check:skills:local` while editing skills and `pnpm check:skills`
112
+ before delivery; external discovery failures remain failures.
89
113
  - Validate package contents, installed-package smoke behavior, Markdown links,
90
114
  and `git diff --check` before delivery review.
91
115
  - Use `silvermoon check --commit HEAD` for checked-out CI and
@@ -96,3 +120,7 @@ branches.
96
120
  Only exit code `0` permits the commit; `1` means invalid or unavailable and
97
121
  `2` means invalid usage. Its JSON uses all four projections; only
98
122
  `check --remote` normally records an action.
123
+ - `check:commit` does not install a hook or stage files. Its tests inspect the
124
+ worktree while `check --staged` inspects Silvermoon metadata in the index.
125
+ Partial staging is not exact-candidate test evidence; align worktree and
126
+ index and rerun before claiming staged code passed.