@azure-id/orc 1.7.1 → 1.8.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.
Files changed (58) hide show
  1. package/CHANGELOG.md +3649 -3381
  2. package/README-id.md +923 -844
  3. package/README.md +836 -788
  4. package/bin/build-agents.js +43 -27
  5. package/bin/cli.js +701 -3
  6. package/bin/graph-extract.js +927 -0
  7. package/bin/graph-notes.js +188 -0
  8. package/bin/graph-query.js +808 -0
  9. package/bin/graph-resolve.js +178 -0
  10. package/bin/graph-signals.js +277 -0
  11. package/bin/graph.js +605 -0
  12. package/bin/verify-contracts.js +4669 -4553
  13. package/bin/verify-package.js +626 -616
  14. package/bin/webui/api.js +1419 -1414
  15. package/bin/webui/fixtures/index.js +579 -576
  16. package/bin/webui/fixtures/knowledge.js +316 -291
  17. package/bin/webui/i18n/en/knowledge.json +167 -151
  18. package/bin/webui/i18n/en/overview.json +101 -100
  19. package/bin/webui/i18n/id/knowledge.json +167 -151
  20. package/bin/webui/i18n/id/overview.json +101 -100
  21. package/bin/webui/js/panels/knowledge.js +1065 -1006
  22. package/bin/webui/js/panels/overview.js +492 -488
  23. package/package.json +39 -39
  24. package/templates/agents/MODEL-MAPPING.md +163 -158
  25. package/templates/agents/orc-executor-haiku-4-5.md +133 -121
  26. package/templates/agents/orc-executor-opus-4-7-high.md +134 -122
  27. package/templates/agents/orc-executor-opus-4-7-med.md +134 -122
  28. package/templates/agents/orc-executor-opus-4-8-high.md +134 -122
  29. package/templates/agents/orc-executor-opus-5-high.md +134 -122
  30. package/templates/agents/orc-executor-opus-5-low.md +134 -122
  31. package/templates/agents/orc-executor-opus-5-med.md +134 -122
  32. package/templates/agents/orc-executor-sonnet-4-6-high.md +134 -122
  33. package/templates/agents/orc-executor-sonnet-4-6-med.md +134 -122
  34. package/templates/agents/orc-executor-sonnet-5-high.md +134 -122
  35. package/templates/agents/orc-graph-noter-sonnet-4-6-med.md +86 -0
  36. package/templates/hooks/README.md +444 -396
  37. package/templates/hooks/orc-graph-hook.js +336 -0
  38. package/templates/hooks/orc-statusline-render.js +922 -921
  39. package/templates/hooks/orc-statusline.js +1596 -1545
  40. package/templates/skills/_shared/README.md +4 -0
  41. package/templates/skills/_shared/code-graph.md +220 -0
  42. package/templates/skills/_shared/opus5-only.md +4 -0
  43. package/templates/skills/_shared/phases/execution.md +166 -147
  44. package/templates/skills/_shared/phases/planning.md +142 -135
  45. package/templates/skills/_shared/phases/preflight.md +132 -118
  46. package/templates/skills/_shared/phases/review.md +63 -53
  47. package/templates/skills/_shared/phases/ship.md +96 -88
  48. package/templates/skills/_shared/phases/trace.md +6 -0
  49. package/templates/skills/_shared/phases/wiki-consult.md +194 -189
  50. package/templates/skills/_shared/read-ladder.md +124 -102
  51. package/templates/skills/_shared/return-validation.md +259 -250
  52. package/templates/skills/orc/SKILL.md +255 -254
  53. package/templates/skills/orc-diy/references/flow-schema.md +101 -100
  54. package/templates/skills/orc-fast/SKILL.md +236 -229
  55. package/templates/skills/orc-mini/SKILL.md +267 -259
  56. package/templates/skills/orc-quick/SKILL.md +378 -361
  57. package/templates/skills/orc-quick/references/dispatch-gate.md +6 -0
  58. package/templates/skills/orc-wiki/references/staleness.md +294 -288
@@ -1,288 +1,294 @@
1
- # Reference — Freshness, Staleness & Refresh
2
-
3
- THE canonical freshness reference for the whole constellation. Every skill that
4
- consults the wiki (orc, /orc-ultra, orc-mini, orc-fast, planners) follows the
5
- rules here; this file is the single source of truth for the manifest format,
6
- the tier thresholds, the refresh modes, and the precedence rule.
7
-
8
- ## Precedence (source-of-truth contract)
9
-
10
- **code > fresh wiki > stale wiki (hints) > model priors.** The wiki is a
11
- DERIVED source of truth: on any conflict between a wiki claim and the actual
12
- code, the code wins and the doc gets stale-flagged. Never let a confident wiki
13
- claim override what a file actually shows; never let a model prior override a
14
- fresh, evidence-anchored wiki claim without reading the code.
15
-
16
- ## The manifest — `.claude/orc/wiki-meta.json`
17
-
18
- Written **ONLY by the `orc wiki sync` CLI** — never by a model, never by a
19
- consumer. The manifest is DERIVED data: every field it carries already lives in
20
- the docs' own headers (schemas/wiki-doc.md), so deriving it is deterministic and
21
- free, while authoring it from memory is neither. orc-wiki runs `orc wiki sync`
22
- after every scan-task, at every pause, and at Phase 3; consumers only ever READ
23
- it, and never persist the freshness status they compute from it (below) — that
24
- status goes stale the moment anyone commits. Lives outside `templates/` next to
25
- the pattern cache, so `orc update` never clobbers it.
26
-
27
- > **Why the CLI owns this.** Registration was once the model's job at the end of
28
- > orc-wiki's Phase 3 — the last step of a lane that pauses every 5 scan-tasks by
29
- > design. Every run stopped at a pause left real docs on disk that nothing had
30
- > indexed, invisible to every consumer and to `orc crosslink`. The one field no
31
- > header carries is `commands` (discovered during the scan): sync preserves it
32
- > across rebuilds and falls back to `package.json` scripts, and it is the only
33
- > key a model may hand-edit.
34
-
35
- ```json
36
- {
37
- "last_scan": "12-07-2026 14:32:05",
38
- "scan_commit": "<full git hash — HEAD at scan time>",
39
- "branch": "main",
40
- "pages": 14,
41
- "commands": {
42
- "build": "npm run build",
43
- "test_fast": "npm test",
44
- "lint": "npm run lint"
45
- },
46
- "docs": [
47
- {
48
- "file": "wiki/orc-feature-orders.md",
49
- "area": "orders",
50
- "doc_type": "feature",
51
- "covers": ["src/orders/**"],
52
- "covered_files": { "src/orders/service.ts": "a1b2c3d" },
53
- "scanned_commit": "<git hash>"
54
- }
55
- ]
56
- }
57
- ```
58
-
59
- - `last_scan`: dd-mm-yyyy hh:mm:ss, local time.
60
- - `scan_commit`: the anchor every staleness compute measures against.
61
- - `commands`: the project's build/test/lint invocations, discovered ONCE during
62
- the scan. Consumers (especially orc-fast's smoke gate) run these directly
63
- instead of rediscovering the project's tooling every run. Omit keys the
64
- project doesn't have; never guess.
65
- - `docs` (v2 registry): one entry per wiki doc mirroring its header's
66
- `covers` + `covered_files` (`wiki_schema: 2` docs). Purpose: ALL staleness
67
- questions become answerable from ONE small JSON read + two git commands —
68
- no doc opens. A manifest without `docs` is v1: consumers fall back to
69
- doc-header reads; the next refresh writes the registry.
70
-
71
- ## Computing freshness — COVERAGE-RELATIVE, and the CLI computes it (v0.41.0)
72
-
73
- **Run `orc wiki status` (or `--json` to branch on `.tier`). Never compute the
74
- tier by hand.** These are the RULES; the CLI is their only executor.
75
-
76
- Freshness is **per doc, against its own coverage**:
77
-
78
- ```
79
- per-doc distance = git rev-list --count <doc.scanned_commit>..HEAD -- <that doc's covers/covered_files>
80
- wiki tier = the WORST doc's tier
81
- ```
82
-
83
- | Tier | Condition |
84
- |-------|--------------------|
85
- | FRESH | distance < `wiki_fresh_max` (default 10) |
86
- | AGING | `wiki_fresh_max` ≤ distance ≤ `wiki_aging_max` (default 30) |
87
- | STALE | distance > `wiki_aging_max` |
88
-
89
- Thresholds come from config (`wiki_fresh_max`, `wiki_aging_max`) — the CLI reads
90
- them; a hardcoded 10/30 anywhere is a bug.
91
-
92
- **A STRUCTURAL blind spot** — changed files that NO doc covers — degrades the
93
- tier by exactly ONE step, never past AGING. That is a COVERAGE gap, not doc rot:
94
- the docs on disk are still accurate, they just don't cover everything. (STALE
95
- means "do not trust these docs", which a blind spot does not say. `orc wiki
96
- impact` is where a blind spot escalates to a FULL-refresh recommendation.)
97
-
98
- ### Why per-doc, and why this used to be permanently STALE
99
-
100
- `wiki-meta.json`'s `scan_commit` is the **oldest** doc's anchor — deliberately,
101
- as the conservative floor for the blind-spot sweep. But a DELTA refresh (the
102
- default path) only re-scans TOUCHED docs, so untouched docs keep their original
103
- `scanned_commit` and **that anchor can never move**. Measuring the tier from it
104
- meant every refresh reported the same hash and an ever-growing distance:
105
- permanently STALE, no matter how many times the user refreshed — the exact state
106
- a refresh exists to clear.
107
-
108
- Per-doc coverage also makes the answer semantically right: a doc about auth does
109
- not rot because the README changed forty times. A doc is stale when commits
110
- since its own anchor touched files it covers, and not before.
111
-
112
- ## UNREGISTERED — docs without a manifest
113
-
114
- If `wiki-meta.json` is ABSENT but `wiki/` has docs, the wiki is **UNREGISTERED**,
115
- not missing and not stale. The docs may be perfectly current; nothing has indexed
116
- them. Never treat this as a reason to re-scan — the fix is derived and free:
117
-
118
- > "This wiki has {N} docs but no manifest, so nothing can read it. Run
119
- > `orc wiki sync` — instant, no re-scan."
120
-
121
- Consumers treat an unregistered wiki as STALE for precedence purposes (they
122
- cannot prove freshness without an anchor) but must surface the sync fix, never a
123
- refresh. `orc wiki status` names the state; `orc wiki sync --check` is the
124
- read-only test. The same applies to a manifest that exists but won't parse
125
- (CORRUPT) or that has drifted from the docs on disk (OUT OF SYNC) — one command
126
- fixes all three.
127
-
128
- **Do not conflate incomplete coverage with unregistered.** A scan stopped at a
129
- pause has both: partial coverage (real, fix by resuming — costs money) and no
130
- registration (fix with sync — free). Diagnose them separately; only the first
131
- is worth spending on.
132
-
133
- ## Per-skill reactions
134
-
135
- | Tier | orc / /orc-ultra / planners | orc-mini | orc-fast |
136
- |-------|-----------------------------|----------|----------|
137
- | FRESH | silent | silent | proceed |
138
- | AGING | one-line notice, proceed | one-line notice, proceed | one-line notice, proceed |
139
- | STALE | prominent warning, continue (these lanes self-ground) | prominent warning, continue | **user gate** — see the orc-fast skill (refresh-then-continue recommended / drop to mini / continue anyway) |
140
-
141
- ## Per-doc staleness (advisory second signal)
142
-
143
- Each doc records `scanned_commit` and per-file `covered_files` hashes (v1 docs:
144
- a single `covered_hash`). A doc is stale when the current state of any file in
145
- `covered_files` differs from its recorded hash. Cheap to check via the manifest
146
- registry, no re-scan needed. The doc-header `status: fresh|stale` flag is
147
- ADVISORY only — it is flipped by the auto-flag hook below, which fires only on
148
- ORC runs, so commits made outside ORC never flip it. The computed tier above is
149
- always the authoritative check.
150
-
151
- ## Refresh modes
152
-
153
- 0. **Register-only (`orc wiki sync`)** — not a refresh at all, but it is the
154
- right answer whenever the complaint is "ORC can't see my wiki". Re-derives
155
- the manifest + INDEX from the doc headers. No scan, no cost, no doc changes.
156
- Always try this BEFORE offering any mode below: a wiki that is merely
157
- unregistered needs no re-scan, and re-scanning it wastes real money. Sync
158
- also runs the **boundary detector** (references/crosslink.md): a non-empty
159
- `## Contracts & shapes` table with zero `wiki/crosslink/` tags → prominent
160
- warning + `--check` exit 1 (a documented boundary that never published), and
161
- an N→0 tripwire when the manifest listed tags but the folder is now empty.
162
- 1. **Delta (THE DEFAULT refresh path when a manifest exists — v0.33.0)** —
163
- commit-scoped, probe-first. Step 1 is always the deterministic CLI probe
164
- **`orc wiki impact`** (never an ad-hoc diff): it runs `git diff --name-only
165
- <scan_commit>..HEAD` against the registry's `covers`/`covered_files` and
166
- prints per-doc `CLEAN | TOUCHED (n) | STRUCTURAL` + a summary, with a
167
- branchable exit code (0 clean · 1 can't compute · 2 delta · 3 full
168
- recommended).
169
- - **Exit 0 (CLEAN):** say so; nothing to refresh.
170
- - **Exit 2 (small delta):** re-scan ONLY the touched docs → `orc wiki sync`
171
- → regenerate the orientation doc (+ the atlas when crosslink is
172
- configured) — both DERIVED and cheap, no new scan area. The delta pass
173
- also runs the sweeps below.
174
- - **Exit 3 (FULL recommended):** present the impact table and let the USER
175
- decide — **never silently full**. The probe recommends full when ANY of:
176
- TOUCHED docs > `wiki_delta_full_threshold` % of registered docs (config,
177
- default 30) · STRUCTURAL (a doc's covered file is gone, or changed files
178
- match NO doc's coverage — a blind spot a targeted refresh can't fix) ·
179
- `scan_commit` more than `wiki_aging_max` commits behind HEAD. A delta
180
- refresh of just the touched docs remains a valid, cheaper choice.
181
- - **Exit 1 (can't compute):** the probe names the fix (sync / re-anchor);
182
- fall back to offering full/selective with an honest cost note.
183
- 2. **Full regenerate** — re-scan every area. Full cost warning. Timestamps all
184
- docs fresh. Does NOT clear `wiki/` or `wiki/crosslink/` first: docs and tags
185
- are overwritten per-area/per-point as each re-scan lands, so the crosslink
186
- surface is never momentarily wiped (a full regenerate must never destroy the
187
- boundary — hard rule 12). `wiki/crosslink/atlas.md` is likewise preserved
188
- and regenerated at the end, never bulk-deleted.
189
- 3. **Selective refresh** — list stale-flagged docs; user picks which to
190
- re-scan. Only those spawn agents.
191
- 4. **Pre-push diff-scan** — `git diff --name-only` against the push target;
192
- find docs whose `covers` intersect the changed files; offer to refresh those
193
- before commit.
194
-
195
- **Coverage-gap sweep (delta refresh + integrity check):** changed files
196
- matched by NO doc's `covers` = uncovered drift — the silent way a wiki becomes
197
- a partial map while still reading FRESH. `orc wiki impact` surfaces these as
198
- the STRUCTURAL blind spot; report them grouped by directory and
199
- propose new areas/docs; the user consents per new area (rides the refresh
200
- consent, no separate warning). Never silently ignore uncovered drift.
201
-
202
- **Dead-doc sweep:** registry entries whose `covers` match ZERO existing files
203
- (area deleted/moved) → offer per doc: archive to `wiki/archive/` (kept out of
204
- INDEX.md) or delete. Never silent, never automatic.
205
-
206
- **Dead-tag sweep (crosslink, beside the dead-doc sweep):** a `wiki/crosslink/`
207
- tag whose `anchor` file no longer exists, or whose owning area was re-scanned
208
- this pass and returned `crosslink_tags` WITHOUT it → offer archive/delete per
209
- tag. This is the ONLY way a tag is retired — a refresh never bulk-deletes the
210
- folder (references/crosslink.md preservation rule). Never silent, never automatic.
211
-
212
- ## Post-ship refresh ask (big runs — full orc + /orc-ultra ship phase)
213
-
214
- GUARD FIRST: only if `wiki/` exists AND contains > 0 docs. No wiki → completely
215
- silent (no ask, no note).
216
-
217
- A run counts as BIG when, judged by FINAL counts at ship time (so a medium run
218
- that grew counts): tasks dispatched ≥ `wiki_refresh_ask_tasks` (default 3), OR
219
- union of executors' touched files > `wiki_refresh_ask_files` (default 10), OR
220
- waves > 1. Relevance check: if the run's touched files intersect ZERO docs'
221
- `covers`, downgrade to the passive note regardless of size.
222
-
223
- - **BIG** → right after ship, ask:
224
- 1. **Refresh wiki now** *(recommended)* — incremental refresh (mode 1),
225
- scoped to the docs this run staled.
226
- 2. **Later** — print: "This was a big change — N wiki docs are now stale.
227
- Refresh ASAP (/orc-wiki) or orc-fast and future runs will degrade." Stamp
228
- `wiki_refresh_declined` in the checkpoint so /orc-retro can correlate.
229
- - **Small runs** → the passive auto-flag note below only. No ask.
230
-
231
- orc-mini keeps the passive note only (single-task lane); orc-fast never asks
232
- (its preflight polices freshness on the way in).
233
-
234
- ## Auto-flag hook (after orc / orc-mini runs)
235
-
236
- GUARD FIRST: only act if `wiki/` exists AND contains > 0 files. On an empty/
237
- absent wiki this hook is a silent no-op.
238
-
239
- If guarded in:
240
- 1. Take the files the orc run touched (from its dispatch/actual_files).
241
- 2. Mark every wiki doc whose `covers` intersect those files as `status: stale`.
242
- This is a metadata flip only — instant, free, no scanning.
243
- 3. Tell the user: "N wiki docs are now stale from this change. Run
244
- /orc-wiki to refresh when ready." Never auto-scan. (On a BIG full-lane run
245
- the post-ship refresh ask above replaces this passive note.)
246
-
247
- ## Cross-repo crosslink freshness (references/crosslink.md — advisory only)
248
-
249
- A crosslink hint is trustworthy only if BOTH signals hold; the weakest wins,
250
- `effective = min(Signal-A, Signal-B)`. Both are computed on read; the cache
251
- stamp is a fallback INPUT, never a stored status.
252
-
253
- - **Signal A — provider wiki tier.** The SAME git-commit-distance compute above,
254
- run read-only in the linked repo's checkout (`git rev-list --count
255
- <scan_commit>..HEAD` in `<repo_path>`), using the DEFAULT edges
256
- (`wiki_fresh_max` 10 / `wiki_aging_max` 30) — we do not read the provider's
257
- overrides. Provider not checked out or git fails → fall back to the
258
- `source_tier` stamped in `.claude/orc/crosslink/cache/` at sync, "as of last
259
- sync".
260
- - **Signal B — snapshot age.** The ONLY day-based tier in the constellation
261
- (two repos share no commit axis): `days = today − synced_at`, against
262
- `crosslink_fresh_days` (default 10 → FRESH) and `crosslink_aging_days`
263
- (default 15 → AGING; beyond → STALE).
264
-
265
- Reaction is always advisory: label the injected surface with the effective tier
266
- + "cross-repo hints, not verified", and warn on per-point drift — never block.
267
- Precedence extends the local rule: `local code > local fresh wiki > cross-repo
268
- fresh wiki (hints) > cross-repo stale wiki (weak hints) > model priors`.
269
-
270
- ## Consume rule (main orc + orc-mini)
271
-
272
- Before consulting the wiki during planning/scoring: determine existence with the
273
- deterministic probe `orc wiki status` (per `../../_shared/detecting-artifacts.md`
274
- — never an ad-hoc `find`; `.claude` is hidden). If present, compute the freshness
275
- tier (above) and react per the
276
- per-skill table, then read the relevant `orc-feature-*` / `orc-reference-*` /
277
- `orc-architecture-overview.md` for the area being planned — selecting pages via
278
- `wiki/INDEX.md` (one line per doc: type, status, description, keywords)
279
- instead of globbing and skimming headers. Pull the cross-cutting reference
280
- maps when they exist and the task touches their domain:
281
- `orc-reference-api-surface` (route/endpoint inventory — the best planning
282
- input for API work), `orc-reference-data-model` (tables/entities + owners),
283
- `orc-reference-glossary` (domain terms — read it whenever the request uses
284
- project jargon), `orc-reference-config-env` (env/config keys). In each doc the
285
- `TL;DR` section is the cheap read; `Contracts & shapes` and `Testing map`
286
- carry the file-anchored specifics. Apply the precedence rule above. If
287
- `wiki/` is empty/absent, ignore entirely and plan as normal. The wiki is
288
- purely additive.
1
+ # Reference — Freshness, Staleness & Refresh
2
+
3
+ THE canonical freshness reference for the whole constellation. Every skill that
4
+ consults the wiki (orc, /orc-ultra, orc-mini, orc-fast, planners) follows the
5
+ rules here; this file is the single source of truth for the manifest format,
6
+ the tier thresholds, the refresh modes, and the precedence rule.
7
+
8
+ ## Precedence (source-of-truth contract)
9
+
10
+ **code > fresh wiki > stale wiki (hints) > model priors.** The wiki is a
11
+ DERIVED source of truth: on any conflict between a wiki claim and the actual
12
+ code, the code wins and the doc gets stale-flagged. Never let a confident wiki
13
+ claim override what a file actually shows; never let a model prior override a
14
+ fresh, evidence-anchored wiki claim without reading the code.
15
+
16
+ With the local code graph on, the order gains two rungs and loses none:
17
+ **code > graph structure (current blob) > fresh wiki > stale wiki (hints) > graph notes > model priors.**
18
+ Graph structure outranks the wiki because it is extracted from the exact current
19
+ bytes; graph notes rank below it because a model wrote them. Canonical:
20
+ `skills/_shared/code-graph.md`.
21
+
22
+ ## The manifest — `.claude/orc/wiki-meta.json`
23
+
24
+ Written **ONLY by the `orc wiki sync` CLI** — never by a model, never by a
25
+ consumer. The manifest is DERIVED data: every field it carries already lives in
26
+ the docs' own headers (schemas/wiki-doc.md), so deriving it is deterministic and
27
+ free, while authoring it from memory is neither. orc-wiki runs `orc wiki sync`
28
+ after every scan-task, at every pause, and at Phase 3; consumers only ever READ
29
+ it, and never persist the freshness status they compute from it (below) — that
30
+ status goes stale the moment anyone commits. Lives outside `templates/` next to
31
+ the pattern cache, so `orc update` never clobbers it.
32
+
33
+ > **Why the CLI owns this.** Registration was once the model's job at the end of
34
+ > orc-wiki's Phase 3 — the last step of a lane that pauses every 5 scan-tasks by
35
+ > design. Every run stopped at a pause left real docs on disk that nothing had
36
+ > indexed, invisible to every consumer and to `orc crosslink`. The one field no
37
+ > header carries is `commands` (discovered during the scan): sync preserves it
38
+ > across rebuilds and falls back to `package.json` scripts, and it is the only
39
+ > key a model may hand-edit.
40
+
41
+ ```json
42
+ {
43
+ "last_scan": "12-07-2026 14:32:05",
44
+ "scan_commit": "<full git hash — HEAD at scan time>",
45
+ "branch": "main",
46
+ "pages": 14,
47
+ "commands": {
48
+ "build": "npm run build",
49
+ "test_fast": "npm test",
50
+ "lint": "npm run lint"
51
+ },
52
+ "docs": [
53
+ {
54
+ "file": "wiki/orc-feature-orders.md",
55
+ "area": "orders",
56
+ "doc_type": "feature",
57
+ "covers": ["src/orders/**"],
58
+ "covered_files": { "src/orders/service.ts": "a1b2c3d" },
59
+ "scanned_commit": "<git hash>"
60
+ }
61
+ ]
62
+ }
63
+ ```
64
+
65
+ - `last_scan`: dd-mm-yyyy hh:mm:ss, local time.
66
+ - `scan_commit`: the anchor every staleness compute measures against.
67
+ - `commands`: the project's build/test/lint invocations, discovered ONCE during
68
+ the scan. Consumers (especially orc-fast's smoke gate) run these directly
69
+ instead of rediscovering the project's tooling every run. Omit keys the
70
+ project doesn't have; never guess.
71
+ - `docs` (v2 registry): one entry per wiki doc mirroring its header's
72
+ `covers` + `covered_files` (`wiki_schema: 2` docs). Purpose: ALL staleness
73
+ questions become answerable from ONE small JSON read + two git commands —
74
+ no doc opens. A manifest without `docs` is v1: consumers fall back to
75
+ doc-header reads; the next refresh writes the registry.
76
+
77
+ ## Computing freshness — COVERAGE-RELATIVE, and the CLI computes it (v0.41.0)
78
+
79
+ **Run `orc wiki status` (or `--json` to branch on `.tier`). Never compute the
80
+ tier by hand.** These are the RULES; the CLI is their only executor.
81
+
82
+ Freshness is **per doc, against its own coverage**:
83
+
84
+ ```
85
+ per-doc distance = git rev-list --count <doc.scanned_commit>..HEAD -- <that doc's covers/covered_files>
86
+ wiki tier = the WORST doc's tier
87
+ ```
88
+
89
+ | Tier | Condition |
90
+ |-------|--------------------|
91
+ | FRESH | distance < `wiki_fresh_max` (default 10) |
92
+ | AGING | `wiki_fresh_max` ≤ distance ≤ `wiki_aging_max` (default 30) |
93
+ | STALE | distance > `wiki_aging_max` |
94
+
95
+ Thresholds come from config (`wiki_fresh_max`, `wiki_aging_max`) — the CLI reads
96
+ them; a hardcoded 10/30 anywhere is a bug.
97
+
98
+ **A STRUCTURAL blind spot** — changed files that NO doc covers — degrades the
99
+ tier by exactly ONE step, never past AGING. That is a COVERAGE gap, not doc rot:
100
+ the docs on disk are still accurate, they just don't cover everything. (STALE
101
+ means "do not trust these docs", which a blind spot does not say. `orc wiki
102
+ impact` is where a blind spot escalates to a FULL-refresh recommendation.)
103
+
104
+ ### Why per-doc, and why this used to be permanently STALE
105
+
106
+ `wiki-meta.json`'s `scan_commit` is the **oldest** doc's anchor — deliberately,
107
+ as the conservative floor for the blind-spot sweep. But a DELTA refresh (the
108
+ default path) only re-scans TOUCHED docs, so untouched docs keep their original
109
+ `scanned_commit` and **that anchor can never move**. Measuring the tier from it
110
+ meant every refresh reported the same hash and an ever-growing distance:
111
+ permanently STALE, no matter how many times the user refreshed — the exact state
112
+ a refresh exists to clear.
113
+
114
+ Per-doc coverage also makes the answer semantically right: a doc about auth does
115
+ not rot because the README changed forty times. A doc is stale when commits
116
+ since its own anchor touched files it covers, and not before.
117
+
118
+ ## UNREGISTERED — docs without a manifest
119
+
120
+ If `wiki-meta.json` is ABSENT but `wiki/` has docs, the wiki is **UNREGISTERED**,
121
+ not missing and not stale. The docs may be perfectly current; nothing has indexed
122
+ them. Never treat this as a reason to re-scan — the fix is derived and free:
123
+
124
+ > "This wiki has {N} docs but no manifest, so nothing can read it. Run
125
+ > `orc wiki sync` — instant, no re-scan."
126
+
127
+ Consumers treat an unregistered wiki as STALE for precedence purposes (they
128
+ cannot prove freshness without an anchor) but must surface the sync fix, never a
129
+ refresh. `orc wiki status` names the state; `orc wiki sync --check` is the
130
+ read-only test. The same applies to a manifest that exists but won't parse
131
+ (CORRUPT) or that has drifted from the docs on disk (OUT OF SYNC) — one command
132
+ fixes all three.
133
+
134
+ **Do not conflate incomplete coverage with unregistered.** A scan stopped at a
135
+ pause has both: partial coverage (real, fix by resuming — costs money) and no
136
+ registration (fix with sync — free). Diagnose them separately; only the first
137
+ is worth spending on.
138
+
139
+ ## Per-skill reactions
140
+
141
+ | Tier | orc / /orc-ultra / planners | orc-mini | orc-fast |
142
+ |-------|-----------------------------|----------|----------|
143
+ | FRESH | silent | silent | proceed |
144
+ | AGING | one-line notice, proceed | one-line notice, proceed | one-line notice, proceed |
145
+ | STALE | prominent warning, continue (these lanes self-ground) | prominent warning, continue | **user gate** — see the orc-fast skill (refresh-then-continue recommended / drop to mini / continue anyway) |
146
+
147
+ ## Per-doc staleness (advisory second signal)
148
+
149
+ Each doc records `scanned_commit` and per-file `covered_files` hashes (v1 docs:
150
+ a single `covered_hash`). A doc is stale when the current state of any file in
151
+ `covered_files` differs from its recorded hash. Cheap to check via the manifest
152
+ registry, no re-scan needed. The doc-header `status: fresh|stale` flag is
153
+ ADVISORY only — it is flipped by the auto-flag hook below, which fires only on
154
+ ORC runs, so commits made outside ORC never flip it. The computed tier above is
155
+ always the authoritative check.
156
+
157
+ ## Refresh modes
158
+
159
+ 0. **Register-only (`orc wiki sync`)** — not a refresh at all, but it is the
160
+ right answer whenever the complaint is "ORC can't see my wiki". Re-derives
161
+ the manifest + INDEX from the doc headers. No scan, no cost, no doc changes.
162
+ Always try this BEFORE offering any mode below: a wiki that is merely
163
+ unregistered needs no re-scan, and re-scanning it wastes real money. Sync
164
+ also runs the **boundary detector** (references/crosslink.md): a non-empty
165
+ `## Contracts & shapes` table with zero `wiki/crosslink/` tags → prominent
166
+ warning + `--check` exit 1 (a documented boundary that never published), and
167
+ an N→0 tripwire when the manifest listed tags but the folder is now empty.
168
+ 1. **Delta (THE DEFAULT refresh path when a manifest exists — v0.33.0)** —
169
+ commit-scoped, probe-first. Step 1 is always the deterministic CLI probe
170
+ **`orc wiki impact`** (never an ad-hoc diff): it runs `git diff --name-only
171
+ <scan_commit>..HEAD` against the registry's `covers`/`covered_files` and
172
+ prints per-doc `CLEAN | TOUCHED (n) | STRUCTURAL` + a summary, with a
173
+ branchable exit code (0 clean · 1 can't compute · 2 delta · 3 full
174
+ recommended).
175
+ - **Exit 0 (CLEAN):** say so; nothing to refresh.
176
+ - **Exit 2 (small delta):** re-scan ONLY the touched docs → `orc wiki sync`
177
+ → regenerate the orientation doc (+ the atlas when crosslink is
178
+ configured) — both DERIVED and cheap, no new scan area. The delta pass
179
+ also runs the sweeps below.
180
+ - **Exit 3 (FULL recommended):** present the impact table and let the USER
181
+ decide — **never silently full**. The probe recommends full when ANY of:
182
+ TOUCHED docs > `wiki_delta_full_threshold` % of registered docs (config,
183
+ default 30) · STRUCTURAL (a doc's covered file is gone, or changed files
184
+ match NO doc's coverage — a blind spot a targeted refresh can't fix) ·
185
+ `scan_commit` more than `wiki_aging_max` commits behind HEAD. A delta
186
+ refresh of just the touched docs remains a valid, cheaper choice.
187
+ - **Exit 1 (can't compute):** the probe names the fix (sync / re-anchor);
188
+ fall back to offering full/selective with an honest cost note.
189
+ 2. **Full regenerate** — re-scan every area. Full cost warning. Timestamps all
190
+ docs fresh. Does NOT clear `wiki/` or `wiki/crosslink/` first: docs and tags
191
+ are overwritten per-area/per-point as each re-scan lands, so the crosslink
192
+ surface is never momentarily wiped (a full regenerate must never destroy the
193
+ boundary — hard rule 12). `wiki/crosslink/atlas.md` is likewise preserved
194
+ and regenerated at the end, never bulk-deleted.
195
+ 3. **Selective refresh** — list stale-flagged docs; user picks which to
196
+ re-scan. Only those spawn agents.
197
+ 4. **Pre-push diff-scan** — `git diff --name-only` against the push target;
198
+ find docs whose `covers` intersect the changed files; offer to refresh those
199
+ before commit.
200
+
201
+ **Coverage-gap sweep (delta refresh + integrity check):** changed files
202
+ matched by NO doc's `covers` = uncovered drift — the silent way a wiki becomes
203
+ a partial map while still reading FRESH. `orc wiki impact` surfaces these as
204
+ the STRUCTURAL blind spot; report them grouped by directory and
205
+ propose new areas/docs; the user consents per new area (rides the refresh
206
+ consent, no separate warning). Never silently ignore uncovered drift.
207
+
208
+ **Dead-doc sweep:** registry entries whose `covers` match ZERO existing files
209
+ (area deleted/moved) → offer per doc: archive to `wiki/archive/` (kept out of
210
+ INDEX.md) or delete. Never silent, never automatic.
211
+
212
+ **Dead-tag sweep (crosslink, beside the dead-doc sweep):** a `wiki/crosslink/`
213
+ tag whose `anchor` file no longer exists, or whose owning area was re-scanned
214
+ this pass and returned `crosslink_tags` WITHOUT it → offer archive/delete per
215
+ tag. This is the ONLY way a tag is retired — a refresh never bulk-deletes the
216
+ folder (references/crosslink.md preservation rule). Never silent, never automatic.
217
+
218
+ ## Post-ship refresh ask (big runs — full orc + /orc-ultra ship phase)
219
+
220
+ GUARD FIRST: only if `wiki/` exists AND contains > 0 docs. No wiki → completely
221
+ silent (no ask, no note).
222
+
223
+ A run counts as BIG when, judged by FINAL counts at ship time (so a medium run
224
+ that grew counts): tasks dispatched ≥ `wiki_refresh_ask_tasks` (default 3), OR
225
+ union of executors' touched files > `wiki_refresh_ask_files` (default 10), OR
226
+ waves > 1. Relevance check: if the run's touched files intersect ZERO docs'
227
+ `covers`, downgrade to the passive note regardless of size.
228
+
229
+ - **BIG** → right after ship, ask:
230
+ 1. **Refresh wiki now** *(recommended)* — incremental refresh (mode 1),
231
+ scoped to the docs this run staled.
232
+ 2. **Later** — print: "This was a big change — N wiki docs are now stale.
233
+ Refresh ASAP (/orc-wiki) or orc-fast and future runs will degrade." Stamp
234
+ `wiki_refresh_declined` in the checkpoint so /orc-retro can correlate.
235
+ - **Small runs** → the passive auto-flag note below only. No ask.
236
+
237
+ orc-mini keeps the passive note only (single-task lane); orc-fast never asks
238
+ (its preflight polices freshness on the way in).
239
+
240
+ ## Auto-flag hook (after orc / orc-mini runs)
241
+
242
+ GUARD FIRST: only act if `wiki/` exists AND contains > 0 files. On an empty/
243
+ absent wiki this hook is a silent no-op.
244
+
245
+ If guarded in:
246
+ 1. Take the files the orc run touched (from its dispatch/actual_files).
247
+ 2. Mark every wiki doc whose `covers` intersect those files as `status: stale`.
248
+ This is a metadata flip only — instant, free, no scanning.
249
+ 3. Tell the user: "N wiki docs are now stale from this change. Run
250
+ /orc-wiki to refresh when ready." Never auto-scan. (On a BIG full-lane run
251
+ the post-ship refresh ask above replaces this passive note.)
252
+
253
+ ## Cross-repo crosslink freshness (references/crosslink.md — advisory only)
254
+
255
+ A crosslink hint is trustworthy only if BOTH signals hold; the weakest wins,
256
+ `effective = min(Signal-A, Signal-B)`. Both are computed on read; the cache
257
+ stamp is a fallback INPUT, never a stored status.
258
+
259
+ - **Signal A — provider wiki tier.** The SAME git-commit-distance compute above,
260
+ run read-only in the linked repo's checkout (`git rev-list --count
261
+ <scan_commit>..HEAD` in `<repo_path>`), using the DEFAULT edges
262
+ (`wiki_fresh_max` 10 / `wiki_aging_max` 30) — we do not read the provider's
263
+ overrides. Provider not checked out or git fails → fall back to the
264
+ `source_tier` stamped in `.claude/orc/crosslink/cache/` at sync, "as of last
265
+ sync".
266
+ - **Signal B — snapshot age.** The ONLY day-based tier in the constellation
267
+ (two repos share no commit axis): `days = today − synced_at`, against
268
+ `crosslink_fresh_days` (default 10 → FRESH) and `crosslink_aging_days`
269
+ (default 15 → AGING; beyond → STALE).
270
+
271
+ Reaction is always advisory: label the injected surface with the effective tier
272
+ + "cross-repo hints, not verified", and warn on per-point drift — never block.
273
+ Precedence extends the local rule: `local code > local fresh wiki > cross-repo
274
+ fresh wiki (hints) > cross-repo stale wiki (weak hints) > model priors`.
275
+
276
+ ## Consume rule (main orc + orc-mini)
277
+
278
+ Before consulting the wiki during planning/scoring: determine existence with the
279
+ deterministic probe `orc wiki status` (per `../../_shared/detecting-artifacts.md`
280
+ — never an ad-hoc `find`; `.claude` is hidden). If present, compute the freshness
281
+ tier (above) and react per the
282
+ per-skill table, then read the relevant `orc-feature-*` / `orc-reference-*` /
283
+ `orc-architecture-overview.md` for the area being planned — selecting pages via
284
+ `wiki/INDEX.md` (one line per doc: type, status, description, keywords)
285
+ instead of globbing and skimming headers. Pull the cross-cutting reference
286
+ maps when they exist and the task touches their domain:
287
+ `orc-reference-api-surface` (route/endpoint inventory — the best planning
288
+ input for API work), `orc-reference-data-model` (tables/entities + owners),
289
+ `orc-reference-glossary` (domain terms — read it whenever the request uses
290
+ project jargon), `orc-reference-config-env` (env/config keys). In each doc the
291
+ `TL;DR` section is the cheap read; `Contracts & shapes` and `Testing map`
292
+ carry the file-anchored specifics. Apply the precedence rule above. If
293
+ `wiki/` is empty/absent, ignore entirely and plan as normal. The wiki is
294
+ purely additive.