@fenglimg/fabric-shared 2.3.0-rc.15 → 2.3.0-rc.16

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.
@@ -36,7 +36,8 @@ var BOOTSTRAP_CANONICAL_ZH = `# Fabric Bootstrap
36
36
  \u5B8C\u6574 maintainer \u7248\u89C1 \`docs/USER-QUICKSTART.md\`\u3002
37
37
 
38
38
  ## \u884C\u4E3A\u89C4\u5219
39
- - **\u4FEE\u6539\u4EFB\u4F55\u6587\u4EF6\u524D**:\u5148 \`fab_recall(paths=[<\u88AB\u6539\u6587\u4EF6>])\` \u2014\u2014 \u4E00\u6B21\u8C03\u7528\u62FF\u56DE\u76F8\u5173 KB \u7684\u63CF\u8FF0 + \u539F\u751F\u8BFB\u53D6\u8DEF\u5F84(\`entries[].read_path\`)\u3002\`fab_recall\` \u4E0D\u518D\u6295\u9012\u6B63\u6587;\u9700\u8981\u67D0\u6761\u6B63\u6587\u65F6\u76F4\u63A5\u5BF9\u5176 \`entries[].read_path\` \u505A\u539F\u751F Read(\`Read <store>/knowledge/<type>/<id>--*.md\`),\u8FD9\u4F1A\u88AB PostToolUse hook \u8BB0\u4E3A \`knowledge_body_read\`\u3002lean \u9ED8\u8BA4:\u63CF\u8FF0+\u7D22\u5F15\u5DF2\u591F\u53D1\u73B0\u6761\u76EE,\u6B63\u6587\u6309\u9700\u8BFB\u4E00\u6B21,\u4E0D\u6BCF\u8F6E\u91CD\u704C(KT-GLD-0005)\u3002
39
+ - **Pre-action gating (\u4FEE\u6539\u4EFB\u4F55\u6587\u4EF6\u524D MUST)**: \u2460 \u5148 \`fab_recall(paths=[<\u88AB\u6539\u6587\u4EF6>], session_id=<client-session-id>)\`\uFF1B\u2461 \u6309\u9700\u539F\u751F Read \u547D\u4E2D\u7684 \`entries[].read_path\` \u6B63\u6587(PostToolUse \u8BB0\u4E3A \`knowledge_body_read\`)\uFF1B\u2462 \u8DF3\u8FC7\u4E0D\u9002\u7528\u547D\u4E2D\u65F6\u8BF4 \`dismissed: <id> (<reason>)\`\u3002\`fab_recall\` \u4E0D\u518D\u6295\u9012\u6B63\u6587;lean \u9ED8\u8BA4\u63CF\u8FF0+\u7D22\u5F15\u5DF2\u591F\u53D1\u73B0\u6761\u76EE(KT-GLD-0005)\u3002PreToolUse \u4EC5\u8F6F nudge,\u5B88 KT-DEC-0007(\u975E permanent gate / \u65E0 \`decision:block\`)\u3002
40
+ - **Archive-as-truth**: \u8FDB canonical **\u552F\u4E00\u8DEF\u5F84** \u662F \`fab_propose\` \u2192 pending \u2192 \`fabric-review\`/\`fab_review\` \u5BA1\u6279\uFF1B\u7981\u6B62\u628A chat/log \u81EA\u52A8 promote \u8FDB canonical\u3002
40
41
  - **\`.fabric/agents.meta.json\` \u4E25\u7981\u624B\u52A8\u7F16\u8F91**\uFF08co-location index \u5DF2\u9000\u5F79;\u77E5\u8BC6\u5728 mounted stores\uFF09\u3002\u5F02\u5E38\u65F6\u8DD1 \`fabric doctor\` / \`fabric doctor --fix\` \u81EA\u6108\u53EF\u4FEE\u590D\u9879\u3002
41
42
 
42
43
  ## \u77E5\u8BC6\u5E93(KB)
@@ -46,7 +47,7 @@ var BOOTSTRAP_CANONICAL_ZH = `# Fabric Bootstrap
46
47
  - **session_id**: \u8C03\u7528 \`fab_recall\` \u65F6, \u52A1\u5FC5\u628A\u5F53\u524D client session id \u4F5C\u4E3A \`session_id\` \u53C2\u6570\u4F20\u5165(Claude Code \u7684 session id \u5728 stdin payload \u4E2D, Codex \u7684\u5BF9\u5E94 identifier \u540C\u7406)\u3002\u8FD9\u80FD\u8BA9 \`fabric doctor --archive-history\` \u4E0E \`fabric-hint.cjs\` Stop hook \u51C6\u786E\u8BC6\u522B\u8DE8\u4F1A\u8BDD debt \u72B6\u6001\u3002
47
48
  - **Skills (4)**:\u5199\u6D41\u7A0B \`fabric-archive\`(\u542B source mode \u51B7\u542F\u52A8\u4ECE git/docs \u56DE\u704C)/ \`fabric-review\`(\u542B retire \u8BED\u4E49\u6DD8\u6C70 + relate \u5173\u8054\u5EFA\u8FB9 \u5B50\u6D41\u7A0B);store \u8FD0\u7EF4 \`fabric-store\` / \`fabric-sync\`\u3002
48
49
  - **Language**:\u6E32\u67D3\u6309 \`~/.fabric/fabric-global.json\` \u7684 \`language\` \u5B57\u6BB5(machine-wide tone)\u3002
49
- - **Archive cadence nudge** (rc.36): \u6BCF\u5B8C\u6210\u4E00\u6279 Edit(\u9ED8\u8BA4 ~20 \u6B21, \u4E0E Stop hook \u9608\u503C config \`archive_edit_threshold\` \u4E00\u81F4)/ \u663E\u8457 decision \u540E,\u5728\u5408\u9002\u56DE\u5408\u4E3B\u52A8 propose \u8C03 \`fabric-archive\` skill \u2014 archive \u6CA1\u5EFA\u7ACB\u9891\u7387\u4F1A\u8BA9 KB \u6162\u901F\u6B7B\u6389\u3002
50
+ - **Archive cadence nudge** (rc.36 / finish\u2192archive): \u663E\u8457 decision \u6536\u53E3\u6216\u4E00\u6279 Edit \u8FBE\u5230 config \`archive_edit_threshold\`(\u9ED8\u8BA4 20) \u540E,\u5728\u5408\u9002\u56DE\u5408\u8F7B\u91CF\u81EA\u8C03 \`fabric-archive\`(\u540C turn \u6700\u591A 1 \u6B21;\u975E task engine / \u975E Stop-hook flood)\u3002Stop hook \u4EC5 soft threshold nudge,\u5B88 KT-DEC-0007 \u2014 archive \u6CA1\u5EFA\u7ACB\u9891\u7387\u4F1A\u8BA9 KB \u6162\u901F\u6B7B\u6389\u3002
50
51
  - **Review backlog nudge** (rc.36): \u9700\u8981\u5224\u65AD pending backlog \u65F6\u8D70 \`fab_pending action="list"\` \u6216 \`fabric-review\` \u8FD4\u56DE\u7684 \`pending_path\`;\u4E0D\u8981 glob \u9879\u76EE\u672C\u5730 \`.fabric/knowledge/pending\`\u3002\u5F53\u53EF\u89C1 pending \u7D2F\u79EF >10 \u6761\u65F6,\u5728\u5408\u9002\u56DE\u5408\u4E3B\u52A8 propose \u8C03 \`fabric-review\` skill \u6279\u91CF\u5BA1,\u907F\u514D draft \u5361\u6B7B\u3002
51
52
 
52
53
  ## Self-archive policy (v2.2 C1: \u7CBE\u7B80\u8BF4\u660E\u4E66)
@@ -95,7 +96,8 @@ As a dev you only need to: run \`fabric install\` once per repo, use \`fabric st
95
96
  See \`docs/USER-QUICKSTART.md\` for the full maintainer version.
96
97
 
97
98
  ## Behavior Rules
98
- - **Before modifying any file**: first \`fab_recall(paths=[<file-being-edited>])\` \u2014\u2014 a single call returns the relevant KB descriptions + native read paths (\`entries[].read_path\`). \`fab_recall\` no longer delivers bodies; when you need a body, do a native Read of its \`entries[].read_path\` (\`Read <store>/knowledge/<type>/<id>--*.md\`), which the PostToolUse hook records as \`knowledge_body_read\`. Lean default: descriptions + index already suffice to discover entries; read a body once on demand, don't re-inject it every turn (KT-GLD-0005).
99
+ - **Pre-action gating (MUST before Edit/Write)**: (1) call \`fab_recall(paths=[<file-being-edited>], session_id=<client-session-id>)\`; (2) optionally native-Read selected \`entries[].read_path\` bodies (PostToolUse records \`knowledge_body_read\`); (3) when skipping a hit, say \`dismissed: <id> (<reason>)\`. \`fab_recall\` no longer delivers bodies; lean default is description+index discovery (KT-GLD-0005). PreToolUse is soft nudge only per KT-DEC-0007 (never permanent gate / no \`decision:block\`).
100
+ - **Archive-as-truth**: the **only** path into canonical is \`fab_propose\` \u2192 pending \u2192 \`fabric-review\`/\`fab_review\` approve; never auto-promote chat/logs into canonical.
99
101
  - **Never hand-edit \`.fabric/agents.meta.json\`** (co-location index retired; knowledge lives in mounted stores). For anomalies run \`fabric doctor\` / \`fabric doctor --fix\` on fixable state.
100
102
 
101
103
  ## Knowledge Base (KB)
@@ -105,7 +107,7 @@ See \`docs/USER-QUICKSTART.md\` for the full maintainer version.
105
107
  - **session_id**: when calling \`fab_recall\`, always pass the current client session id as the \`session_id\` argument (Claude Code's session id is in the stdin payload; Codex's corresponding identifier likewise). This lets \`fabric doctor --archive-history\` and the \`fabric-hint.cjs\` Stop hook track cross-session debt accurately.
106
108
  - **Skills (4)**: write flow \`fabric-archive\` (with source-mode cold-start backfill from git/docs) / \`fabric-review\` (with retire-deprecation + relate-edge sub-flows); store ops \`fabric-store\` / \`fabric-sync\`.
107
109
  - **Language**: rendered per the \`language\` field in \`~/.fabric/fabric-global.json\` (machine-wide tone).
108
- - **Archive cadence nudge** (rc.36): after each batch of edits (default ~20, matching the Stop hook threshold config \`archive_edit_threshold\`) / a significant decision, proactively propose the \`fabric-archive\` skill at a suitable turn \u2014 without an archive cadence the KB slowly dies.
110
+ - **Archive cadence nudge** (rc.36 / finish\u2192archive): after a significant decision lands or an edit batch reaches config \`archive_edit_threshold\` (default 20), lightly self-trigger \`fabric-archive\` at a suitable turn (max 1 per turn; not a task engine / not Stop-hook flood). Stop hook remains a soft threshold nudge per KT-DEC-0007 \u2014 without an archive cadence the KB slowly dies.
109
111
  - **Review backlog nudge** (rc.36): to judge the pending backlog, go through \`fab_pending action="list"\` or the \`pending_path\` returned by \`fabric-review\`; don't glob the project-local \`.fabric/knowledge/pending\`. When the visible pending count exceeds 10, proactively propose the \`fabric-review\` skill at a suitable turn to batch-review and avoid draft deadlock.
110
112
 
111
113
  ## Self-archive policy (v2.2 C1: lean spec)
@@ -4,6 +4,8 @@ import {
4
4
 
5
5
  // src/i18n/locales/en.ts
6
6
  var enMessages = {
7
+ "cli.signpost.retired": "Command `{retired}` was removed. Use `{successor}` instead.",
8
+ "cli.doctor.args.probe.description": "Emit a machine-readable JSON readiness snapshot (first-hit + store/hooks) without running --fix Prefer --probe in CI for a cheap readiness snapshot; full cite-coverage scans remain on-demand.",
7
9
  "cli.main.description": "Fabric CLI \u2014 feeds your project's decisions, pitfalls & conventions to your AI assistant automatically. First time? Run: fabric install",
8
10
  "cli.shared.created": "Created",
9
11
  "cli.shared.skipped": "Skipped",
@@ -63,8 +65,8 @@ var enMessages = {
63
65
  "cli.preview.error": "preview failed: {message}",
64
66
  "cli.audit.description": "Knowledge & telemetry audit (cite/conflicts/history/metrics)",
65
67
  // `fabric audit cite` — 0%-recall-coverage self-diagnosis hints.
66
- "cli.audit.cite.recall-mismatch-hint": "recall coverage is 0 despite {recalls} recall(s) across {sessions} session(s) \u2014 none shared a session with an edit. The recall caller is likely passing a non-client session_id (correlation is session-scoped). See AGENTS.md: pass the real client session_id to fab_recall.",
67
- "cli.audit.cite.recall-none-hint": "recall coverage is 0 \u2014 no in-session fab_recall preceded these edits. Recall before editing, and pass the real client session_id (correlation is session-scoped). See AGENTS.md.",
68
+ "cli.audit.cite.recall-mismatch-hint": "recall coverage is 0 despite {recalls} recall(s) across {sessions} session(s) \u2014 none shared a session with an edit. Likely causes: (1) fab_recall omitted/wrong session_id (must be real client session_id; empty planned events never join edits); (2) recall paths do not path-overlap the edited file (auto-cite only counts overlapping planned.target_paths). Fix: pass session_id, reinstall hooks for active-session sidecar, or fab_recall paths that cover the edit. See AGENTS.md + docs/UPGRADE.md.",
69
+ "cli.audit.cite.recall-none-hint": "recall coverage is 0 \u2014 no in-session fab_recall preceded these edits (or planned events had empty session_id so they could not join). Recall before editing with the real client session_id; after install, SessionStart stamps .fabric/.cache/active-session.json as server fallback. Path-overlap still required: recall the files you will edit, not only unrelated .fabric paths. See AGENTS.md + docs/UPGRADE.md.",
68
70
  // `fabric audit --help` — filtered help (i18n'd subcommand listing).
69
71
  "cli.audit.help.tagline": "Knowledge & telemetry audit surfaces (read-only)",
70
72
  "cli.audit.help.sub.cite": "Cite-policy adherence report",
@@ -112,7 +114,7 @@ var enMessages = {
112
114
  "cli.config.install.args.dry-run.description": "Preview detected write operations without modifying files.",
113
115
  "cli.config.errors.unknown-client": 'Unknown client "{client}". Use a comma-separated list such as cc,codex.',
114
116
  "cli.config.errors.expected-object": "Expected object in {path}",
115
- "cli.config.install.no-configs": "No Fabric MCP client config detected. Create the client directory or set clientPaths in fabric.config.json.",
117
+ "cli.config.install.no-configs": "No Fabric MCP client config detected. Create the client directory or set clientPaths in .fabric/fabric-config.json.",
116
118
  "cli.config.install.no-config-path": "Skipping {client}: no config path detected.",
117
119
  "cli.config.install.dry-run": "[dry-run] {client}: would write {path}",
118
120
  "cli.config.install.wrote": "{client}: wrote {path}",
@@ -195,9 +197,9 @@ var enMessages = {
195
197
  // with doctor.check.*; messages carry store alias / counts via interpolation.
196
198
  "doctor.store.no-global-config": "no global Fabric config \u2014 run `fabric install --global <url>`",
197
199
  "doctor.store.missing-required": "required store '{id}' is not mounted; run `fabric store mount`",
198
- "doctor.store.unbound": "store '{alias}' is mounted but not bound to this project; run `fabric store bind {alias}` to read its knowledge here (then `fabric store switch-write {alias}` to write team knowledge into it)",
200
+ "doctor.store.unbound": "store '{alias}' is mounted but not bound to this project \u2014 paste: `fabric store bind {alias}` then `fabric store switch-write {alias}`",
199
201
  "doctor.store.empty": "bound store(s) have 0 knowledge entries ({stores}) \u2014 first-hit cannot succeed until you seed or clone knowledge; run `fabric first-hit --seed` (empty local store) or bind a remote team store with content",
200
- "doctor.store.no-write-target": "no active write store for this project \u2014 bind and switch-write: `fabric store bind <alias>` then `fabric store switch-write <alias>` (or re-run `fabric install`)",
202
+ "doctor.store.no-write-target": "no active write store for this project \u2014 paste: `fabric store bind <alias>` then `fabric store switch-write <alias>` (or `fabric install`)",
201
203
  "doctor.store.no-match": "knowledge exists but no entry matches the probe paths \u2014 try broader paths or add relevance_paths for your modules",
202
204
  "doctor.store.write-target-mismatch": "active write store '{alias}' is not a valid team write target for this project \u2014 run `fabric store switch-write <mounted-team-alias>`",
203
205
  "doctor.store.first-hit-missing-required": "required store(s) not mounted: {ids} \u2014 bind/clone them then re-run `fabric first-hit`",
@@ -216,6 +218,12 @@ var enMessages = {
216
218
  "doctor.store.consumption-heatmap": "top consumed (last {days}d, {consumed}/{total} entries read across {windows} window(s)): {top}",
217
219
  "doctor.store.consumption-zero": "{count} entries never consumed in the last {days}d: {sample}{overflow} \u2014 review for retirement via `fab_review` (consumption is one signal, not proof of rot)",
218
220
  "doctor.store.overflow-more": ", \u2026(+{count} more)",
221
+ "doctor.check.knowledge_body_altitude_dump.name": "Knowledge body altitude",
222
+ "doctor.check.knowledge_body_altitude_dump.ok": "No dump-shaped knowledge bodies detected.",
223
+ "doctor.check.knowledge_body_altitude_dump.message.singular": "1 dump-shaped knowledge body: {detail}",
224
+ "doctor.check.knowledge_body_altitude_dump.message.plural": "{count} dump-shaped knowledge bodies (e.g. {detail})",
225
+ "doctor.check.knowledge_body_altitude_dump.remediation": "Rewrite as reusable decision/pitfall/guideline altitude (## structure), not a session transcript; re-archive via fabric-archive / fab_propose",
226
+ "doctor.check.knowledge_body_altitude_dump.scan_error": "Body-altitude scan failed ({detail}); doctor cannot confirm corpus is clean.",
219
227
  "doctor.fix-plan.header": "knowledge mutation plan ({count} total)",
220
228
  "doctor.fix-plan.preview": "preview:",
221
229
  "doctor.fix-plan.more": "... and {count} more",
@@ -423,7 +431,7 @@ var enMessages = {
423
431
  "doctor.check.events_jsonl_health.message.metric_leak": ".fabric/events.jsonl contains {count} rows with metric-counter event_types ({samples}). Those events should be aggregated in metrics.jsonl, not in the audit ledger.",
424
432
  "doctor.check.events_jsonl_health.message.metrics_stale": ".fabric/metrics.jsonl hasn't been updated for {minutes} minutes; the server-side 60s flush may be stalled.",
425
433
  "doctor.check.events_jsonl_health.message.rotation_overdue": ".fabric/events.jsonl hasn't rotated for {days} days; the 6h rotation tick may not be running.",
426
- "doctor.check.events_jsonl_health.remediation": "Run `fabric doctor --fix` \u2014 it triggers a rotation AND flushes metrics.jsonl (rc.2 F16: clears idle-buffered metric counters without a server restart). If the warning persists, restart the MCP server so startMetricsFlush + startRotationTick reschedule. If metric_leak fires, audit recent code changes for direct appendEventLedgerEvent calls bypassing bumpCounter for one of the 4 metric-managed event_types.",
434
+ "doctor.check.events_jsonl_health.remediation": "Run `fabric doctor --fix` \u2014 it triggers events.jsonl rotation (honors fabric_event_retention_days: 7|30|90 in .fabric/fabric-config.json) AND flushes metrics.jsonl. If the warning persists, restart the MCP server so startMetricsFlush + startRotationTick reschedule. If metric_leak fires, audit recent code changes for direct appendEventLedgerEvent calls bypassing bumpCounter for one of the 4 metric-managed event_types.",
427
435
  "doctor.check.event_ledger_partial_write.name": "Event ledger partial write",
428
436
  "doctor.check.event_ledger_partial_write.ok.skipped": "No partial-write check needed (ledger missing or not writable).",
429
437
  "doctor.check.event_ledger_partial_write.message": "events.jsonl has a partial write at byte offset {byteOffset} ({byteLength} corrupted bytes). Run --fix to truncate and preserve corrupted bytes.",
@@ -626,6 +634,7 @@ var enMessages = {
626
634
  "doctor.check.relevance_paths_drift.message.plural": "{count} narrow-scope canonical entries have relevance_paths whose globs match no file touched in the last {windowDays}d of git history. First: {detail}.",
627
635
  "doctor.check.relevance_paths_drift.remediation": "Review whether the entry is still relevant \u2014 use `fab_review.modify` to refresh the anchors or `fab_review.reject` to archive.",
628
636
  // W4-3 (KT-MOD-0001): narrow-scope entry with an empty relevance_paths set.
637
+ "doctor.check.relevance_paths_drift.remediation_with_sample": "Review whether the entry is still relevant \u2014 sample {sample}; refresh anchors via `fab_review.modify`, or archive via `fab_review.reject`.",
629
638
  "doctor.check.narrow_no_paths.name": "Knowledge narrow scope without paths",
630
639
  "doctor.check.narrow_no_paths.ok": "Every narrow-scope canonical entry carries at least one relevance_path.",
631
640
  "doctor.check.narrow_no_paths.message.singular": "{count} narrow-scope entry has an empty relevance_paths set \u2014 it can never path-match, so it will never surface (permanently dead). First: {detail}.",
@@ -677,6 +686,14 @@ var enMessages = {
677
686
  "doctor.check.stray_fabric_dir_detected.ok": "No stray .fabric directories under the project root \u2014 the only authoritative anchor is <projectRoot>/.fabric.",
678
687
  "doctor.check.stray_fabric_dir_detected.message": "Found {count} stray .fabric director(ies) ({dirs}) left by subprocesses that mistook a subdirectory for the project root (pre-rc.10 hooks / pre-rc.11 server-side). These scatter events.jsonl / metrics.jsonl / .cache across the source tree.",
679
688
  "doctor.check.stray_fabric_dir_detected.remediation": "Run `fabric doctor --fix` to rename each stray dir to `.fabric.stale-<timestamp>` (rescue-before-delete \u2014 never a hard delete). Review the renamed dirs before merging events. Also upgrade global fabric-cli to rc.11+ so the server-side git-anchor resolver is active.",
689
+ // legacy_fabric_cache_dir_detected — the recall engine's BM25 / vector
690
+ // caches used to live at `.fabric/cache/{bm25,vectors}`; unify-fabric-cache-dir
691
+ // moved them into `.fabric/.cache/` next to the hook sidecar cache so one
692
+ // .gitignore rule covers both. Old data is intact; the fix is a rename.
693
+ "doctor.check.legacy_fabric_cache_dir_detected.name": "Legacy .fabric/cache/ directories",
694
+ "doctor.check.legacy_fabric_cache_dir_detected.ok": "Recall caches live under .fabric/.cache/ \u2014 no legacy .fabric/cache/{bm25,vectors} remains.",
695
+ "doctor.check.legacy_fabric_cache_dir_detected.message": "Found {count} legacy recall-cache dir(s) ({dirs}). These pre-date the unify-fabric-cache-dir move to .fabric/.cache/; the on-disk data (BM25 snapshots / vector embeddings) is intact \u2014 a rename preserves it.",
696
+ "doctor.check.legacy_fabric_cache_dir_detected.remediation": "Run `fabric doctor --fix` to rename each legacy dir into its `.fabric/.cache/` counterpart (idempotent; skipped if the new path already holds newer data). No re-embed cost is paid; the snapshot files are moved as-is.",
680
697
  "doctor.check.skill_md_yaml_invalid.name": "Skill markdown YAML",
681
698
  "doctor.check.skill_md_yaml_invalid.ok": "All .claude/.codex SKILL.md frontmatter values parse as strict YAML.",
682
699
  "doctor.check.skill_md_yaml_invalid.message.singular": "{count} SKILL.md frontmatter value contains an unquoted ': ' that strict YAML parsers reject (Claude Code tolerates it; Codex CLI drops the skill at load). First: {detail}.",
@@ -818,6 +835,7 @@ var enMessages = {
818
835
  // so its MCP server loads — that is the default anchor; the --reapply maintenance
819
836
  // hint moves to --verbose.
820
837
  "cli.install.next-step.restart": "restart any open Claude Code / Codex session to load Fabric (new sessions pick it up automatically).",
838
+ "cli.install.next-step.nudge-mode": 'Human breadcrumbs default to minimal (one status line/session). Mute with nudge_mode: "silent" in .fabric/fabric-config.json or FABRIC_NUDGE_MODE=silent; raise with normal/verbose.',
821
839
  "cli.install.reason-message": "{label} {message}",
822
840
  "cli.install.language.prompt": "Choose the Fabric language (used for both UI and knowledge; change later via `fabric config`):",
823
841
  "cli.install.language.option.zh-CN": "\u7B80\u4F53\u4E2D\u6587 (zh-CN)",
@@ -874,7 +892,7 @@ var enMessages = {
874
892
  "cli.install.semantic.installing": "Running `npm i -g fastembed` \u2026",
875
893
  "cli.install.semantic.installed": "fastembed installed. The embedding model downloads automatically on the first recall (~tens\u2013hundreds of MB; no KB data is uploaded).",
876
894
  "cli.install.semantic.install-failed": "Auto-install failed ({reason}). Run the steps manually:",
877
- "cli.install.semantic.manual-steps": " 1. Install the optional embedder where the MCP server resolves modules (a global install is global):\n npm i -g fastembed\n 2. Warm the model cache (the first run downloads the weights, ~tens\u2013hundreds of MB; no KB data is uploaded):\n export FABRIC_EMBED_CACHE_DIR=~/.cache/fabric-embed # strict-offline: pre-place the weights here\n Note: after switching embed_model the existing vector dim/semantics change; the next recall re-embeds with the new model (doc vectors are cached by text and auto-recompute on mismatch).\n Disable: set embed_enabled=false in fabric.config.json.",
895
+ "cli.install.semantic.manual-steps": " 1. Install the optional embedder where the MCP server resolves modules (a global install is global):\n npm i -g fastembed\n 2. Warm the model cache (the first run downloads the weights, ~tens\u2013hundreds of MB; no KB data is uploaded):\n export FABRIC_EMBED_CACHE_DIR=~/.cache/fabric-embed # strict-offline: pre-place the weights here\n Note: after switching embed_model the existing vector dim/semantics change; the next recall re-embeds with the new model (doc vectors are cached by text and auto-recompute on mismatch).\n Disable: set embed_enabled=false in .fabric/fabric-config.json.",
878
896
  // C5: store onboarding interactive copy routed through t().
879
897
  "cli.install.store.local-store": "local store",
880
898
  "cli.install.store.bind-mounted.prompt": "Bind an already-mounted knowledge store to this project?",
@@ -1046,6 +1064,18 @@ var enMessages = {
1046
1064
  "cli.first-hit.args.target.description": "Project root (default: cwd)",
1047
1065
  "cli.first-hit.args.seed.description": "If empty store, write minimal starter knowledge entries",
1048
1066
  "cli.first-hit.args.paths.description": "Comma-separated probe paths for surface check",
1067
+ "cli.first-hit.msg.ok": "first-hit ready: {total} knowledge entr{plural} across {stores} store(s); hooks present.",
1068
+ "cli.first-hit.msg.unbound": "unbound: no store is bound to this project's read-set \u2014 knowledge cannot surface.",
1069
+ "cli.first-hit.msg.no_write_target": "no_write_target: project has required stores but no active_write_store.",
1070
+ "cli.first-hit.msg.empty_store": "empty_store: store(s) bound but 0 canonical knowledge files \u2014 empty store is not a happy path.",
1071
+ "cli.first-hit.msg.missing_required": "missing_required: one or more required_stores are not mounted \u2014 multi-store bind incomplete.",
1072
+ "cli.first-hit.msg.write_target_mismatch": "write_target_mismatch: active_write_store is not a mounted writable store on the read-set.",
1073
+ "cli.first-hit.msg.store_unreachable": "store_unreachable: a bound store is registered but its directory is missing on disk.",
1074
+ "cli.first-hit.msg.project_unsealed": "project_unsealed: write store is bound but project_id/active_project is missing \u2014 team knowledge will land flat (semantic_scope: team), not project-partitioned.",
1075
+ "cli.first-hit.msg.no_match": "no_match: knowledge exists but the probe surface is empty (path/scope filter).",
1076
+ "cli.first-hit.msg.hooks_missing": "hooks_missing: knowledge is present but SessionStart/PreToolUse hooks are not installed.",
1077
+ "cli.first-hit.msg.no_project": "no_project: this directory is not a Fabric project (missing .fabric/fabric-config.json).",
1078
+ "cli.first-hit.msg.no_global": "no_global: fabric global config missing \u2014 run fabric install --global first.",
1049
1079
  "cli.onboard-coverage.description": "Report S5 onboard-slot coverage for the workspace. Used by the fabric-archive Skill's first-run phase to detect unclaimed project-tone slots.",
1050
1080
  "cli.onboard-coverage.args.json.description": "Emit machine-readable JSON to stdout instead of the human table.",
1051
1081
  "cli.onboard-coverage.args.target.description": "Override the project root (defaults to cwd).",
@@ -1296,6 +1326,10 @@ var enMessages = {
1296
1326
  "cli.info.recall.vector.not-ready": "not ready \u2014 recall falls back to keyword mode (BM25 / additive)",
1297
1327
  "cli.info.recall.warm.ok": "embedder warm: model '{model}' loaded (vector dim {dim}), cached at {dir}",
1298
1328
  "cli.info.recall.warm.fail": "embedder unavailable \u2014 the optional 'fastembed' package is not resolvable or the model failed to load.\n Recall falls back to keyword mode (BM25 / additive). Install fastembed where the server resolves modules, then retry.",
1329
+ "cli.store.mount.description": "Mount a knowledge store into the global registry",
1330
+ "cli.store.create.description": "Create a brand-new local knowledge store and mount it",
1331
+ "cli.store.remove.description": "Detach a store from the registry (does NOT delete it)",
1332
+ "cli.store.explain.description": "Explain how a store alias resolves",
1299
1333
  "cli.store.list.description": "List mounted knowledge stores",
1300
1334
  // Footer note appended to `fabric store --help` — explains where the advanced
1301
1335
  // (meta.hidden) operations went so the list-only listing isn't a dead end.
@@ -1369,6 +1403,8 @@ var enMessages = {
1369
1403
 
1370
1404
  // src/i18n/locales/zh-CN.ts
1371
1405
  var zhCNMessages = {
1406
+ "cli.signpost.retired": "\u547D\u4EE4 `{retired}` \u5DF2\u79FB\u9664\u3002\u8BF7\u6539\u7528 `{successor}`\u3002",
1407
+ "cli.doctor.args.probe.description": "\u8F93\u51FA\u673A\u5668\u53EF\u8BFB JSON \u5C31\u7EEA\u5FEB\u7167(first-hit + store/hooks),\u4E0D\u8DD1 --fix CI \u4F18\u5148\u7528 --probe \u505A\u8F7B\u91CF\u5C31\u7EEA\u5FEB\u7167\uFF1B\u5B8C\u6574 cite-coverage \u626B\u63CF\u6309\u9700\u8FD0\u884C\u3002",
1372
1408
  "cli.main.description": "Fabric CLI \u2014 \u81EA\u52A8\u628A\u672C\u9879\u76EE\u7684\u51B3\u7B56 / \u8E29\u5751 / \u89C4\u8303\u5582\u7ED9\u4F60\u7684 AI \u52A9\u624B\uFF0C\u8BA9\u5B83\u4E0D\u5FC5\u6BCF\u6B21\u4F1A\u8BDD\u91CD\u65B0\u5B66\u3002\u9996\u6B21\u4F7F\u7528?\u8FD0\u884C: fabric install",
1373
1409
  "cli.shared.created": "\u5DF2\u521B\u5EFA",
1374
1410
  "cli.shared.skipped": "\u5DF2\u8DF3\u8FC7",
@@ -1426,8 +1462,8 @@ var zhCNMessages = {
1426
1462
  "cli.preview.error": "preview \u5931\u8D25:{message}",
1427
1463
  "cli.audit.description": "\u77E5\u8BC6\u4E0E\u9065\u6D4B\u5BA1\u8BA1 (cite/conflicts/history/metrics)",
1428
1464
  // `fabric audit cite` — recall 覆盖率为 0 的自诊断提示。
1429
- "cli.audit.cite.recall-mismatch-hint": "recall \u8986\u76D6\u7387\u4E3A 0,\u4F46\u672C\u7A97\u53E3\u6709 {recalls} \u6B21 recall(\u5206\u5E03\u5728 {sessions} \u4E2A\u4F1A\u8BDD)\u2014\u2014 \u6CA1\u6709\u4E00\u4E2A\u4E0E\u7F16\u8F91\u5171\u4EAB\u4F1A\u8BDD\u3002\u591A\u534A\u662F fab_recall \u8C03\u7528\u65B9\u4F20\u4E86\u975E\u5BA2\u6237\u7AEF session_id(\u5173\u8054\u6309\u4F1A\u8BDD\u9694\u79BB)\u3002\u89C1 AGENTS.md:fab_recall \u5FC5\u987B\u4F20\u5165\u771F\u5B9E\u5BA2\u6237\u7AEF session_id\u3002",
1430
- "cli.audit.cite.recall-none-hint": "recall \u8986\u76D6\u7387\u4E3A 0 \u2014\u2014 \u8FD9\u4E9B\u7F16\u8F91\u524D\u6CA1\u6709\u540C\u4F1A\u8BDD\u7684 fab_recall\u3002\u6539\u524D\u5148 recall,\u4E14\u4F20\u5165\u771F\u5B9E\u5BA2\u6237\u7AEF session_id(\u5173\u8054\u6309\u4F1A\u8BDD\u9694\u79BB)\u3002\u89C1 AGENTS.md\u3002",
1465
+ "cli.audit.cite.recall-mismatch-hint": "recall \u8986\u76D6\u7387\u4E3A 0,\u4F46\u672C\u7A97\u53E3\u6709 {recalls} \u6B21 recall(\u5206\u5E03\u5728 {sessions} \u4E2A\u4F1A\u8BDD)\u2014\u2014 \u6CA1\u6709\u4E00\u4E2A\u4E0E\u7F16\u8F91\u5171\u4EAB\u4F1A\u8BDD\u3002\u5E38\u89C1\u539F\u56E0:(1) fab_recall \u6F0F\u4F20/\u4F20\u9519 session_id(\u5FC5\u987B\u662F\u771F\u5B9E\u5BA2\u6237\u7AEF session_id;planned \u65E0 session \u6C38\u4E0D\u4E0E edit \u5173\u8054);(2) recall \u7684 paths \u4E0E\u7F16\u8F91\u6587\u4EF6\u65E0 path-overlap(\u81EA\u52A8 cite \u53EA\u8BA1\u91CD\u53E0\u7684 planned.target_paths)\u3002\u4FEE:\u4F20 session_id\u3001\u91CD\u88C5 hooks \u542F\u7528 active-session sidecar\u3001\u6216 fab_recall \u8986\u76D6\u5C06\u7F16\u8F91\u7684\u8DEF\u5F84\u3002\u89C1 AGENTS.md \u4E0E docs/UPGRADE.md\u3002",
1466
+ "cli.audit.cite.recall-none-hint": "recall \u8986\u76D6\u7387\u4E3A 0 \u2014\u2014 \u8FD9\u4E9B\u7F16\u8F91\u524D\u6CA1\u6709\u540C\u4F1A\u8BDD\u7684 fab_recall(\u6216 planned \u4E8B\u4EF6 session_id \u4E3A\u7A7A\u5BFC\u81F4\u65E0\u6CD5\u5173\u8054)\u3002\u6539\u524D\u5148 recall \u5E76\u4F20\u5165\u771F\u5B9E\u5BA2\u6237\u7AEF session_id;install \u540E SessionStart \u4F1A\u5199 .fabric/.cache/active-session.json \u4F9B\u670D\u52A1\u7AEF\u56DE\u586B\u3002\u4ECD\u8981\u6C42 path-overlap:recall \u8981\u8986\u76D6\u5C06\u7F16\u8F91\u7684\u6587\u4EF6,\u4E0D\u8981\u53EA recall \u65E0\u5173\u7684 .fabric \u8DEF\u5F84\u3002\u89C1 AGENTS.md \u4E0E docs/UPGRADE.md\u3002",
1431
1467
  // `fabric audit --help` — 过滤式帮助(i18n 子命令清单)。
1432
1468
  "cli.audit.help.tagline": "\u77E5\u8BC6\u4E0E\u9065\u6D4B\u5BA1\u8BA1\u9762(\u53EA\u8BFB)",
1433
1469
  "cli.audit.help.sub.cite": "Cite \u653F\u7B56\u9075\u5FAA\u5EA6\u62A5\u544A",
@@ -1470,7 +1506,7 @@ var zhCNMessages = {
1470
1506
  "cli.config.install.args.dry-run.description": "\u4EC5\u9884\u89C8\u5C06\u8981\u53D1\u751F\u7684\u5199\u5165\u64CD\u4F5C\uFF0C\u4E0D\u4FEE\u6539\u6587\u4EF6\u3002",
1471
1507
  "cli.config.errors.unknown-client": "\u672A\u77E5\u5BA2\u6237\u7AEF\u201C{client}\u201D\u3002\u8BF7\u4F7F\u7528\u9017\u53F7\u5206\u9694\u5217\u8868\uFF0C\u4F8B\u5982 cc,codex\u3002",
1472
1508
  "cli.config.errors.expected-object": "{path} \u4E2D\u5E94\u4E3A\u5BF9\u8C61\u3002",
1473
- "cli.config.install.no-configs": "\u672A\u68C0\u6D4B\u5230 Fabric MCP \u5BA2\u6237\u7AEF\u914D\u7F6E\u3002\u8BF7\u521B\u5EFA\u5BA2\u6237\u7AEF\u76EE\u5F55\uFF0C\u6216\u5728 fabric.config.json \u4E2D\u8BBE\u7F6E clientPaths\u3002",
1509
+ "cli.config.install.no-configs": "\u672A\u68C0\u6D4B\u5230 Fabric MCP \u5BA2\u6237\u7AEF\u914D\u7F6E\u3002\u8BF7\u521B\u5EFA\u5BA2\u6237\u7AEF\u76EE\u5F55\uFF0C\u6216\u5728 .fabric/fabric-config.json \u4E2D\u8BBE\u7F6E clientPaths\u3002",
1474
1510
  "cli.config.install.no-config-path": "\u8DF3\u8FC7 {client}\uFF1A\u672A\u68C0\u6D4B\u5230\u914D\u7F6E\u8DEF\u5F84\u3002",
1475
1511
  "cli.config.install.dry-run": "[dry-run] {client}\uFF1A\u5C06\u5199\u5165 {path}",
1476
1512
  "cli.config.install.wrote": "{client}\uFF1A\u5DF2\u5199\u5165 {path}",
@@ -1551,9 +1587,9 @@ var zhCNMessages = {
1551
1587
  // 文案通过插值带上 store alias / 计数。
1552
1588
  "doctor.store.no-global-config": "\u65E0\u5168\u5C40 Fabric \u914D\u7F6E \u2014\u2014 \u8FD0\u884C `fabric install --global <url>`",
1553
1589
  "doctor.store.missing-required": "\u5FC5\u9700 store '{id}' \u672A\u6302\u8F7D;\u8FD0\u884C `fabric store mount`",
1554
- "doctor.store.unbound": "store '{alias}' \u5DF2\u6302\u8F7D\u4F46\u672A\u7ED1\u5B9A\u5230\u672C\u9879\u76EE;\u8FD0\u884C `fabric store bind {alias}` \u5373\u53EF\u5728\u6B64\u8BFB\u53D6\u5B83\u7684\u77E5\u8BC6(\u518D\u7528 `fabric store switch-write {alias}` \u628A\u56E2\u961F\u77E5\u8BC6\u5199\u5165\u5B83)",
1590
+ "doctor.store.unbound": "store '{alias}' \u5DF2\u6302\u8F7D\u4F46\u672A\u7ED1\u5B9A\u5230\u672C\u9879\u76EE \u2014 \u7C98\u8D34\u6267\u884C: `fabric store bind {alias}` \u7136\u540E `fabric store switch-write {alias}`",
1555
1591
  "doctor.store.empty": "\u5DF2\u7ED1\u5B9A store \u77E5\u8BC6\u6761\u6570\u4E3A 0\uFF08{stores}\uFF09\u2014\u2014\u5728 seed \u6216 clone \u6709\u5185\u5BB9\u524D\u65E0\u6CD5 first-hit\uFF1B\u8FD0\u884C `fabric first-hit --seed`\uFF08\u7A7A\u672C\u5730\u5E93\uFF09\u6216\u7ED1\u5B9A\u5E26\u5185\u5BB9\u7684\u8FDC\u7A0B team store",
1556
- "doctor.store.no-write-target": "\u672C\u9879\u76EE\u65E0\u6D3B\u52A8\u5199\u5E93 \u2014\u2014 \u5148 bind \u518D switch-write\uFF1A`fabric store bind <alias>` \u7136\u540E `fabric store switch-write <alias>`\uFF08\u6216\u91CD\u8DD1 `fabric install`\uFF09",
1592
+ "doctor.store.no-write-target": "\u672C\u9879\u76EE\u65E0 active write store \u2014 \u7C98\u8D34\u6267\u884C: `fabric store bind <alias>` \u7136\u540E `fabric store switch-write <alias>`\uFF08\u6216 `fabric install`\uFF09",
1557
1593
  "doctor.store.no-match": "\u77E5\u8BC6\u5B58\u5728\u4F46\u4E0E\u63A2\u6D4B\u8DEF\u5F84\u65E0\u5339\u914D \u2014\u2014 \u653E\u5BBD paths \u6216\u4E3A\u6A21\u5757\u8865 relevance_paths",
1558
1594
  "doctor.store.write-target-mismatch": "\u6D3B\u52A8\u5199\u5E93 '{alias}' \u4E0D\u662F\u672C\u9879\u76EE\u7684\u6709\u6548 team \u5199\u76EE\u6807 \u2014\u2014 \u8FD0\u884C `fabric store switch-write <\u5DF2\u6302\u8F7D team \u522B\u540D>`",
1559
1595
  "doctor.store.first-hit-missing-required": "\u5FC5\u9700 store \u672A\u6302\u8F7D: {ids} \u2014\u2014 \u5148 bind/clone \u518D\u8DD1 `fabric first-hit`",
@@ -1572,6 +1608,12 @@ var zhCNMessages = {
1572
1608
  "doctor.store.consumption-heatmap": "\u6D88\u8D39\u70ED\u533A(\u8FD1 {days}d,{consumed}/{total} \u6761\u88AB\u8BFB,\u8DE8 {windows} \u4E2A\u7A97\u53E3):{top}",
1573
1609
  "doctor.store.consumption-zero": "{count} \u6761\u5728\u8FD1 {days}d \u5185\u4ECE\u672A\u88AB\u6D88\u8D39:{sample}{overflow} \u2014\u2014 \u901A\u8FC7 `fab_review` \u8003\u8651\u6DD8\u6C70(\u6D88\u8D39\u91CF\u53EA\u662F\u4FE1\u53F7\u4E4B\u4E00,\u975E\u9648\u65E7\u7684\u8BC1\u636E)",
1574
1610
  "doctor.store.overflow-more": ", \u2026(+{count} \u6761)",
1611
+ "doctor.check.knowledge_body_altitude_dump.name": "\u77E5\u8BC6\u6B63\u6587 altitude",
1612
+ "doctor.check.knowledge_body_altitude_dump.ok": "\u672A\u53D1\u73B0 dump \u5F62\u6001\u7684\u77E5\u8BC6\u6B63\u6587\u3002",
1613
+ "doctor.check.knowledge_body_altitude_dump.message.singular": "1 \u6761 dump \u5F62\u6001\u77E5\u8BC6\u6B63\u6587: {detail}",
1614
+ "doctor.check.knowledge_body_altitude_dump.message.plural": "{count} \u6761 dump \u5F62\u6001\u77E5\u8BC6\u6B63\u6587(\u4F8B\u5982 {detail})",
1615
+ "doctor.check.knowledge_body_altitude_dump.remediation": "\u6539\u5199\u6210\u53EF\u590D\u7528\u7684 decision/pitfall/guideline altitude(\u5E26 ## \u7ED3\u6784),\u4E0D\u8981\u8D34 session \u6D41\u6C34;\u7ECF fabric-archive / fab_propose \u91CD\u5F52\u6863",
1616
+ "doctor.check.knowledge_body_altitude_dump.scan_error": "\u6B63\u6587 altitude \u626B\u63CF\u5931\u8D25({detail});doctor \u65E0\u6CD5\u786E\u8BA4\u8BED\u6599\u5E72\u51C0\u3002",
1575
1617
  "doctor.fix-plan.header": "\u77E5\u8BC6\u4FA7\u53D8\u66F4\u8BA1\u5212(\u5171 {count} \u9879)",
1576
1618
  "doctor.fix-plan.preview": "\u9884\u89C8:",
1577
1619
  "doctor.fix-plan.more": "... \u8FD8\u6709 {count} \u9879",
@@ -1771,7 +1813,7 @@ var zhCNMessages = {
1771
1813
  "doctor.check.events_jsonl_health.message.metric_leak": ".fabric/events.jsonl \u542B {count} \u884C metric-counter \u7C7B event_type ({samples})\u3002\u8FD9\u4E9B event \u5E94\u7531 metrics.jsonl \u8BA1\u6570, \u4E0D\u518D\u8FDB\u5165 audit ledger\u3002",
1772
1814
  "doctor.check.events_jsonl_health.message.metrics_stale": ".fabric/metrics.jsonl \u5DF2 {minutes} \u5206\u949F\u672A\u66F4\u65B0\uFF1Bserver-side 60s flush \u53EF\u80FD stalled\u3002",
1773
1815
  "doctor.check.events_jsonl_health.message.rotation_overdue": ".fabric/events.jsonl \u5DF2 {days} \u5929\u672A rotate\uFF1B6h rotation tick \u53EF\u80FD\u672A\u8FD0\u884C\u3002",
1774
- "doctor.check.events_jsonl_health.remediation": "\u8FD0\u884C `fabric doctor --fix` \u2014\u2014 \u5B83\u4F1A\u89E6\u53D1 rotation \u5E76 flush metrics.jsonl(rc.2 F16: \u65E0\u9700\u91CD\u542F server \u5373\u53EF\u6E05\u51FA idle \u671F\u672A\u5237\u7684 metric counter)\u3002\u82E5\u544A\u8B66\u4ECD\u6301\u7EED, \u518D\u91CD\u542F MCP server \u8BA9 startMetricsFlush + startRotationTick \u91CD\u65B0\u8C03\u5EA6\u3002\u82E5 metric_leak \u547D\u4E2D, \u68C0\u67E5\u6700\u8FD1\u4EE3\u7801\u6539\u52A8\u662F\u5426\u7ED5\u8FC7 bumpCounter API \u76F4\u63A5 appendEventLedgerEvent \u5199\u4E86 4 \u4E2A metric-managed event_type \u4E4B\u4E00\u3002",
1816
+ "doctor.check.events_jsonl_health.remediation": "\u8FD0\u884C `fabric doctor --fix` \u2014\u2014 \u4F1A\u6309 .fabric/fabric-config.json \u7684 fabric_event_retention_days(7|30|90) \u8F6E\u8F6C events.jsonl\uFF0C\u5E76 flush metrics.jsonl\u3002\u82E5\u544A\u8B66\u4ECD\u6301\u7EED\uFF0C\u518D\u91CD\u542F MCP server \u8BA9 startMetricsFlush + startRotationTick \u91CD\u65B0\u8C03\u5EA6\u3002\u82E5 metric_leak \u547D\u4E2D\uFF0C\u68C0\u67E5\u6700\u8FD1\u4EE3\u7801\u662F\u5426\u7ED5\u8FC7 bumpCounter \u76F4\u63A5\u5199\u4E86 metric-managed event_type\u3002",
1775
1817
  "doctor.check.event_ledger_partial_write.name": "\u4E8B\u4EF6\u8D26\u672C\u534A\u622A\u5199\u5165",
1776
1818
  "doctor.check.event_ledger_partial_write.ok.skipped": "\u65E0\u9700\u6267\u884C partial-write \u68C0\u67E5\uFF08ledger \u7F3A\u5931\u6216\u4E0D\u53EF\u5199\uFF09\u3002",
1777
1819
  "doctor.check.event_ledger_partial_write.message": "events.jsonl \u5728 byte offset {byteOffset} \u5904\u5B58\u5728 partial write\uFF08{byteLength} \u4E2A corrupted bytes\uFF09\u3002\u8FD0\u884C --fix \u622A\u65AD\u5E76\u4FDD\u7559 corrupted bytes\u3002",
@@ -1973,6 +2015,7 @@ var zhCNMessages = {
1973
2015
  "doctor.check.relevance_paths_drift.message.singular": "{count} \u4E2A narrow-scope canonical entry \u7684 relevance_paths globs \u6CA1\u6709\u5339\u914D\u5230\u6700\u8FD1 {windowDays}d git history \u4E2D\u89E6\u78B0\u8FC7\u7684\u6587\u4EF6\u3002\u9996\u4E2A:{detail}\u3002",
1974
2016
  "doctor.check.relevance_paths_drift.message.plural": "{count} \u4E2A narrow-scope canonical entries \u7684 relevance_paths globs \u6CA1\u6709\u5339\u914D\u5230\u6700\u8FD1 {windowDays}d git history \u4E2D\u89E6\u78B0\u8FC7\u7684\u6587\u4EF6\u3002\u9996\u4E2A:{detail}\u3002",
1975
2017
  "doctor.check.relevance_paths_drift.remediation": "\u5BA1\u9605\u8BE5 entry \u662F\u5426\u4ECD\u7136\u76F8\u5173 \u2014 \u4F7F\u7528 `fab_review.modify` \u5237\u65B0 anchors,\u6216\u4F7F\u7528 `fab_review.reject` \u5F52\u6863\u3002",
2018
+ "doctor.check.relevance_paths_drift.remediation_with_sample": "\u5BA1\u9605\u8BE5 entry \u662F\u5426\u4ECD\u7136\u76F8\u5173 \u2014 \u6837\u672C {sample};\u4F7F\u7528 `fab_review.modify` \u5237\u65B0 anchors,\u6216\u4F7F\u7528 `fab_review.reject` \u5F52\u6863\u3002",
1976
2019
  // W4-3 (KT-MOD-0001): narrow scope 但 relevance_paths 为空。
1977
2020
  "doctor.check.narrow_no_paths.name": "\u77E5\u8BC6 narrow scope \u7F3A\u8DEF\u5F84",
1978
2021
  "doctor.check.narrow_no_paths.ok": "\u6BCF\u6761 narrow scope canonical entry \u90FD\u81F3\u5C11\u5E26\u4E00\u4E2A relevance_path\u3002",
@@ -2024,6 +2067,14 @@ var zhCNMessages = {
2024
2067
  "doctor.check.stray_fabric_dir_detected.ok": "\u9879\u76EE\u4E0B\u672A\u53D1\u73B0\u6E38\u79BB .fabric \u76EE\u5F55,\u552F\u4E00\u6743\u5A01\u6839 .fabric \u5C31\u662F <projectRoot>/.fabric\u3002",
2025
2068
  "doctor.check.stray_fabric_dir_detected.message": "\u53D1\u73B0 {count} \u4E2A\u6E38\u79BB .fabric \u76EE\u5F55({dirs}),\u5B83\u4EEC\u662F\u5B50\u8FDB\u7A0B\u5728\u5B50\u76EE\u5F55\u88AB\u8BEF\u8BA4\u4F5C project root \u7684\u5386\u53F2\u9057\u7559(rc.10 \u4E4B\u524D\u7684 hook / rc.11 \u4E4B\u524D\u7684 server \u4FA7),\u4F1A\u5BFC\u81F4 events.jsonl / metrics.jsonl / .cache \u6563\u843D\u3002",
2026
2069
  "doctor.check.stray_fabric_dir_detected.remediation": "\u8DD1 `fabric doctor --fix` \u4F1A\u628A\u6BCF\u4E2A\u6E38\u79BB dir \u6539\u540D\u4E3A `.fabric.stale-<timestamp>`(rescue-before-delete,\u4E0D\u786C\u5220)\u3002\u6539\u540D\u540E\u53EF\u4EBA\u5DE5\u6838\u5BF9\u662F\u5426\u9700\u8981\u5408\u5E76 events \u518D\u5220\u3002\u540C\u65F6\u5347\u7EA7\u672C\u673A fabric-cli \u81F3 rc.11+ \u8BA9 server \u4FA7 git-anchor \u751F\u6548\u3002",
2070
+ // legacy_fabric_cache_dir_detected — 老版 recall engine 把 BM25/vector 缓存
2071
+ // 放 `.fabric/cache/{bm25,vectors}`;unify-fabric-cache-dir 后统一到
2072
+ // `.fabric/.cache/` 与 hook sidecar 同处,一条 .gitignore 覆盖两者。老数据
2073
+ // 完好,--fix 仅 rename 迁移。
2074
+ "doctor.check.legacy_fabric_cache_dir_detected.name": "\u8001\u7248 .fabric/cache/ \u76EE\u5F55",
2075
+ "doctor.check.legacy_fabric_cache_dir_detected.ok": "Recall \u7F13\u5B58\u5DF2\u5728 .fabric/.cache/ \u4E0B,\u65E0\u6B8B\u7559 .fabric/cache/{bm25,vectors}\u3002",
2076
+ "doctor.check.legacy_fabric_cache_dir_detected.message": "\u53D1\u73B0 {count} \u4E2A\u8001\u7248 recall \u7F13\u5B58\u76EE\u5F55({dirs})\u3002\u8FD9\u4E9B\u662F unify-fabric-cache-dir \u4E4B\u524D\u7684\u4F4D\u7F6E;\u78C1\u76D8\u4E0A\u7684 BM25 \u5FEB\u7167 / \u5411\u91CF embedding \u6570\u636E\u5B8C\u597D,rename \u5373\u53EF\u4FDD\u7559\u3002",
2077
+ "doctor.check.legacy_fabric_cache_dir_detected.remediation": "\u8DD1 `fabric doctor --fix` \u628A\u6BCF\u4E2A\u8001\u76EE\u5F55 rename \u5230 `.fabric/.cache/` \u5BF9\u5E94\u4F4D\u7F6E(\u5E42\u7B49;\u82E5\u65B0\u8DEF\u5F84\u5DF2\u6709\u66F4\u65B0\u6570\u636E\u5219\u8DF3\u8FC7)\u3002\u4E0D\u6D89\u53CA\u91CD\u65B0 embed,\u5FEB\u7167\u6587\u4EF6\u539F\u6837\u8FC1\u79FB\u3002",
2027
2078
  "doctor.check.skill_md_yaml_invalid.name": "Skill markdown YAML",
2028
2079
  "doctor.check.skill_md_yaml_invalid.ok": "\u6240\u6709 .claude/.codex SKILL.md frontmatter values \u90FD\u80FD\u6309 strict YAML \u89E3\u6790\u3002",
2029
2080
  "doctor.check.skill_md_yaml_invalid.message.singular": "{count} \u4E2A SKILL.md frontmatter value \u5305\u542B\u672A\u52A0\u5F15\u53F7\u7684 ': '\uFF0Cstrict YAML parsers \u4F1A\u62D2\u7EDD\uFF08Claude Code tolerates it\uFF1BCodex CLI drops the skill at load\uFF09\u3002\u9996\u4E2A\uFF1A{detail}\u3002",
@@ -2158,6 +2209,7 @@ var zhCNMessages = {
2158
2209
  // flat-design (G6): 装完最该做的事是重启客户端让 MCP 生效 —— 这才是默认锚点动作;
2159
2210
  // --reapply 维护提示退到 --verbose。
2160
2211
  "cli.install.next-step.restart": "\u91CD\u542F\u5DF2\u5F00\u7684 Claude Code / Codex \u4F1A\u8BDD\u4EE5\u52A0\u8F7D Fabric(\u65B0\u4F1A\u8BDD\u81EA\u52A8\u751F\u6548)\u3002",
2212
+ "cli.install.next-step.nudge-mode": '\u4EBA\u53EF\u89C1\u63D0\u793A\u9ED8\u8BA4 minimal\uFF08\u6BCF\u4F1A\u8BDD\u4E00\u6761\u72B6\u6001\uFF09\u3002\u53EF\u5728 .fabric/fabric-config.json \u8BBE nudge_mode: "silent" \u9759\u97F3\uFF0C\u6216 FABRIC_NUDGE_MODE=silent\uFF1B\u8981\u66F4\u5435\u7528 normal/verbose\u3002',
2161
2213
  "cli.install.reason-message": "{label} {message}",
2162
2214
  "cli.install.language.prompt": "\u9009\u62E9 Fabric \u8BED\u8A00\uFF08\u754C\u9762\u4E0E\u77E5\u8BC6\u7EDF\u4E00\u4F7F\u7528\uFF0C\u4E4B\u540E\u53EF\u7528 fabric config \u4FEE\u6539\uFF09\uFF1A",
2163
2215
  "cli.install.language.option.zh-CN": "\u7B80\u4F53\u4E2D\u6587 (zh-CN)",
@@ -2213,7 +2265,7 @@ var zhCNMessages = {
2213
2265
  "cli.install.semantic.installing": "\u6B63\u5728\u8FD0\u884C `npm i -g fastembed` \u2026",
2214
2266
  "cli.install.semantic.installed": "fastembed \u5B89\u88C5\u5B8C\u6210\u3002\u5D4C\u5165\u6A21\u578B\u4F1A\u5728\u9996\u6B21\u53EC\u56DE (recall) \u65F6\u81EA\u52A8\u4E0B\u8F7D\uFF08\u7EA6\u6570\u5341\u2013\u6570\u767E MB\uFF1B\u4E0D\u4E0A\u4F20\u4EFB\u4F55 KB \u6570\u636E\uFF09\u3002",
2215
2267
  "cli.install.semantic.install-failed": "\u81EA\u52A8\u5B89\u88C5\u5931\u8D25\uFF08{reason}\uFF09\u3002\u8BF7\u624B\u52A8\u6267\u884C\u4E0B\u9762\u7684\u6B65\u9AA4\uFF1A",
2216
- "cli.install.semantic.manual-steps": " 1. \u5B89\u88C5\u53EF\u9009 embedder (\u5411\u91CF\u7F16\u7801\u5668\uFF0C\u88C5\u5230 MCP server \u89E3\u6790\u6A21\u5757\u7684\u4F4D\u7F6E \u2014 \u5168\u5C40\u5B89\u88C5\u5373\u5168\u5C40):\n npm i -g fastembed\n 2. \u9884\u70ED\u6A21\u578B\u7F13\u5B58 (\u9996\u8DD1\u4F1A\u8054\u7F51\u4E0B\u8F7D\u6A21\u578B\u6743\u91CD ~\u6570\u5341-\u6570\u767E MB, \u4E0D\u4E0A\u4F20\u4EFB\u4F55 KB \u6570\u636E):\n export FABRIC_EMBED_CACHE_DIR=~/.cache/fabric-embed # \u4E25\u683C\u79BB\u7EBF\u8005\u9884\u5148\u653E\u597D\u6743\u91CD\n \u6CE8: \u5207\u6362 embed_model \u540E\u5DF2\u6709\u5411\u91CF\u7EF4\u5EA6/\u8BED\u4E49\u53D8\u5316, \u4E0B\u6B21 recall \u4F1A\u6309\u65B0\u6A21\u578B\u91CD\u65B0\u5D4C\u5165 (doc \u5411\u91CF\u6309\u6587\u672C\u7F13\u5B58, \u81EA\u52A8\u5931\u914D\u91CD\u7B97)\u3002\n \u5173\u95ED: \u7F16\u8F91 fabric.config.json \u8BBE embed_enabled=false\u3002",
2268
+ "cli.install.semantic.manual-steps": " 1. \u5B89\u88C5\u53EF\u9009 embedder (\u5411\u91CF\u7F16\u7801\u5668\uFF0C\u88C5\u5230 MCP server \u89E3\u6790\u6A21\u5757\u7684\u4F4D\u7F6E \u2014 \u5168\u5C40\u5B89\u88C5\u5373\u5168\u5C40):\n npm i -g fastembed\n 2. \u9884\u70ED\u6A21\u578B\u7F13\u5B58 (\u9996\u8DD1\u4F1A\u8054\u7F51\u4E0B\u8F7D\u6A21\u578B\u6743\u91CD ~\u6570\u5341-\u6570\u767E MB, \u4E0D\u4E0A\u4F20\u4EFB\u4F55 KB \u6570\u636E):\n export FABRIC_EMBED_CACHE_DIR=~/.cache/fabric-embed # \u4E25\u683C\u79BB\u7EBF\u8005\u9884\u5148\u653E\u597D\u6743\u91CD\n \u6CE8: \u5207\u6362 embed_model \u540E\u5DF2\u6709\u5411\u91CF\u7EF4\u5EA6/\u8BED\u4E49\u53D8\u5316, \u4E0B\u6B21 recall \u4F1A\u6309\u65B0\u6A21\u578B\u91CD\u65B0\u5D4C\u5165 (doc \u5411\u91CF\u6309\u6587\u672C\u7F13\u5B58, \u81EA\u52A8\u5931\u914D\u91CD\u7B97)\u3002\n \u5173\u95ED: \u7F16\u8F91 .fabric/fabric-config.json \u8BBE embed_enabled=false\u3002",
2217
2269
  // C5: store onboarding 交互文案统一走 t()。
2218
2270
  "cli.install.store.local-store": "\u672C\u5730 store",
2219
2271
  "cli.install.store.bind-mounted.prompt": "\u628A\u4E00\u4E2A\u5DF2\u6302\u8F7D\u7684\u77E5\u8BC6 store \u7ED1\u5B9A\u5230\u672C\u9879\u76EE\uFF1F",
@@ -2384,6 +2436,18 @@ var zhCNMessages = {
2384
2436
  "cli.first-hit.args.target.description": "\u9879\u76EE\u6839\uFF08\u9ED8\u8BA4 cwd\uFF09",
2385
2437
  "cli.first-hit.args.seed.description": "\u82E5 store \u4E3A\u7A7A\u5219\u5199\u5165\u6700\u5C0F starter \u77E5\u8BC6\u6761\u76EE",
2386
2438
  "cli.first-hit.args.paths.description": "\u9017\u53F7\u5206\u9694\u7684\u63A2\u6D4B\u8DEF\u5F84",
2439
+ "cli.first-hit.msg.ok": "first-hit \u5C31\u7EEA\uFF1A{stores} \u4E2A store \u5171 {total} \u6761\u77E5\u8BC6\uFF1Bhooks \u5DF2\u5B89\u88C5\u3002",
2440
+ "cli.first-hit.msg.unbound": "unbound\uFF1A\u672C\u9879\u76EE read-set \u672A\u7ED1\u5B9A\u4EFB\u4F55 store\uFF0C\u77E5\u8BC6\u65E0\u6CD5\u6D6E\u73B0\u3002",
2441
+ "cli.first-hit.msg.no_write_target": "no_write_target\uFF1A\u5DF2\u6709 required stores \u4F46\u672A\u8BBE\u7F6E active_write_store\u3002",
2442
+ "cli.first-hit.msg.empty_store": "empty_store\uFF1Astore \u5DF2\u7ED1\u5B9A\u4F46\u89C4\u8303\u77E5\u8BC6\u6587\u4EF6\u4E3A 0 \u2014 \u7A7A store \u4E0D\u662F\u6210\u529F\u8DEF\u5F84\u3002",
2443
+ "cli.first-hit.msg.missing_required": "missing_required\uFF1Arequired_stores \u4E2D\u6709\u672A\u6302\u8F7D\u7684 store\u3002",
2444
+ "cli.first-hit.msg.write_target_mismatch": "write_target_mismatch\uFF1Aactive_write_store \u4E0D\u5728\u5DF2\u6302\u8F7D\u53EF\u5199 read-set \u4E0A\u3002",
2445
+ "cli.first-hit.msg.store_unreachable": "store_unreachable\uFF1A\u5DF2\u7ED1\u5B9A store \u5728\u6CE8\u518C\u8868\u4E2D\u4F46\u78C1\u76D8\u76EE\u5F55\u7F3A\u5931\u3002",
2446
+ "cli.first-hit.msg.project_unsealed": "project_unsealed\uFF1A\u5DF2\u7ED1\u5B9A\u5199\u5E93\u4F46\u7F3A\u5C11 project_id/active_project \u2014 \u56E2\u961F\u77E5\u8BC6\u4F1A\u843D\u6210 flat\uFF08semantic_scope: team\uFF09\u800C\u975E\u9879\u76EE\u5206\u533A\u3002",
2447
+ "cli.first-hit.msg.no_match": "no_match\uFF1A\u77E5\u8BC6\u5B58\u5728\u4F46\u63A2\u6D4B\u9762\u4E3A\u7A7A\uFF08\u8DEF\u5F84/scope \u8FC7\u6EE4\uFF09\u3002",
2448
+ "cli.first-hit.msg.hooks_missing": "hooks_missing\uFF1A\u77E5\u8BC6\u5DF2\u5728\u4F46 SessionStart/PreToolUse hooks \u672A\u5B89\u88C5\u3002",
2449
+ "cli.first-hit.msg.no_project": "no_project\uFF1A\u5F53\u524D\u76EE\u5F55\u4E0D\u662F Fabric \u9879\u76EE\uFF08\u7F3A\u5C11 .fabric/fabric-config.json\uFF09\u3002",
2450
+ "cli.first-hit.msg.no_global": "no_global\uFF1A\u7F3A\u5C11\u5168\u5C40 fabric \u914D\u7F6E \u2014 \u8BF7\u5148\u8FD0\u884C fabric install --global\u3002",
2387
2451
  "cli.onboard-coverage.description": "\u6C47\u603B\u5F53\u524D\u5DE5\u4F5C\u533A\u7684 S5 onboard-slot \u8986\u76D6\u5EA6\u3002fabric-archive Skill \u9996\u8DD1\u9636\u6BB5\u7528\u5B83\u5224\u65AD\u54EA\u4E9B\u9879\u76EE\u8BED\u8C03\u69FD\u4F4D\u5C1A\u672A\u88AB\u8BA4\u9886\u3002",
2388
2452
  "cli.onboard-coverage.args.json.description": "\u8F93\u51FA\u673A\u5668\u53EF\u8BFB\u7684 JSON \u5230 stdout\uFF08\u66FF\u4EE3\u4EBA\u7C7B\u53EF\u8BFB\u7684\u8868\u683C\uFF09\u3002",
2389
2453
  "cli.onboard-coverage.args.target.description": "\u8986\u76D6\u9879\u76EE\u6839\u76EE\u5F55\uFF08\u9ED8\u8BA4\u4E3A\u5F53\u524D\u5DE5\u4F5C\u76EE\u5F55\uFF09\u3002",
@@ -2633,6 +2697,10 @@ var zhCNMessages = {
2633
2697
  "cli.info.recall.vector.not-ready": "\u672A\u5C31\u7EEA \u2014\u2014 \u53EC\u56DE\u56DE\u9000\u5230\u5173\u952E\u8BCD\u6A21\u5F0F(BM25 / additive)",
2634
2698
  "cli.info.recall.warm.ok": "embedder \u5DF2\u9884\u70ED:\u6A21\u578B '{model}' \u5DF2\u52A0\u8F7D(\u5411\u91CF\u7EF4\u5EA6 {dim}),\u7F13\u5B58\u4E8E {dir}",
2635
2699
  "cli.info.recall.warm.fail": "embedder \u4E0D\u53EF\u7528 \u2014\u2014 \u53EF\u9009\u7684 'fastembed' \u5305\u65E0\u6CD5\u89E3\u6790,\u6216\u6A21\u578B\u52A0\u8F7D\u5931\u8D25\u3002\n \u53EC\u56DE\u56DE\u9000\u5230\u5173\u952E\u8BCD\u6A21\u5F0F(BM25 / additive)\u3002\u8BF7\u5728 server \u80FD\u89E3\u6790\u6A21\u5757\u7684\u4F4D\u7F6E\u5B89\u88C5 fastembed \u540E\u91CD\u8BD5\u3002",
2700
+ "cli.store.mount.description": "\u5C06\u77E5\u8BC6 store \u6302\u8F7D\u5230\u5168\u5C40\u6CE8\u518C\u8868",
2701
+ "cli.store.create.description": "\u521B\u5EFA\u5E76\u6302\u8F7D\u672C\u5730\u77E5\u8BC6 store",
2702
+ "cli.store.remove.description": "\u4ECE\u6CE8\u518C\u8868\u5378\u4E0B store\uFF08\u4E0D\u5220\u9664\u78C1\u76D8\uFF09",
2703
+ "cli.store.explain.description": "\u89E3\u91CA store \u522B\u540D\u5982\u4F55\u89E3\u6790",
2636
2704
  "cli.store.list.description": "\u5217\u51FA\u6302\u8F7D\u7684 store",
2637
2705
  // 追加在 `fabric store --help` 末尾的说明 —— 交代进阶(meta.hidden)操作去哪了,
2638
2706
  // 否则只剩 list 一行会让用户以为 store 没别的能力。
@@ -5,7 +5,7 @@ import {
5
5
  enMessages,
6
6
  resolveFabricLocale,
7
7
  zhCNMessages
8
- } from "../chunk-47M6HKBU.js";
8
+ } from "../chunk-WXVFJBL5.js";
9
9
  import {
10
10
  detectNodeLocale,
11
11
  normalizeLocale,
@@ -480,6 +480,7 @@ declare const fabricConfigSchema: z.ZodObject<{
480
480
  hint_dismiss_signals: z.ZodOptional<z.ZodArray<z.ZodEnum<["archive", "review", "import", "maintenance", "narrow", "cite-evict"]>, "many">>;
481
481
  cite_policy_enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
482
482
  self_archive_policy_enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
483
+ altitude_propose_gate: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
483
484
  hint_narrow_top_k: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
484
485
  hint_narrow_dedup_window_turns: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
485
486
  hint_broad_cooldown_hours: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
@@ -524,6 +525,7 @@ declare const fabricConfigSchema: z.ZodObject<{
524
525
  broad_index_backstop: number;
525
526
  cite_policy_enabled: boolean;
526
527
  self_archive_policy_enabled: boolean;
528
+ altitude_propose_gate: boolean;
527
529
  hint_narrow_top_k: number;
528
530
  hint_narrow_dedup_window_turns: number;
529
531
  hint_broad_cooldown_hours: number;
@@ -632,6 +634,7 @@ declare const fabricConfigSchema: z.ZodObject<{
632
634
  hint_dismiss_signals?: ("narrow" | "archive" | "review" | "import" | "maintenance" | "cite-evict")[] | undefined;
633
635
  cite_policy_enabled?: boolean | undefined;
634
636
  self_archive_policy_enabled?: boolean | undefined;
637
+ altitude_propose_gate?: boolean | undefined;
635
638
  hint_narrow_top_k?: number | undefined;
636
639
  hint_narrow_dedup_window_turns?: number | undefined;
637
640
  hint_broad_cooldown_hours?: number | undefined;
@@ -733,6 +736,7 @@ declare const fabricConfigLoadSchema: z.ZodObject<{
733
736
  hint_dismiss_signals: z.ZodOptional<z.ZodArray<z.ZodEnum<["archive", "review", "import", "maintenance", "narrow", "cite-evict"]>, "many">>;
734
737
  cite_policy_enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
735
738
  self_archive_policy_enabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
739
+ altitude_propose_gate: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
736
740
  hint_narrow_top_k: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
737
741
  hint_narrow_dedup_window_turns: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
738
742
  hint_broad_cooldown_hours: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
@@ -788,6 +792,7 @@ declare const fabricConfigLoadSchema: z.ZodObject<{
788
792
  broad_index_backstop: number;
789
793
  cite_policy_enabled: boolean;
790
794
  self_archive_policy_enabled: boolean;
795
+ altitude_propose_gate: boolean;
791
796
  hint_narrow_top_k: number;
792
797
  hint_narrow_dedup_window_turns: number;
793
798
  hint_broad_cooldown_hours: number;
@@ -896,6 +901,7 @@ declare const fabricConfigLoadSchema: z.ZodObject<{
896
901
  hint_dismiss_signals?: ("narrow" | "archive" | "review" | "import" | "maintenance" | "cite-evict")[] | undefined;
897
902
  cite_policy_enabled?: boolean | undefined;
898
903
  self_archive_policy_enabled?: boolean | undefined;
904
+ altitude_propose_gate?: boolean | undefined;
899
905
  hint_narrow_top_k?: number | undefined;
900
906
  hint_narrow_dedup_window_turns?: number | undefined;
901
907
  hint_broad_cooldown_hours?: number | undefined;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { A as AgentsMetaNode, a as AgentsIdentitySource, b as AgentsTopologyType, H as HumanLockEntry, f as fabricConfigSchema, S as StoreIdentity, c as StoreProject, G as GlobalConfig, F as FabricConfig, M as MountedStore, R as RequiredStoreEntry, d as AgentsMeta, L as LedgerEntry } from './index-B2e0wKJi.js';
2
- export { e as AgentsMetaCountersEnvelope, g as AgentsMetaKnowledgeTypeCounters, h as AiLedgerEntry, i as AuditMode, C as ClientPaths, D as DefaultLayerFilter, j as FabricLanguage, k as GLOBAL_BINDINGS_DIR, l as GLOBAL_STATE_DIR, m as HumanLedgerEntry, n as McpPayloadLimits, P as PERSONAL_STORE_SENTINEL, o as RecallScore, p as RecallScoreBreakdown, q as RuleDescription, r as RuleDescriptionIndexItem, s as STORES_ROOT_DIR, t as STORE_ALIAS_PATTERN, u as STORE_KNOWLEDGE_TYPE_DIRS, v as STORE_LAYOUT, w as STORE_MOUNT_GROUPS, x as STORE_MOUNT_NAME_PATTERN, y as STORE_PROJECT_ID_PATTERN, z as STORE_UUID_PATTERN, B as StoreLayout, E as StoreMountGroup, I as StoreProjectsFile, J as auditModeSchema, K as clientPathsSchema, N as defaultLayerFilterSchema, O as deriveMountLabel, Q as fabricConfigLoadSchema, T as fabricLanguageSchema, U as globalConfigSchema, V as isNonPersonalRequiredStore, W as mcpPayloadLimitsSchema, X as migrateRequiredStores, Y as mountedStoreSchema, Z as nudgeModeSchema, _ as observeConfigSchema, $ as planContextTopKSchema, a0 as requiredStoreEntrySchema, a1 as selectionTokenTtlMsSchema, a2 as storeAliasSchema, a3 as storeIdentitySchema, a4 as storeKnowledgeTypeDir, a5 as storeMountGroup, a6 as storeMountNameSchema, a7 as storeMountSubPath, a8 as storeProjectSchema, a9 as storeProjectsFileSchema, aa as storeRelativePath, ab as storeRelativePathForMount, ac as storeUuidSchema, ad as writeRouteSchema } from './index-B2e0wKJi.js';
1
+ import { A as AgentsMetaNode, a as AgentsIdentitySource, b as AgentsTopologyType, H as HumanLockEntry, f as fabricConfigSchema, S as StoreIdentity, c as StoreProject, G as GlobalConfig, F as FabricConfig, M as MountedStore, R as RequiredStoreEntry, d as AgentsMeta, L as LedgerEntry } from './index-KvxqMZV1.js';
2
+ export { e as AgentsMetaCountersEnvelope, g as AgentsMetaKnowledgeTypeCounters, h as AiLedgerEntry, i as AuditMode, C as ClientPaths, D as DefaultLayerFilter, j as FabricLanguage, k as GLOBAL_BINDINGS_DIR, l as GLOBAL_STATE_DIR, m as HumanLedgerEntry, n as McpPayloadLimits, P as PERSONAL_STORE_SENTINEL, o as RecallScore, p as RecallScoreBreakdown, q as RuleDescription, r as RuleDescriptionIndexItem, s as STORES_ROOT_DIR, t as STORE_ALIAS_PATTERN, u as STORE_KNOWLEDGE_TYPE_DIRS, v as STORE_LAYOUT, w as STORE_MOUNT_GROUPS, x as STORE_MOUNT_NAME_PATTERN, y as STORE_PROJECT_ID_PATTERN, z as STORE_UUID_PATTERN, B as StoreLayout, E as StoreMountGroup, I as StoreProjectsFile, J as auditModeSchema, K as clientPathsSchema, N as defaultLayerFilterSchema, O as deriveMountLabel, Q as fabricConfigLoadSchema, T as fabricLanguageSchema, U as globalConfigSchema, V as isNonPersonalRequiredStore, W as mcpPayloadLimitsSchema, X as migrateRequiredStores, Y as mountedStoreSchema, Z as nudgeModeSchema, _ as observeConfigSchema, $ as planContextTopKSchema, a0 as requiredStoreEntrySchema, a1 as selectionTokenTtlMsSchema, a2 as storeAliasSchema, a3 as storeIdentitySchema, a4 as storeKnowledgeTypeDir, a5 as storeMountGroup, a6 as storeMountNameSchema, a7 as storeMountSubPath, a8 as storeProjectSchema, a9 as storeProjectsFileSchema, aa as storeRelativePath, ab as storeRelativePathForMount, ac as storeUuidSchema, ad as writeRouteSchema } from './index-KvxqMZV1.js';
3
3
  import { T as Translator } from './types-qg4xXVuT.js';
4
4
  export { L as Locale, M as Messages, a as TranslationKey } from './types-qg4xXVuT.js';
5
5
  export { PROTECTED_TOKENS, ProtectedToken, createTranslator, defaultMessages, detectNodeLocale, enMessages, normalizeLocale, resolveFabricLocale, resolveGlobalLocale, zhCNMessages } from './i18n/index.js';
@@ -1159,6 +1159,12 @@ interface PanelFieldMeta {
1159
1159
  readonly key: PanelFieldKey;
1160
1160
  /** Logical grouping for panel section headers. */
1161
1161
  readonly group: PanelFieldGroup;
1162
+ /**
1163
+ * JSON value type of the stored config value. Drives non-interactive
1164
+ * `fabric config --get/--set/--list` coercion + display; orthogonal to
1165
+ * `widget` (UI presentation) and `enum_values` (allowed set).
1166
+ */
1167
+ readonly type: "boolean" | "number" | "string";
1162
1168
  /** Clack widget hint — `select` for enums, `text` for free-form numbers. */
1163
1169
  readonly widget: "select" | "text";
1164
1170
  /** i18n key for the field label; strings landed in TASK-006. */
@@ -2787,22 +2793,6 @@ declare function readStoreCounters(storeDir: string): AgentsMetaCounters;
2787
2793
  * KnowledgeIdAllocator held over agents.meta).
2788
2794
  */
2789
2795
  declare function allocateStoreKnowledgeId(layer: Layer, type: KnowledgeType, storeDir: string): Promise<StableId>;
2790
- /**
2791
- * Floor a store's `counters.json` at the highest stable_id actually present on
2792
- * disk, persisting and returning the reconciled envelope.
2793
- *
2794
- * This is the producer↔consumer bridge (W4 F1): a BULK import
2795
- * writes entries whose ids were minted elsewhere (collision-remapped from
2796
- * disk-max) WITHOUT advancing this store's counters.json. Without reconciliation
2797
- * the next `allocateStoreKnowledgeId` would start from a stale zero and re-mint
2798
- * an already-present id. Flooring is also the self-heal `doctor` runs to repair a
2799
- * drifted ledger.
2800
- *
2801
- * Floor — never lower — preserves the monotonic invariant (KT-DEC-0004): a slot
2802
- * already advanced past disk-max (because the highest entry was deleted) keeps
2803
- * its higher value. Sync write (no lock) because the only callers run in
2804
- * exclusive one-shot contexts (post-migrate CLI step, `doctor --fix`).
2805
- */
2806
2796
  declare function reconcileStoreCounters(storeDir: string): AgentsMetaCounters;
2807
2797
 
2808
2798
  declare function resolveGlobalRoot(): string;
@@ -2833,6 +2823,17 @@ declare function redactSecrets(content: string): string;
2833
2823
  declare function redactPii(content: string): string;
2834
2824
  declare function scrubRemoteUrl(remote: string): string;
2835
2825
 
2826
+ /**
2827
+ * ISS-20260713-005: protocol allowlist for git remotes used by
2828
+ * `fabric install --global <url>` / store create --remote / git remote add.
2829
+ *
2830
+ * `git clone -- <url>` only blocks option injection; `ext::`, `file://`, and
2831
+ * other helpers remain executable as a repository argument. Reject anything
2832
+ * outside https / http / ssh / scp-like git@host:path / git:// before spawn.
2833
+ */
2834
+ declare function isAllowedGitRemote(remote: string): boolean;
2835
+ declare function assertAllowedGitRemote(remote: string): string;
2836
+
2836
2837
  type ScanRecommendationInput = {
2837
2838
  frameworkKind: string;
2838
2839
  hasMeta?: boolean;
@@ -11373,4 +11374,4 @@ declare function isHighValueArchiveCandidate(events: unknown, sessionId: string
11373
11374
  */
11374
11375
  declare function tokenize(text: string): string[];
11375
11376
 
11376
- export { AGENTS_META_IDENTITY_SOURCES, AGENTS_META_TOPOLOGY_TYPES, AgentsIdentitySource, AgentsMeta, type AgentsMetaCounters, AgentsMetaCountersSchema, AgentsMetaNode, AgentsTopologyType, type AssistantTurnObservedEvent, type CandidateFileEntry, type CandidateFileFamily, type CiteCommitment, type CiteCommitmentOperator, type CiteCommitmentOperatorKind, type CiteContractPolicyActivatedEvent, type CitePolicyActivatedEvent, type CiteTag, type ClaudeHookPathMigratedEvent, type ClaudeSkillPathMigratedEvent, type ClientCapabilitySnapshotEvent, type CodexSkillPathMigratedEvent, type CrossStoreLintInput, type CrossStoreRefViolation, type DebugBundle, type DebugBundleInput, type DoctorRunEvent, type DriftDetectedEvent, type EditIntentCheckedEvent, type EntryLayer, type EntryScopeMetadata, type EventLedgerEvent, type EventLedgerEventInput, type EventLedgerEventType, type EventLedgerTruncatedEvent, type EventsRotatedEvent, FabricConfig, type FabricConfigSchemaShape, type FabricEvent, type FailureStage, type FailureTrace, type FileMutatedEvent, type FindStoreExecutableViolationsOptions, type ForensicAssertion, type ForensicAssertionConfidence, type ForensicAssertionCoverage, type ForensicAssertionType, type ForensicCodeSample, type ForensicEntryPoint, type ForensicEvidenceAnchor, type ForensicFramework, type ForensicReadme, type ForensicReport, type ForensicSamplingBudget, type ForensicTopology, GLOBAL_REF_PATTERN, GlobalConfig, type GlobalRef, type GraphEdgeCandidateRequestedEvent, type HookSignalEmittedEvent, type HookSurfaceEmittedEvent, HumanLockEntry, type HumanLockFile, type InitContext, type InitContextDomainGroup, type InitContextFramework, type InitContextInterviewTrailEntry, type InitContextInvariant, type InitContextInvariantConfidenceSnapshot, type InitContextSourceEvidence, type InitScanCompletedEvent, type InitStoreOptions, type InstallDiffAppliedEvent, KNOWLEDGE_TEST_INDEX_SCHEMA_VERSION, KNOWN_SCOPE_PREFIXES, type KnowledgeArchiveAttemptedEvent, type KnowledgeArchivedEvent, type KnowledgeBodyReadEvent, type KnowledgeConsumedEvent, type KnowledgeContextPlannedEvent, type KnowledgeDeferredEvent, type KnowledgeDemotedEvent, type KnowledgeDriftDetectedEvent, type KnowledgeEnrichedEvent, type KnowledgeIdRedirectEvent, type KnowledgeLayerChangedEvent, type KnowledgeMetaAutoHealedEvent, type KnowledgeModifiedEvent, type KnowledgePathDangledEvent, type KnowledgePromoteFailedEvent, type KnowledgePromoteStartedEvent, type KnowledgePromotedEvent, type KnowledgeProposedEvent, type KnowledgeProvenance, type KnowledgeRejectedEvent, type KnowledgeScopeDegradedEvent, type KnowledgeSectionsFetchedEvent, type KnowledgeSelectionEvent, type KnowledgeSlugRenamedEvent, type KnowledgeTestIndex, type KnowledgeTestLink, type KnowledgeTestOrphanAnnotation, KnowledgeType, type KnowledgeUnarchivedEvent, Layer, type LedgerAppendedEvent, LedgerEntry, type LlmJudgeRunEvent, type LocalKnowledgeId, type LockApprovedEvent, type LockDriftEvent, MCP_STORE_AWARE_CONTRACTS, MCP_STORE_AWARE_TOOLS, type McpEventLedgerEvent, type McpStdioTraceEvent, type McpStoreAwareContract, type McpStoreAwareTool, type MetaReconciledEvent, type MetaReconciledOnStartupEvent, type MetaUpdatedEvent, MountedStore, type MountedStoreDir, type NarrowHintFailedEvent, ONBOARD_SLOT_NAMES, ONBOARD_SLOT_TOTAL, type OnboardSlot, PARITY_CLIENTS, PARITY_SURFACES, PERSONAL_SCOPE, PROJECT_ROOT_SIGNALS, type PanelFieldGroup, type PanelFieldKey, type PanelFieldMeta, type ParityCapability, type ParityClient, type ParityClientExpectation, type ParityMatrix, type ParitySurface, type ParseCiteLineResult, type ParsedGlobalRef, type PayloadGuardObservedEvent, type PendingAutoArchivedEvent, type PrecompactObservedEvent, type ProjectRootGoldenCase, type ProjectRootResolution, type ProjectRootResolver, type ProjectRootSignal, type ProjectRootSignals, type QualifiedCandidate, type QualifiedIdResolution, REDACTION_PLACEHOLDER_PREFIX, type ReadSetEntry, type ReadSetGoldenCase, type ReapplyCompletedEvent, type RelevanceMigrationRunEvent, RequiredStoreEntry, type ResolutionCandidate, type ResolutionResult, type ResolutionWarning, type ResolveOptions, type ResolvedBindingsSnapshot, type ResolvedEntry, SCOPE_COORDINATE_HINT, SCOPE_COORDINATE_PATTERN, STORE_GITIGNORE, STORE_PENDING_DIR, STORE_RESOLVER_WARNING_CODES, type ScanRecommendationInput, type ScopeCoordinate, type SecretFinding, type ServeLockClearedEvent, type SessionArchiveAttemptedEvent, type SessionEndedEvent, type SkillInvocationCompletedEvent, type SkillInvocationStartedEvent, type SkillPhaseTransitionEvent, type SkillTriggerCandidateEvent, StableId, type StoreAwareEntry, type StoreBoundEvent, type StoreCounters, type StoreDetachedEvent, type StoreExplain, StoreIdentity, type StoreKnowledgeRef, type StoreMountedEvent, StoreProject, type StoreReadSet, type StoreResolveInput, type StoreResolver, type StoreResolverWarning, type StoreResolverWarningCode, type StoreVisibility, Translator, UID_SEGMENT_PATTERN, type Uid, type ValidateResult, type WriteBindingsSnapshotOptions, type WriteRouteChangedEvent, type WriteStoreSwitchedEvent, type WriteTarget, type WrittenToStore, addMountedStore, addStoreProject, agentsIdentitySourceSchema, agentsMetaNodeSchema, agentsMetaSchema, agentsTopologyTypeSchema, aggregatePendingAcrossStores, aiLedgerEntrySchema, allocateKnowledgeId, allocateStoreKnowledgeId, assistantTurnObservedEventSchema, bindRequiredStore, bindingsSnapshotPath, buildDebugBundle, buildFailureTrace, buildScanRecommendations, buildStoreResolveInput, candidateFileEntrySchema, citeContractPolicyActivatedEventSchema, citePolicyActivatedEventSchema, claudeHookPathMigratedEventSchema, claudeSkillPathMigratedEventSchema, clientCapabilitySnapshotEventSchema, codexSkillPathMigratedEventSchema, createProjectRootResolver, createStoreResolver, defaultAgentsMetaCounters, deriveAgentsMetaIdentitySource, deriveAgentsMetaStableId, deriveAgentsMetaTopologyType, detachMountedStore, disambiguateAlias, doctorRunEventSchema, driftDetectedEventSchema, editIntentCheckedEventSchema, entryScopeMetadataSchema, eventLedgerEventSchema, eventLedgerTruncatedEventSchema, eventsRotatedEventSchema, explainStore, fabricConfigSchema, fabricEventSchema, fileMutatedEventSchema, findMountedStore, findStoreExecutableViolations, forensicAssertionCoverageSchema, forensicAssertionSchema, forensicCodeSampleSchema, forensicEntryPointSchema, forensicEvidenceAnchorSchema, forensicFrameworkSchema, forensicReadmeSchema, forensicReportSchema, forensicSamplingBudgetSchema, forensicTopologySchema, formatGlobalRef, getPanelFieldByKey, getPanelFields, globalConfigPath, globalRefSchema, graphEdgeCandidateRequestedEventSchema, hasSecrets, hookSignalEmittedEventSchema, hookSurfaceEmittedEventSchema, humanLedgerEntrySchema, humanLockEntrySchema, humanLockFileSchema, initContextDomainGroupSchema, initContextFrameworkSchema, initContextInterviewTrailEntrySchema, initContextInvariantConfidenceSnapshotSchema, initContextInvariantSchema, initContextSchema, initContextSourceEvidenceSchema, initScanCompletedEventSchema, initStore, installDiffAppliedEventSchema, isHighValueArchiveCandidate, isKnowledgeStableId, isPersonalLeakIntoSharedStore, isPersonalScope, knowledgeArchiveAttemptedEventSchema, knowledgeArchivedEventSchema, knowledgeBodyReadEventSchema, knowledgeConsumedEventSchema, knowledgeContextPlannedEventSchema, knowledgeDeferredEventSchema, knowledgeDemotedEventSchema, knowledgeDriftDetectedEventSchema, knowledgeEnrichedEventSchema, knowledgeIdRedirectEventSchema, knowledgeLayerChangedEventSchema, knowledgeMetaAutoHealedEventSchema, knowledgeModifiedEventSchema, knowledgePathDangledEventSchema, knowledgePromoteFailedEventSchema, knowledgePromoteStartedEventSchema, knowledgePromotedEventSchema, knowledgeProposedEventSchema, knowledgeProvenanceSchema, knowledgeRejectedEventSchema, knowledgeScopeDegradedEventSchema, knowledgeSectionsFetchedEventSchema, knowledgeSelectionEventSchema, knowledgeSlugRenamedEventSchema, knowledgeTestIndexSchema, knowledgeTestLinkSchema, knowledgeTestOrphanAnnotationSchema, knowledgeUnarchivedEventSchema, ledgerAppendedEventSchema, ledgerEntrySchema, lintCrossStoreReferences, listStoreKnowledge, llmJudgeRunEventSchema, loadGlobalConfig, loadProjectConfig, localKnowledgeIdSchema, lockApprovedEventSchema, lockDriftEventSchema, mcpEventLedgerEventSchema, mcpStdioTraceEventSchema, metaReconciledEventSchema, metaReconciledOnStartupEventSchema, metaUpdatedEventSchema, narrowHintFailedEventSchema, normalizeCiteTag, onboardSlotSchema, parityCapabilitySchema, parityClientExpectationSchema, parityClientSchema, parityMatrixSchema, paritySurfaceSchema, parseCiteLine, parseGlobalRef, payloadGuardObservedEventSchema, pendingAutoArchivedEventSchema, precompactObservedEventSchema, projectConfigPath, projectRootGoldenCaseSchema, projectRootGoldenFileSchema, projectRootResolutionSchema, projectRootSignalSchema, projectRootSignalsSchema, readBindingsSnapshot, readKnowledgeAcrossStores, readSetEntrySchema, readSetGoldenCaseSchema, readSetGoldenFileSchema, readStoreCounters, readStoreIdentity, readStoreIdentityAsync, readStoreProjects, reapplyCompletedEventSchema, recognizeStoreDir, reconcileStoreCounters, redactPii, redactSecrets, relevanceMigrationRunEventSchema, resolveCandidates, resolveGlobalRoot, resolveStoreQualifiedId, resolveWorkspaceBindingId, resolvedBindingsSnapshotSchema, ruleDescriptionIndexItemSchema, ruleDescriptionSchema, saveGlobalConfig, saveGlobalConfigAsync, saveProjectConfig, scanForSecrets, scopeCoordinateSchema, scopeRoot, scrubRemoteUrl, serveLockClearedEventSchema, sessionArchiveAttemptedEventSchema, sessionEndedEventSchema, skillInvocationCompletedEventSchema, skillInvocationStartedEventSchema, skillPhaseTransitionEventSchema, skillTriggerCandidateEventSchema, storeAwareEntrySchema, storeBoundEventSchema, storeCountersPath, storeCountersSchema, storeDetachedEventSchema, storeHasProject, storeMountedEventSchema, storeReadSetSchema, storeResolveInputSchema, storeResolverWarningCodeSchema, storeResolverWarningSchema, tokenize, uidSchema, withDerivedAgentsMetaNodeDefaults, writeBindingsSnapshot, writeRouteChangedEventSchema, writeStoreSwitchedEventSchema, writeTargetSchema, writtenToStoreSchema };
11377
+ export { AGENTS_META_IDENTITY_SOURCES, AGENTS_META_TOPOLOGY_TYPES, AgentsIdentitySource, AgentsMeta, type AgentsMetaCounters, AgentsMetaCountersSchema, AgentsMetaNode, AgentsTopologyType, type AssistantTurnObservedEvent, type CandidateFileEntry, type CandidateFileFamily, type CiteCommitment, type CiteCommitmentOperator, type CiteCommitmentOperatorKind, type CiteContractPolicyActivatedEvent, type CitePolicyActivatedEvent, type CiteTag, type ClaudeHookPathMigratedEvent, type ClaudeSkillPathMigratedEvent, type ClientCapabilitySnapshotEvent, type CodexSkillPathMigratedEvent, type CrossStoreLintInput, type CrossStoreRefViolation, type DebugBundle, type DebugBundleInput, type DoctorRunEvent, type DriftDetectedEvent, type EditIntentCheckedEvent, type EntryLayer, type EntryScopeMetadata, type EventLedgerEvent, type EventLedgerEventInput, type EventLedgerEventType, type EventLedgerTruncatedEvent, type EventsRotatedEvent, FabricConfig, type FabricConfigSchemaShape, type FabricEvent, type FailureStage, type FailureTrace, type FileMutatedEvent, type FindStoreExecutableViolationsOptions, type ForensicAssertion, type ForensicAssertionConfidence, type ForensicAssertionCoverage, type ForensicAssertionType, type ForensicCodeSample, type ForensicEntryPoint, type ForensicEvidenceAnchor, type ForensicFramework, type ForensicReadme, type ForensicReport, type ForensicSamplingBudget, type ForensicTopology, GLOBAL_REF_PATTERN, GlobalConfig, type GlobalRef, type GraphEdgeCandidateRequestedEvent, type HookSignalEmittedEvent, type HookSurfaceEmittedEvent, HumanLockEntry, type HumanLockFile, type InitContext, type InitContextDomainGroup, type InitContextFramework, type InitContextInterviewTrailEntry, type InitContextInvariant, type InitContextInvariantConfidenceSnapshot, type InitContextSourceEvidence, type InitScanCompletedEvent, type InitStoreOptions, type InstallDiffAppliedEvent, KNOWLEDGE_TEST_INDEX_SCHEMA_VERSION, KNOWN_SCOPE_PREFIXES, type KnowledgeArchiveAttemptedEvent, type KnowledgeArchivedEvent, type KnowledgeBodyReadEvent, type KnowledgeConsumedEvent, type KnowledgeContextPlannedEvent, type KnowledgeDeferredEvent, type KnowledgeDemotedEvent, type KnowledgeDriftDetectedEvent, type KnowledgeEnrichedEvent, type KnowledgeIdRedirectEvent, type KnowledgeLayerChangedEvent, type KnowledgeMetaAutoHealedEvent, type KnowledgeModifiedEvent, type KnowledgePathDangledEvent, type KnowledgePromoteFailedEvent, type KnowledgePromoteStartedEvent, type KnowledgePromotedEvent, type KnowledgeProposedEvent, type KnowledgeProvenance, type KnowledgeRejectedEvent, type KnowledgeScopeDegradedEvent, type KnowledgeSectionsFetchedEvent, type KnowledgeSelectionEvent, type KnowledgeSlugRenamedEvent, type KnowledgeTestIndex, type KnowledgeTestLink, type KnowledgeTestOrphanAnnotation, KnowledgeType, type KnowledgeUnarchivedEvent, Layer, type LedgerAppendedEvent, LedgerEntry, type LlmJudgeRunEvent, type LocalKnowledgeId, type LockApprovedEvent, type LockDriftEvent, MCP_STORE_AWARE_CONTRACTS, MCP_STORE_AWARE_TOOLS, type McpEventLedgerEvent, type McpStdioTraceEvent, type McpStoreAwareContract, type McpStoreAwareTool, type MetaReconciledEvent, type MetaReconciledOnStartupEvent, type MetaUpdatedEvent, MountedStore, type MountedStoreDir, type NarrowHintFailedEvent, ONBOARD_SLOT_NAMES, ONBOARD_SLOT_TOTAL, type OnboardSlot, PARITY_CLIENTS, PARITY_SURFACES, PERSONAL_SCOPE, PROJECT_ROOT_SIGNALS, type PanelFieldGroup, type PanelFieldKey, type PanelFieldMeta, type ParityCapability, type ParityClient, type ParityClientExpectation, type ParityMatrix, type ParitySurface, type ParseCiteLineResult, type ParsedGlobalRef, type PayloadGuardObservedEvent, type PendingAutoArchivedEvent, type PrecompactObservedEvent, type ProjectRootGoldenCase, type ProjectRootResolution, type ProjectRootResolver, type ProjectRootSignal, type ProjectRootSignals, type QualifiedCandidate, type QualifiedIdResolution, REDACTION_PLACEHOLDER_PREFIX, type ReadSetEntry, type ReadSetGoldenCase, type ReapplyCompletedEvent, type RelevanceMigrationRunEvent, RequiredStoreEntry, type ResolutionCandidate, type ResolutionResult, type ResolutionWarning, type ResolveOptions, type ResolvedBindingsSnapshot, type ResolvedEntry, SCOPE_COORDINATE_HINT, SCOPE_COORDINATE_PATTERN, STORE_GITIGNORE, STORE_PENDING_DIR, STORE_RESOLVER_WARNING_CODES, type ScanRecommendationInput, type ScopeCoordinate, type SecretFinding, type ServeLockClearedEvent, type SessionArchiveAttemptedEvent, type SessionEndedEvent, type SkillInvocationCompletedEvent, type SkillInvocationStartedEvent, type SkillPhaseTransitionEvent, type SkillTriggerCandidateEvent, StableId, type StoreAwareEntry, type StoreBoundEvent, type StoreCounters, type StoreDetachedEvent, type StoreExplain, StoreIdentity, type StoreKnowledgeRef, type StoreMountedEvent, StoreProject, type StoreReadSet, type StoreResolveInput, type StoreResolver, type StoreResolverWarning, type StoreResolverWarningCode, type StoreVisibility, Translator, UID_SEGMENT_PATTERN, type Uid, type ValidateResult, type WriteBindingsSnapshotOptions, type WriteRouteChangedEvent, type WriteStoreSwitchedEvent, type WriteTarget, type WrittenToStore, addMountedStore, addStoreProject, agentsIdentitySourceSchema, agentsMetaNodeSchema, agentsMetaSchema, agentsTopologyTypeSchema, aggregatePendingAcrossStores, aiLedgerEntrySchema, allocateKnowledgeId, allocateStoreKnowledgeId, assertAllowedGitRemote, assistantTurnObservedEventSchema, bindRequiredStore, bindingsSnapshotPath, buildDebugBundle, buildFailureTrace, buildScanRecommendations, buildStoreResolveInput, candidateFileEntrySchema, citeContractPolicyActivatedEventSchema, citePolicyActivatedEventSchema, claudeHookPathMigratedEventSchema, claudeSkillPathMigratedEventSchema, clientCapabilitySnapshotEventSchema, codexSkillPathMigratedEventSchema, createProjectRootResolver, createStoreResolver, defaultAgentsMetaCounters, deriveAgentsMetaIdentitySource, deriveAgentsMetaStableId, deriveAgentsMetaTopologyType, detachMountedStore, disambiguateAlias, doctorRunEventSchema, driftDetectedEventSchema, editIntentCheckedEventSchema, entryScopeMetadataSchema, eventLedgerEventSchema, eventLedgerTruncatedEventSchema, eventsRotatedEventSchema, explainStore, fabricConfigSchema, fabricEventSchema, fileMutatedEventSchema, findMountedStore, findStoreExecutableViolations, forensicAssertionCoverageSchema, forensicAssertionSchema, forensicCodeSampleSchema, forensicEntryPointSchema, forensicEvidenceAnchorSchema, forensicFrameworkSchema, forensicReadmeSchema, forensicReportSchema, forensicSamplingBudgetSchema, forensicTopologySchema, formatGlobalRef, getPanelFieldByKey, getPanelFields, globalConfigPath, globalRefSchema, graphEdgeCandidateRequestedEventSchema, hasSecrets, hookSignalEmittedEventSchema, hookSurfaceEmittedEventSchema, humanLedgerEntrySchema, humanLockEntrySchema, humanLockFileSchema, initContextDomainGroupSchema, initContextFrameworkSchema, initContextInterviewTrailEntrySchema, initContextInvariantConfidenceSnapshotSchema, initContextInvariantSchema, initContextSchema, initContextSourceEvidenceSchema, initScanCompletedEventSchema, initStore, installDiffAppliedEventSchema, isAllowedGitRemote, isHighValueArchiveCandidate, isKnowledgeStableId, isPersonalLeakIntoSharedStore, isPersonalScope, knowledgeArchiveAttemptedEventSchema, knowledgeArchivedEventSchema, knowledgeBodyReadEventSchema, knowledgeConsumedEventSchema, knowledgeContextPlannedEventSchema, knowledgeDeferredEventSchema, knowledgeDemotedEventSchema, knowledgeDriftDetectedEventSchema, knowledgeEnrichedEventSchema, knowledgeIdRedirectEventSchema, knowledgeLayerChangedEventSchema, knowledgeMetaAutoHealedEventSchema, knowledgeModifiedEventSchema, knowledgePathDangledEventSchema, knowledgePromoteFailedEventSchema, knowledgePromoteStartedEventSchema, knowledgePromotedEventSchema, knowledgeProposedEventSchema, knowledgeProvenanceSchema, knowledgeRejectedEventSchema, knowledgeScopeDegradedEventSchema, knowledgeSectionsFetchedEventSchema, knowledgeSelectionEventSchema, knowledgeSlugRenamedEventSchema, knowledgeTestIndexSchema, knowledgeTestLinkSchema, knowledgeTestOrphanAnnotationSchema, knowledgeUnarchivedEventSchema, ledgerAppendedEventSchema, ledgerEntrySchema, lintCrossStoreReferences, listStoreKnowledge, llmJudgeRunEventSchema, loadGlobalConfig, loadProjectConfig, localKnowledgeIdSchema, lockApprovedEventSchema, lockDriftEventSchema, mcpEventLedgerEventSchema, mcpStdioTraceEventSchema, metaReconciledEventSchema, metaReconciledOnStartupEventSchema, metaUpdatedEventSchema, narrowHintFailedEventSchema, normalizeCiteTag, onboardSlotSchema, parityCapabilitySchema, parityClientExpectationSchema, parityClientSchema, parityMatrixSchema, paritySurfaceSchema, parseCiteLine, parseGlobalRef, payloadGuardObservedEventSchema, pendingAutoArchivedEventSchema, precompactObservedEventSchema, projectConfigPath, projectRootGoldenCaseSchema, projectRootGoldenFileSchema, projectRootResolutionSchema, projectRootSignalSchema, projectRootSignalsSchema, readBindingsSnapshot, readKnowledgeAcrossStores, readSetEntrySchema, readSetGoldenCaseSchema, readSetGoldenFileSchema, readStoreCounters, readStoreIdentity, readStoreIdentityAsync, readStoreProjects, reapplyCompletedEventSchema, recognizeStoreDir, reconcileStoreCounters, redactPii, redactSecrets, relevanceMigrationRunEventSchema, resolveCandidates, resolveGlobalRoot, resolveStoreQualifiedId, resolveWorkspaceBindingId, resolvedBindingsSnapshotSchema, ruleDescriptionIndexItemSchema, ruleDescriptionSchema, saveGlobalConfig, saveGlobalConfigAsync, saveProjectConfig, scanForSecrets, scopeCoordinateSchema, scopeRoot, scrubRemoteUrl, serveLockClearedEventSchema, sessionArchiveAttemptedEventSchema, sessionEndedEventSchema, skillInvocationCompletedEventSchema, skillInvocationStartedEventSchema, skillPhaseTransitionEventSchema, skillTriggerCandidateEventSchema, storeAwareEntrySchema, storeBoundEventSchema, storeCountersPath, storeCountersSchema, storeDetachedEventSchema, storeHasProject, storeMountedEventSchema, storeReadSetSchema, storeResolveInputSchema, storeResolverWarningCodeSchema, storeResolverWarningSchema, tokenize, uidSchema, withDerivedAgentsMetaNodeDefaults, writeBindingsSnapshot, writeRouteChangedEventSchema, writeStoreSwitchedEventSchema, writeTargetSchema, writtenToStoreSchema };
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  BOOTSTRAP_REGEX,
8
8
  matchBootstrapCanonicalLocale,
9
9
  resolveBootstrapCanonical
10
- } from "./chunk-DNIICOSG.js";
10
+ } from "./chunk-V7IUN5U2.js";
11
11
  import "./chunk-LXNCAKJZ.js";
12
12
  import {
13
13
  PROTECTED_TOKENS,
@@ -16,7 +16,7 @@ import {
16
16
  enMessages,
17
17
  resolveFabricLocale,
18
18
  zhCNMessages
19
- } from "./chunk-47M6HKBU.js";
19
+ } from "./chunk-WXVFJBL5.js";
20
20
  import {
21
21
  GLOBAL_BINDINGS_DIR,
22
22
  GLOBAL_STATE_DIR,
@@ -656,6 +656,11 @@ var fabricConfigSchema = z5.object({
656
656
  // relieve; until then they ship as inert-safe opt-outs.
657
657
  cite_policy_enabled: z5.boolean().optional().default(true),
658
658
  self_archive_policy_enabled: z5.boolean().optional().default(true),
659
+ // Peer micro-transfer P0-2: when true, fab_propose hard-refuses dump-shaped
660
+ // session_context / bodies (body altitude). Default false = warn-and-still-write
661
+ // so corpus recovery stays non-blocking. Env FABRIC_ALTITUDE_PROPOSE_GATE=1
662
+ // overrides this to true for CI/dogfood. Power-user JSON only (not on config TUI).
663
+ altitude_propose_gate: z5.boolean().optional().default(false),
659
664
  // v2.0.0-rc.33 W2-1 (P0-9): TopK upper bound for the narrow PreToolUse hint
660
665
  // emitted by knowledge-hint-narrow.cjs. After filtering to entries whose
661
666
  // `relevance_scope === "narrow"` (rc.27 TASK-005 audit §2.5 fix), the hook
@@ -678,10 +683,13 @@ var fabricConfigSchema = z5.object({
678
683
  // fabric-hint Stop hook — knowledge-hint-broad re-fires on every
679
684
  // SessionStart by default (compact / clear / new-window), which on long
680
685
  // sessions becomes redundant noise. Setting to 1 means "emit the broad
681
- // menu at most once per hour"; 0 means "no cooldown, current behavior."
686
+ // menu at most once per hour"; 0 means "no cooldown, re-fire every open."
687
+ // ISS-20260713-033 shipped a non-zero quiet DEFAULT of 24 (at most once per
688
+ // day) so repeat session-opens stay quiet; set 0 for verbose/debug.
682
689
  // Range 0..168 (one week). Stored alongside fabric-hint's cooldown cache
683
690
  // under a distinct knowledge-hint-broad key.
684
- hint_broad_cooldown_hours: z5.number().int().min(0).max(168).optional().default(0),
691
+ hint_broad_cooldown_hours: z5.number().int().min(0).max(168).optional().default(24),
692
+ // ISS-20260713-033
685
693
  // v2.0.0-rc.33 W2-5 (P1-8): cooldown for the narrow PreToolUse hint.
686
694
  // Same shape as hint_broad_cooldown_hours but applies to per-Edit hint
687
695
  // re-emission across the cooldown window — independent of E3 session-
@@ -838,6 +846,7 @@ function makePositiveIntField(key, defaultValue) {
838
846
  return {
839
847
  key,
840
848
  group: "B_hint_threshold",
849
+ type: "number",
841
850
  widget: "text",
842
851
  label_i18n_key: `cli.config.fields.${key}.label`,
843
852
  description_i18n_key: `cli.config.fields.${key}.description`,
@@ -867,6 +876,7 @@ function makeEnumField(key, group, enumValues, defaultValue) {
867
876
  return {
868
877
  key,
869
878
  group,
879
+ type: "string",
870
880
  widget: "select",
871
881
  label_i18n_key: `cli.config.fields.${key}.label`,
872
882
  description_i18n_key: `cli.config.fields.${key}.description`,
@@ -893,6 +903,7 @@ function makeBooleanField(key, defaultValue) {
893
903
  return {
894
904
  key,
895
905
  group: "D_behavior",
906
+ type: "boolean",
896
907
  widget: "select",
897
908
  label_i18n_key: `cli.config.fields.${key}.label`,
898
909
  description_i18n_key: `cli.config.fields.${key}.description`,
@@ -1451,7 +1462,7 @@ function hasScriptExtension(name) {
1451
1462
  return dot !== -1 && SCRIPT_EXTENSIONS.has(name.slice(dot).toLowerCase());
1452
1463
  }
1453
1464
  var STORE_SCAN_MAX_DEPTH = 32;
1454
- var STORE_SCAN_MAX_ENTRIES = 1e5;
1465
+ var STORE_SCAN_MAX_ENTRIES = 5e4;
1455
1466
  function findStoreExecutableViolations(absDir, options = {}) {
1456
1467
  const maxDepth = options.maxDepth ?? STORE_SCAN_MAX_DEPTH;
1457
1468
  const maxEntries = options.maxEntries ?? STORE_SCAN_MAX_ENTRIES;
@@ -1775,7 +1786,18 @@ async function aggregatePendingAcrossStores(stores) {
1775
1786
  }
1776
1787
 
1777
1788
  // src/store/store-counters.ts
1778
- import { existsSync as existsSync2, readFileSync as readFileSync2, readdirSync as readdirSync2, writeFileSync } from "fs";
1789
+ import {
1790
+ closeSync,
1791
+ existsSync as existsSync2,
1792
+ openSync,
1793
+ readFileSync as readFileSync2,
1794
+ readdirSync as readdirSync2,
1795
+ renameSync,
1796
+ rmSync,
1797
+ statSync,
1798
+ writeFileSync
1799
+ } from "fs";
1800
+ import { randomUUID } from "crypto";
1779
1801
  import { join as join3 } from "path";
1780
1802
  function storeCountersPath(storeDir) {
1781
1803
  return join3(storeDir, STORE_LAYOUT.countersFile);
@@ -1849,6 +1871,57 @@ function readEntryId(file) {
1849
1871
  const idPart = stem.split("--")[0];
1850
1872
  return idPart.length > 0 ? idPart : null;
1851
1873
  }
1874
+ function withCountersFileLockSync(lockPath, fn) {
1875
+ const token = `${process.pid}.${randomUUID()}`;
1876
+ const start = Date.now();
1877
+ const maxWaitMs = 1e4;
1878
+ const staleMs = 1e4;
1879
+ for (; ; ) {
1880
+ let fd;
1881
+ try {
1882
+ fd = openSync(lockPath, "wx");
1883
+ writeFileSync(lockPath, token, "utf8");
1884
+ try {
1885
+ closeSync(fd);
1886
+ } catch {
1887
+ }
1888
+ try {
1889
+ return fn();
1890
+ } finally {
1891
+ try {
1892
+ if (readFileSync2(lockPath, "utf8") === token) rmSync(lockPath, { force: true });
1893
+ } catch {
1894
+ }
1895
+ }
1896
+ } catch (err) {
1897
+ const code = err && typeof err === "object" && "code" in err ? err.code : void 0;
1898
+ if (code !== "EEXIST") throw err;
1899
+ try {
1900
+ const st = statSync(lockPath);
1901
+ if (Date.now() - st.mtimeMs > staleMs) {
1902
+ const stale = readFileSync2(lockPath, "utf8");
1903
+ if (readFileSync2(lockPath, "utf8") === stale) rmSync(lockPath, { force: true });
1904
+ continue;
1905
+ }
1906
+ } catch {
1907
+ continue;
1908
+ }
1909
+ if (Date.now() - start > maxWaitMs) {
1910
+ throw new Error(`withCountersFileLockSync: timeout on ${lockPath}`);
1911
+ }
1912
+ const end = Date.now() + 20;
1913
+ while (Date.now() < end) {
1914
+ }
1915
+ }
1916
+ }
1917
+ }
1918
+ function atomicWriteCountersSync(path, counters) {
1919
+ const tmp = `${path}.${process.pid}.${Date.now()}.tmp`;
1920
+ const body = `${JSON.stringify(counters, null, 2)}
1921
+ `;
1922
+ writeFileSync(tmp, body, "utf8");
1923
+ renameSync(tmp, path);
1924
+ }
1852
1925
  function reconcileStoreCounters(storeDir) {
1853
1926
  const current = readStoreCounters(storeDir);
1854
1927
  const next = {
@@ -1873,13 +1946,20 @@ function reconcileStoreCounters(storeDir) {
1873
1946
  next[layerKey][typeCode] = Math.max(next[layerKey][typeCode], parsed.counter);
1874
1947
  }
1875
1948
  }
1876
- writeFileSync(storeCountersPath(storeDir), `${JSON.stringify(next, null, 2)}
1877
- `, "utf8");
1949
+ withCountersFileLockSync(`${storeCountersPath(storeDir)}.lock`, () => {
1950
+ const latest = readStoreCounters(storeDir);
1951
+ for (const layer of ["KP", "KT"]) {
1952
+ for (const code of ["MOD", "DEC", "GLD", "PIT", "PRO"]) {
1953
+ next[layer][code] = Math.max(next[layer][code], latest[layer][code]);
1954
+ }
1955
+ }
1956
+ atomicWriteCountersSync(storeCountersPath(storeDir), next);
1957
+ });
1878
1958
  return next;
1879
1959
  }
1880
1960
 
1881
1961
  // src/store/project-config-io.ts
1882
- import { existsSync as existsSync3, mkdirSync, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
1962
+ import { existsSync as existsSync3, mkdirSync, readFileSync as readFileSync3, renameSync as renameSync2, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
1883
1963
  import { join as join4 } from "path";
1884
1964
  function projectConfigPath(projectRoot) {
1885
1965
  return join4(projectRoot, ".fabric", "fabric-config.json");
@@ -1899,8 +1979,20 @@ function loadProjectConfig(projectRoot) {
1899
1979
  function saveProjectConfig(config, projectRoot) {
1900
1980
  const validated = fabricConfigSchema.parse(config);
1901
1981
  mkdirSync(join4(projectRoot, ".fabric"), { recursive: true });
1902
- writeFileSync2(projectConfigPath(projectRoot), `${JSON.stringify(validated, null, 2)}
1903
- `, "utf8");
1982
+ const target = projectConfigPath(projectRoot);
1983
+ const tmp = `${target}.${process.pid}.${Date.now()}.tmp`;
1984
+ const body = `${JSON.stringify(validated, null, 2)}
1985
+ `;
1986
+ try {
1987
+ writeFileSync2(tmp, body, "utf8");
1988
+ renameSync2(tmp, target);
1989
+ } catch (err) {
1990
+ try {
1991
+ unlinkSync(tmp);
1992
+ } catch {
1993
+ }
1994
+ throw err;
1995
+ }
1904
1996
  }
1905
1997
 
1906
1998
  // src/store/resolve-input.ts
@@ -2013,6 +2105,31 @@ function scrubRemoteUrl(remote) {
2013
2105
  );
2014
2106
  }
2015
2107
 
2108
+ // src/store/git-remote-allowlist.ts
2109
+ var ALLOWED_REMOTE_RE = /^(?:https?:\/\/|ssh:\/\/|git:\/\/|git@[^:\s]+:)/i;
2110
+ var BLOCKED_REMOTE_RE = /^(?:ext::|file:\/\/|fd::|http\+\w+:\/\/|https\+\w+:\/\/)/i;
2111
+ var ABSOLUTE_LOCAL_PATH_RE = /^(?:\/|[A-Za-z]:[\\/])/;
2112
+ function isTestRuntime() {
2113
+ return process.env.VITEST !== void 0 || process.env.VITEST_WORKER_ID !== void 0;
2114
+ }
2115
+ function isAllowedGitRemote(remote) {
2116
+ const trimmed = remote.trim();
2117
+ if (trimmed.length === 0) return false;
2118
+ if (BLOCKED_REMOTE_RE.test(trimmed)) return false;
2119
+ if (trimmed.startsWith("-")) return false;
2120
+ if (ALLOWED_REMOTE_RE.test(trimmed)) return true;
2121
+ return isTestRuntime() && ABSOLUTE_LOCAL_PATH_RE.test(trimmed);
2122
+ }
2123
+ function assertAllowedGitRemote(remote) {
2124
+ const trimmed = remote.trim();
2125
+ if (!isAllowedGitRemote(trimmed)) {
2126
+ throw new Error(
2127
+ `git remote not allowlisted: ${remote} (allowed: https://, http://, ssh://, git://, git@host:path; blocked: ext::, file://, option-like)`
2128
+ );
2129
+ }
2130
+ return trimmed;
2131
+ }
2132
+
2016
2133
  // src/scanner/scan-recommendations.ts
2017
2134
  function buildScanRecommendations(input, t) {
2018
2135
  const recs = [];
@@ -2218,9 +2335,9 @@ import {
2218
2335
  mkdirSync as mkdirSync2,
2219
2336
  readdirSync as readdirSync3,
2220
2337
  readFileSync as readFileSync4,
2221
- renameSync,
2222
- statSync,
2223
- unlinkSync,
2338
+ renameSync as renameSync3,
2339
+ statSync as statSync2,
2340
+ unlinkSync as unlinkSync2,
2224
2341
  writeFileSync as writeFileSync3
2225
2342
  } from "fs";
2226
2343
  import { join as join5, resolve, sep } from "path";
@@ -2271,7 +2388,7 @@ function countMarkdownFiles(dir) {
2271
2388
  }
2272
2389
  let mtimeMs;
2273
2390
  try {
2274
- mtimeMs = statSync(fullPath).mtimeMs;
2391
+ mtimeMs = statSync2(fullPath).mtimeMs;
2275
2392
  } catch {
2276
2393
  continue;
2277
2394
  }
@@ -2317,10 +2434,10 @@ function atomicWriteJsonSync(path, value) {
2317
2434
  try {
2318
2435
  writeFileSync3(tmpPath, `${JSON.stringify(value, null, 2)}
2319
2436
  `, "utf8");
2320
- renameSync(tmpPath, path);
2437
+ renameSync3(tmpPath, path);
2321
2438
  } catch (error) {
2322
2439
  try {
2323
- unlinkSync(tmpPath);
2440
+ unlinkSync2(tmpPath);
2324
2441
  } catch {
2325
2442
  }
2326
2443
  throw error;
@@ -3573,6 +3690,7 @@ export {
3573
3690
  archiveScanAnnotations,
3574
3691
  archiveScanInputSchema,
3575
3692
  archiveScanOutputSchema,
3693
+ assertAllowedGitRemote,
3576
3694
  assistantTurnObservedEventSchema,
3577
3695
  auditModeSchema,
3578
3696
  bindRequiredStore,
@@ -3661,6 +3779,7 @@ export {
3661
3779
  initScanCompletedEventSchema,
3662
3780
  initStore,
3663
3781
  installDiffAppliedEventSchema,
3782
+ isAllowedGitRemote,
3664
3783
  isHighValueArchiveCandidate,
3665
3784
  isKnowledgeStableId,
3666
3785
  isNonPersonalRequiredStore,
@@ -48,7 +48,7 @@ declare const BOOTSTRAP_REGEX: RegExp;
48
48
  *
49
49
  * Length guarantee: ≥ 800 bytes (rc.24: grew from ≥400 with cite-contract syntax).
50
50
  */
51
- declare const BOOTSTRAP_CANONICAL_ZH = "# Fabric Bootstrap\n\n\u672C\u9879\u76EE\u4F7F\u7528 Fabric \u7BA1\u7406\u8DE8\u5BA2\u6237\u7AEF AI \u77E5\u8BC6\u4E0E\u884C\u4E3A\u89C4\u5219\u3002\u672C\u6587\u4EF6\u7531 `fabric install` \u540C\u6B65\u5230\u4E24\u7AEF managed block,**\u4E0D\u8981\u624B\u52A8\u7F16\u8F91\u4E24\u7AEF\u7684 block**,\u53EA\u6539\u8FD9\u91CC + \u91CD\u8DD1 `fabric install`\u3002\n\n## For Developers\n\n\u8FD9\u4E2A\u6587\u4EF6\u662F **AI \u5BA2\u6237\u7AEF\u7684\u7B56\u7565\u4E0E\u89C4\u7EA6\u914D\u7F6E**,\u4E0D\u662F dev onboarding\u3002\u4F60\u4E0D\u9700\u8981\u8BFB Self-archive / Cite / Phase 0.4 \u7B49\u7EC6\u8282\u3002\n\u4F5C\u4E3A dev \u4F60\u53EA\u9700\u8981:\u5728\u6BCF\u4E2A repo \u8DD1\u4E00\u6B21 `fabric install`,\u7528 `fabric store bind <alias>` / `fabric store switch-write <alias>` \u63A5\u5165\u5199\u5165 store,\u51FA\u95EE\u9898\u8DD1 `fabric doctor`\u3002\n**\u4E25\u7981\u624B\u52A8\u7F16\u8F91 `.fabric/agents.meta.json`** \u2014 \u6D3E\u751F\u72B6\u6001\u7531 engine \u91CD\u5EFA\u3002\n\n## 5 \u5206\u949F\u4E0A\u624B (Dev Quickstart)\n\n**Fabric \u662F\u4EC0\u4E48**:\u8DE8\u5BA2\u6237\u7AEF(Claude Code / Codex CLI)\u7684 AI \u77E5\u8BC6\u5C42\u3002\u628A\u56E2\u961F/\u9879\u76EE\u7684 **decisions / pitfalls / guidelines / models / processes** \u5B58\u4E3A markdown,hook \u81EA\u52A8 surface \u7ED9 AI,\u8BA9 AI \u4E0D\u7528\u6BCF\u6B21\u91CD\u5B66\u3002\n\n**\u4F60\u8981\u505A\u7684 (DO)** vs **engine \u81EA\u52A8\u7684 (DON'T \u624B\u52A8)**:\n\n| \u4F60 DO | \u4F60 DON'T |\n| --- | --- |\n| \u6BCF\u4E2A repo \u8DD1\u4E00\u6B21 `fabric install` | \u624B\u7F16 `.fabric/agents.meta.json` |\n| \u5F02\u5E38\u65F6\u8DD1 `fabric doctor` (--fix \u81EA\u6108) | \u624B\u7F16 `.claude/hooks/` \u4E0B `.cjs` |\n| \u7528 `fabric-archive` / `fabric-review` / `fabric store ...` \u7BA1\u7406 store-backed knowledge | \u624B\u5199\u4EFB\u4F55\u975E store knowledge \u6839 |\n| `npm install -g @fenglimg/fabric-cli@latest` \u5347\u7EA7 | \u80CC 35 \u6761 doctor lint \u4EE3\u7801 |\n\n**4 \u6B65\u5FAA\u73AF**: `fabric install` (\u4E00\u6B21) \u2192 \u7ED1\u5B9A\u5E76\u9009\u62E9\u5199\u5165 store \u2192 AI \u6B63\u5E38\u5DE5\u4F5C (hook on session start + edit) \u2192 AI \u901A\u8FC7 MCP \u5199\u5165\u5F53\u524D write store \u7684 pending \u6761\u76EE\u5E76\u8FD4\u56DE `pending_path` \u2192 \u7528 `fabric-review` skill \u5BA1\u6838\u3002\n\n**\u771F\u4F8B**:\u67D0 sprite \u9ED1\u8FB9 root cause \u662F `atlas.premultiplyAlpha` flag \u53CD\u5411 \u2014 \u5F52\u6863\u8FDB store \u7684 `knowledge/pitfalls/` \u540E,\u4E0B\u6B21\u540C\u7C7B\u95EE\u9898 AI \u81EA\u52A8 reference\u3002\n\n\u5B8C\u6574 maintainer \u7248\u89C1 `docs/USER-QUICKSTART.md`\u3002\n\n## \u884C\u4E3A\u89C4\u5219\n- **\u4FEE\u6539\u4EFB\u4F55\u6587\u4EF6\u524D**:\u5148 `fab_recall(paths=[<\u88AB\u6539\u6587\u4EF6>])` \u2014\u2014 \u4E00\u6B21\u8C03\u7528\u62FF\u56DE\u76F8\u5173 KB \u7684\u63CF\u8FF0 + \u539F\u751F\u8BFB\u53D6\u8DEF\u5F84(`entries[].read_path`)\u3002`fab_recall` \u4E0D\u518D\u6295\u9012\u6B63\u6587;\u9700\u8981\u67D0\u6761\u6B63\u6587\u65F6\u76F4\u63A5\u5BF9\u5176 `entries[].read_path` \u505A\u539F\u751F Read(`Read <store>/knowledge/<type>/<id>--*.md`),\u8FD9\u4F1A\u88AB PostToolUse hook \u8BB0\u4E3A `knowledge_body_read`\u3002lean \u9ED8\u8BA4:\u63CF\u8FF0+\u7D22\u5F15\u5DF2\u591F\u53D1\u73B0\u6761\u76EE,\u6B63\u6587\u6309\u9700\u8BFB\u4E00\u6B21,\u4E0D\u6BCF\u8F6E\u91CD\u704C(KT-GLD-0005)\u3002\n- **`.fabric/agents.meta.json` \u4E25\u7981\u624B\u52A8\u7F16\u8F91**\uFF08co-location index \u5DF2\u9000\u5F79;\u77E5\u8BC6\u5728 mounted stores\uFF09\u3002\u5F02\u5E38\u65F6\u8DD1 `fabric doctor` / `fabric doctor --fix` \u81EA\u6108\u53EF\u4FEE\u590D\u9879\u3002\n\n## \u77E5\u8BC6\u5E93(KB)\n- **Discovery**:SessionStart hook \u5217 broad-scoped \u6761\u76EE(\u6761\u76EE\u6309 `semantic_scope` \u5206\u4E09\u5C42:`team` \u56E2\u961F\u901A\u7528 / `project:<id>` \u672C\u9879\u76EE\u4E13\u5C5E(\u4EC5\u5728\u7ED1\u5B9A\u8BE5\u9879\u76EE\u7684\u4ED3\u5E93\u6D6E\u73B0)/ `personal` \u4E2A\u4EBA `KP-*`,\u4E09\u8005\u5F15\u7528\u65B9\u5F0F\u76F8\u540C);edit \u6587\u4EF6\u65F6 PreToolUse hook \u53EF\u80FD\u89E6\u53D1 narrow hint\u3002\n- **Scope \u4E09\u8F74(\u4E3A\u4EC0\u4E48\u6CA1\u6D6E\u73B0)** (KT-MOD-0001):\u4E00\u6761\u77E5\u8BC6\u662F\u5426\u6D6E\u73B0\u7531\u4E09\u4E2A**\u6B63\u4EA4**\u8F74\u51B3\u5B9A \u2014\u2014 \u2460 `semantic_scope` \u53D7\u4F17(`team` / `project:<id>` / `personal`;\u7ED1\u9519\u9879\u76EE\u5219\u4E0D\u663E)\u2461 `relevance_scope` \u65F6\u673A(`broad` \u5E38\u9A7B / `narrow` \u4EC5\u7F16\u8F91\u5339\u914D\u6587\u4EF6\u65F6\u6D6E\u73B0)\u2462 `store` \u7269\u7406\u5E93(\u6CA1 `fabric store bind` \u5C31\u4E0D\u8BFB)\u3002\u4E09\u8F74\u540D\u5B57\u4F1A\u649E(\"team\" \u65E2\u662F\u53D7\u4F17\u503C\u4E5F\u53EF\u662F store \u522B\u540D),\u6240\u4EE5\u56F0\u60D1\"\u4E3A\u4EC0\u4E48\u8FD9\u6761\u6CA1\u6D6E\u73B0\"\u65F6\u8DD1 `fabric audit why-not-surfaced <id>` \u9010\u56E0\u8BCA\u65AD(store \u6CA1\u7ED1 / scope \u4E0D\u5339\u914D / narrow \u65F6\u673A)\u3002\n- **Usage**:\u8D70\u5355\u6B65 `fab_recall(paths=[...])` \u4E00\u6B21\u62FF\u56DE\u76F8\u5173 KB \u7684\u63CF\u8FF0 + \u8BFB\u53D6\u8DEF\u5F84;\u9700\u8981\u67D0\u6761\u6B63\u6587\u65F6\u5BF9\u5176 `entries[].read_path` \u505A\u539F\u751F Read \u53D6\u56DE(\u4E0D\u518D\u8D70 MCP \u4E8C\u6B21\u53D6\u6B63\u6587)\u3002\n- **session_id**: \u8C03\u7528 `fab_recall` \u65F6, \u52A1\u5FC5\u628A\u5F53\u524D client session id \u4F5C\u4E3A `session_id` \u53C2\u6570\u4F20\u5165(Claude Code \u7684 session id \u5728 stdin payload \u4E2D, Codex \u7684\u5BF9\u5E94 identifier \u540C\u7406)\u3002\u8FD9\u80FD\u8BA9 `fabric doctor --archive-history` \u4E0E `fabric-hint.cjs` Stop hook \u51C6\u786E\u8BC6\u522B\u8DE8\u4F1A\u8BDD debt \u72B6\u6001\u3002\n- **Skills (4)**:\u5199\u6D41\u7A0B `fabric-archive`(\u542B source mode \u51B7\u542F\u52A8\u4ECE git/docs \u56DE\u704C)/ `fabric-review`(\u542B retire \u8BED\u4E49\u6DD8\u6C70 + relate \u5173\u8054\u5EFA\u8FB9 \u5B50\u6D41\u7A0B);store \u8FD0\u7EF4 `fabric-store` / `fabric-sync`\u3002\n- **Language**:\u6E32\u67D3\u6309 `~/.fabric/fabric-global.json` \u7684 `language` \u5B57\u6BB5(machine-wide tone)\u3002\n- **Archive cadence nudge** (rc.36): \u6BCF\u5B8C\u6210\u4E00\u6279 Edit(\u9ED8\u8BA4 ~20 \u6B21, \u4E0E Stop hook \u9608\u503C config `archive_edit_threshold` \u4E00\u81F4)/ \u663E\u8457 decision \u540E,\u5728\u5408\u9002\u56DE\u5408\u4E3B\u52A8 propose \u8C03 `fabric-archive` skill \u2014 archive \u6CA1\u5EFA\u7ACB\u9891\u7387\u4F1A\u8BA9 KB \u6162\u901F\u6B7B\u6389\u3002\n- **Review backlog nudge** (rc.36): \u9700\u8981\u5224\u65AD pending backlog \u65F6\u8D70 `fab_pending action=\"list\"` \u6216 `fabric-review` \u8FD4\u56DE\u7684 `pending_path`;\u4E0D\u8981 glob \u9879\u76EE\u672C\u5730 `.fabric/knowledge/pending`\u3002\u5F53\u53EF\u89C1 pending \u7D2F\u79EF >10 \u6761\u65F6,\u5728\u5408\u9002\u56DE\u5408\u4E3B\u52A8 propose \u8C03 `fabric-review` skill \u6279\u91CF\u5BA1,\u907F\u514D draft \u5361\u6B7B\u3002\n\n## Self-archive policy (v2.2 C1: \u7CBE\u7B80\u8BF4\u660E\u4E66)\n\n\u51FA\u73B0\u660E\u786E\u5F52\u6863\u4FE1\u53F7\u65F6, \u4E8E\u8BE5 turn \u672B\u5C3E\u81EA\u4E3B\u8C03\u7528 `fabric-archive` skill(AI \u81EA\u89E6\u53D1\u5165\u53E3 E3):\n\n- **\u89E6\u53D1** (\u4E8C\u9009\u4E00): \u2460 **User-driven normative** \u2014 \u7528\u6237\u8BF4 `\u4EE5\u540E` / `always` / `never` / `\u4E0B\u6B21` / `\u8BB0\u4E00\u4E0B`, \u6216\u5728 \u22652 \u5019\u9009\u95F4\u6743\u8861\u540E\u9501\u5B9A\u65B9\u5411, \u6216\u62D2\u4E86\u5EFA\u8BAE\u5E76\u7ED9\u4E86\u7406\u7531(\u7406\u7531\u5373\u77E5\u8BC6); \u2461 **Wrong-turn-and-revert** \u2014 \u4F60\u8BD5\u4E86 path X \u53CD\u601D\u540E\u6539\u8D70 path Y(\"\u5426\u5B9A+\u66FF\u4EE3\"\u4E24\u6B65\u7ED3\u6784, \u975E\u5355\u7EAF\u63A2\u7D22\u5931\u8D25)\u3002\n- **\u4E0D\u89E6\u53D1**: \u7528\u6237\u7EAF\u8BE2\u95EE / \u7B80\u5355 refactor\u00B7typo / \u51ED\u7A7A\"\u6211\u5B66\u5230\u4E86\"\u7684\u6D1E\u5BDF\u3002\n- **\u9632 loop**: \u540C turn \u6700\u591A\u81EA\u8C03 1 \u6B21; \u540C session \u540C outcome \u4E0D\u91CD\u590D; skill \u5185 Phase 2.5 viability gate \u515C\u5E95\u3002\n- **\u56DE\u6267 (marker-free)**: \u76F4\u63A5\u81EA\u8C03 `fabric-archive` skill \u5373\u53EF, \u65E0\u9700\u6253\u5370\u4EFB\u4F55\u6697\u53F7\u5B57\u7B26\u4E32 \u2014\u2014 skill \u9ED8\u8BA4\u628A AI \u81EA\u8C03\u8BC6\u522B\u4E3A E3(\u786E\u5B9A\u6027 else \u8DEF\u7531, \u4E0D\u518D\u4F9D\u8D56 AI \u8F93\u51FA\u7CBE\u786E\u5B57\u7B26\u4E32)\u3002skill \u843D pending \u540E\u8FD4\u56DE `pending_path`, \u4E0D\u8BE5\u8BB0\u5C31\u56DE `undo`(\u6211\u8C03 fab_review reject)\u3002\n\n## Cite policy (v2.2 C1: recall \u81EA\u52A8\u8BB0\u8D26, \u96F6\u9996\u884C\u8D1F\u62C5)\n\n- **\u6838\u5FC3 (recall-first \u81EA\u52A8\u8BB0\u8D26)**: \u6539\u4EFB\u4F55\u6587\u4EF6\u524D\u5148 `fab_recall(paths=[<\u88AB\u6539\u6587\u4EF6>])`\u3002\u7CFB\u7EDF\u6309\"\u672C session recall \u547D\u4E2D\u7684 path \u4E0E\u7F16\u8F91\u76EE\u6807\u91CD\u53E0\"\u81EA\u52A8\u628A\u53EC\u56DE\u7684 KB \u8BB0\u4E3A\u8BE5\u6B21 edit \u7684\u5F15\u7528 \u2014\u2014 **\u65E0\u9700\u624B\u5199\u4EFB\u4F55\u56DE\u590D\u9996\u884C**(C1 \u5220\u9664\u9996\u884C `KB:` contract \u516B\u80A1:\u5148\u60F3\u540E\u8BF4,recall \u624D\u662F\u5F15\u7528\u53D1\u751F\u7684\u771F\u5B9E\u4FE1\u53F7)\u3002PreToolUse \u68C0\u6D4B\u4E0D\u5230\u76F8\u5173 recall \u65F6\u7ED9\u4E00\u6761\u8F6F nudge(nudge \u975E gate,\u5B88 KT-DEC-0007)\u3002\n- **\u552F\u4E00\u8981\u5F00\u53E3\u7684\u65F6\u5019 (dismissed / override)**: \u4F60\u5224\u65AD\u67D0\u53EC\u56DE KB \u4E0D\u8BE5\u5E94\u7528\u65F6,\u8BF4\u4E00\u53E5 `dismissed: <id> (<reason>)`;reason \u679A\u4E3E `scope-mismatch | outdated | not-applicable | other:<text>`\u3002\u9700\u7CBE\u786E\u6807\u6CE8\u4ECD\u53EF\u7528\u9996\u884C `KB: <id> [applied|dismissed]`(\u89E3\u6790\u5668\u4FDD\u7559,\u5411\u540E\u517C\u5BB9)\u3002\n- **`[applied]` \u9A8C\u8BC1\u4E49\u52A1**: \u5F15\u7528\u4EFB\u4F55 id(\u81EA\u52A8\u6216\u624B\u5199)\u524D\u5FC5\u987B\u5148 fab_recall \u5B9E\u9645\u6293\u56DE KB(\u6309\u9700\u5BF9\u6B63\u6587\u8DEF\u5F84\u505A\u539F\u751F Read),\u9632\u6B62\u7F16\u9020 id\u3002\u9A8C\u8BC1\u4E0D\u901A\u8FC7 = \u4E0D\u80FD cite\u3002\n- **\u7A3D\u6838\u4E0E\u5B8C\u6574\u89C4\u7EA6**: `fabric audit cite` \u8F93\u51FA\u8986\u76D6\u7387(\u4E0D\u963B\u65AD\u5DE5\u4F5C,\u53EA\u8BB0\u5F55);contract operator / store \u524D\u7F00 / skip\u00B7dismissed \u8BCD\u5178 / \u7C7B\u578B\u8DEF\u7531 / \u88C1\u51B3\u9636\u68AF\u7B49\u5B8C\u6574\u89C4\u7EA6\u6743\u5A01\u8BE6\u53C2 `fabric-review` skill \u7684 `ref/cite-contract.md` \u2014\u2014 bootstrap \u53EA\u7559\u53EF\u6267\u884C core\u3002\n";
51
+ declare const BOOTSTRAP_CANONICAL_ZH = "# Fabric Bootstrap\n\n\u672C\u9879\u76EE\u4F7F\u7528 Fabric \u7BA1\u7406\u8DE8\u5BA2\u6237\u7AEF AI \u77E5\u8BC6\u4E0E\u884C\u4E3A\u89C4\u5219\u3002\u672C\u6587\u4EF6\u7531 `fabric install` \u540C\u6B65\u5230\u4E24\u7AEF managed block,**\u4E0D\u8981\u624B\u52A8\u7F16\u8F91\u4E24\u7AEF\u7684 block**,\u53EA\u6539\u8FD9\u91CC + \u91CD\u8DD1 `fabric install`\u3002\n\n## For Developers\n\n\u8FD9\u4E2A\u6587\u4EF6\u662F **AI \u5BA2\u6237\u7AEF\u7684\u7B56\u7565\u4E0E\u89C4\u7EA6\u914D\u7F6E**,\u4E0D\u662F dev onboarding\u3002\u4F60\u4E0D\u9700\u8981\u8BFB Self-archive / Cite / Phase 0.4 \u7B49\u7EC6\u8282\u3002\n\u4F5C\u4E3A dev \u4F60\u53EA\u9700\u8981:\u5728\u6BCF\u4E2A repo \u8DD1\u4E00\u6B21 `fabric install`,\u7528 `fabric store bind <alias>` / `fabric store switch-write <alias>` \u63A5\u5165\u5199\u5165 store,\u51FA\u95EE\u9898\u8DD1 `fabric doctor`\u3002\n**\u4E25\u7981\u624B\u52A8\u7F16\u8F91 `.fabric/agents.meta.json`** \u2014 \u6D3E\u751F\u72B6\u6001\u7531 engine \u91CD\u5EFA\u3002\n\n## 5 \u5206\u949F\u4E0A\u624B (Dev Quickstart)\n\n**Fabric \u662F\u4EC0\u4E48**:\u8DE8\u5BA2\u6237\u7AEF(Claude Code / Codex CLI)\u7684 AI \u77E5\u8BC6\u5C42\u3002\u628A\u56E2\u961F/\u9879\u76EE\u7684 **decisions / pitfalls / guidelines / models / processes** \u5B58\u4E3A markdown,hook \u81EA\u52A8 surface \u7ED9 AI,\u8BA9 AI \u4E0D\u7528\u6BCF\u6B21\u91CD\u5B66\u3002\n\n**\u4F60\u8981\u505A\u7684 (DO)** vs **engine \u81EA\u52A8\u7684 (DON'T \u624B\u52A8)**:\n\n| \u4F60 DO | \u4F60 DON'T |\n| --- | --- |\n| \u6BCF\u4E2A repo \u8DD1\u4E00\u6B21 `fabric install` | \u624B\u7F16 `.fabric/agents.meta.json` |\n| \u5F02\u5E38\u65F6\u8DD1 `fabric doctor` (--fix \u81EA\u6108) | \u624B\u7F16 `.claude/hooks/` \u4E0B `.cjs` |\n| \u7528 `fabric-archive` / `fabric-review` / `fabric store ...` \u7BA1\u7406 store-backed knowledge | \u624B\u5199\u4EFB\u4F55\u975E store knowledge \u6839 |\n| `npm install -g @fenglimg/fabric-cli@latest` \u5347\u7EA7 | \u80CC 35 \u6761 doctor lint \u4EE3\u7801 |\n\n**4 \u6B65\u5FAA\u73AF**: `fabric install` (\u4E00\u6B21) \u2192 \u7ED1\u5B9A\u5E76\u9009\u62E9\u5199\u5165 store \u2192 AI \u6B63\u5E38\u5DE5\u4F5C (hook on session start + edit) \u2192 AI \u901A\u8FC7 MCP \u5199\u5165\u5F53\u524D write store \u7684 pending \u6761\u76EE\u5E76\u8FD4\u56DE `pending_path` \u2192 \u7528 `fabric-review` skill \u5BA1\u6838\u3002\n\n**\u771F\u4F8B**:\u67D0 sprite \u9ED1\u8FB9 root cause \u662F `atlas.premultiplyAlpha` flag \u53CD\u5411 \u2014 \u5F52\u6863\u8FDB store \u7684 `knowledge/pitfalls/` \u540E,\u4E0B\u6B21\u540C\u7C7B\u95EE\u9898 AI \u81EA\u52A8 reference\u3002\n\n\u5B8C\u6574 maintainer \u7248\u89C1 `docs/USER-QUICKSTART.md`\u3002\n\n## \u884C\u4E3A\u89C4\u5219\n- **Pre-action gating (\u4FEE\u6539\u4EFB\u4F55\u6587\u4EF6\u524D MUST)**: \u2460 \u5148 `fab_recall(paths=[<\u88AB\u6539\u6587\u4EF6>], session_id=<client-session-id>)`\uFF1B\u2461 \u6309\u9700\u539F\u751F Read \u547D\u4E2D\u7684 `entries[].read_path` \u6B63\u6587(PostToolUse \u8BB0\u4E3A `knowledge_body_read`)\uFF1B\u2462 \u8DF3\u8FC7\u4E0D\u9002\u7528\u547D\u4E2D\u65F6\u8BF4 `dismissed: <id> (<reason>)`\u3002`fab_recall` \u4E0D\u518D\u6295\u9012\u6B63\u6587;lean \u9ED8\u8BA4\u63CF\u8FF0+\u7D22\u5F15\u5DF2\u591F\u53D1\u73B0\u6761\u76EE(KT-GLD-0005)\u3002PreToolUse \u4EC5\u8F6F nudge,\u5B88 KT-DEC-0007(\u975E permanent gate / \u65E0 `decision:block`)\u3002\n- **Archive-as-truth**: \u8FDB canonical **\u552F\u4E00\u8DEF\u5F84** \u662F `fab_propose` \u2192 pending \u2192 `fabric-review`/`fab_review` \u5BA1\u6279\uFF1B\u7981\u6B62\u628A chat/log \u81EA\u52A8 promote \u8FDB canonical\u3002\n- **`.fabric/agents.meta.json` \u4E25\u7981\u624B\u52A8\u7F16\u8F91**\uFF08co-location index \u5DF2\u9000\u5F79;\u77E5\u8BC6\u5728 mounted stores\uFF09\u3002\u5F02\u5E38\u65F6\u8DD1 `fabric doctor` / `fabric doctor --fix` \u81EA\u6108\u53EF\u4FEE\u590D\u9879\u3002\n\n## \u77E5\u8BC6\u5E93(KB)\n- **Discovery**:SessionStart hook \u5217 broad-scoped \u6761\u76EE(\u6761\u76EE\u6309 `semantic_scope` \u5206\u4E09\u5C42:`team` \u56E2\u961F\u901A\u7528 / `project:<id>` \u672C\u9879\u76EE\u4E13\u5C5E(\u4EC5\u5728\u7ED1\u5B9A\u8BE5\u9879\u76EE\u7684\u4ED3\u5E93\u6D6E\u73B0)/ `personal` \u4E2A\u4EBA `KP-*`,\u4E09\u8005\u5F15\u7528\u65B9\u5F0F\u76F8\u540C);edit \u6587\u4EF6\u65F6 PreToolUse hook \u53EF\u80FD\u89E6\u53D1 narrow hint\u3002\n- **Scope \u4E09\u8F74(\u4E3A\u4EC0\u4E48\u6CA1\u6D6E\u73B0)** (KT-MOD-0001):\u4E00\u6761\u77E5\u8BC6\u662F\u5426\u6D6E\u73B0\u7531\u4E09\u4E2A**\u6B63\u4EA4**\u8F74\u51B3\u5B9A \u2014\u2014 \u2460 `semantic_scope` \u53D7\u4F17(`team` / `project:<id>` / `personal`;\u7ED1\u9519\u9879\u76EE\u5219\u4E0D\u663E)\u2461 `relevance_scope` \u65F6\u673A(`broad` \u5E38\u9A7B / `narrow` \u4EC5\u7F16\u8F91\u5339\u914D\u6587\u4EF6\u65F6\u6D6E\u73B0)\u2462 `store` \u7269\u7406\u5E93(\u6CA1 `fabric store bind` \u5C31\u4E0D\u8BFB)\u3002\u4E09\u8F74\u540D\u5B57\u4F1A\u649E(\"team\" \u65E2\u662F\u53D7\u4F17\u503C\u4E5F\u53EF\u662F store \u522B\u540D),\u6240\u4EE5\u56F0\u60D1\"\u4E3A\u4EC0\u4E48\u8FD9\u6761\u6CA1\u6D6E\u73B0\"\u65F6\u8DD1 `fabric audit why-not-surfaced <id>` \u9010\u56E0\u8BCA\u65AD(store \u6CA1\u7ED1 / scope \u4E0D\u5339\u914D / narrow \u65F6\u673A)\u3002\n- **Usage**:\u8D70\u5355\u6B65 `fab_recall(paths=[...])` \u4E00\u6B21\u62FF\u56DE\u76F8\u5173 KB \u7684\u63CF\u8FF0 + \u8BFB\u53D6\u8DEF\u5F84;\u9700\u8981\u67D0\u6761\u6B63\u6587\u65F6\u5BF9\u5176 `entries[].read_path` \u505A\u539F\u751F Read \u53D6\u56DE(\u4E0D\u518D\u8D70 MCP \u4E8C\u6B21\u53D6\u6B63\u6587)\u3002\n- **session_id**: \u8C03\u7528 `fab_recall` \u65F6, \u52A1\u5FC5\u628A\u5F53\u524D client session id \u4F5C\u4E3A `session_id` \u53C2\u6570\u4F20\u5165(Claude Code \u7684 session id \u5728 stdin payload \u4E2D, Codex \u7684\u5BF9\u5E94 identifier \u540C\u7406)\u3002\u8FD9\u80FD\u8BA9 `fabric doctor --archive-history` \u4E0E `fabric-hint.cjs` Stop hook \u51C6\u786E\u8BC6\u522B\u8DE8\u4F1A\u8BDD debt \u72B6\u6001\u3002\n- **Skills (4)**:\u5199\u6D41\u7A0B `fabric-archive`(\u542B source mode \u51B7\u542F\u52A8\u4ECE git/docs \u56DE\u704C)/ `fabric-review`(\u542B retire \u8BED\u4E49\u6DD8\u6C70 + relate \u5173\u8054\u5EFA\u8FB9 \u5B50\u6D41\u7A0B);store \u8FD0\u7EF4 `fabric-store` / `fabric-sync`\u3002\n- **Language**:\u6E32\u67D3\u6309 `~/.fabric/fabric-global.json` \u7684 `language` \u5B57\u6BB5(machine-wide tone)\u3002\n- **Archive cadence nudge** (rc.36 / finish\u2192archive): \u663E\u8457 decision \u6536\u53E3\u6216\u4E00\u6279 Edit \u8FBE\u5230 config `archive_edit_threshold`(\u9ED8\u8BA4 20) \u540E,\u5728\u5408\u9002\u56DE\u5408\u8F7B\u91CF\u81EA\u8C03 `fabric-archive`(\u540C turn \u6700\u591A 1 \u6B21;\u975E task engine / \u975E Stop-hook flood)\u3002Stop hook \u4EC5 soft threshold nudge,\u5B88 KT-DEC-0007 \u2014 archive \u6CA1\u5EFA\u7ACB\u9891\u7387\u4F1A\u8BA9 KB \u6162\u901F\u6B7B\u6389\u3002\n- **Review backlog nudge** (rc.36): \u9700\u8981\u5224\u65AD pending backlog \u65F6\u8D70 `fab_pending action=\"list\"` \u6216 `fabric-review` \u8FD4\u56DE\u7684 `pending_path`;\u4E0D\u8981 glob \u9879\u76EE\u672C\u5730 `.fabric/knowledge/pending`\u3002\u5F53\u53EF\u89C1 pending \u7D2F\u79EF >10 \u6761\u65F6,\u5728\u5408\u9002\u56DE\u5408\u4E3B\u52A8 propose \u8C03 `fabric-review` skill \u6279\u91CF\u5BA1,\u907F\u514D draft \u5361\u6B7B\u3002\n\n## Self-archive policy (v2.2 C1: \u7CBE\u7B80\u8BF4\u660E\u4E66)\n\n\u51FA\u73B0\u660E\u786E\u5F52\u6863\u4FE1\u53F7\u65F6, \u4E8E\u8BE5 turn \u672B\u5C3E\u81EA\u4E3B\u8C03\u7528 `fabric-archive` skill(AI \u81EA\u89E6\u53D1\u5165\u53E3 E3):\n\n- **\u89E6\u53D1** (\u4E8C\u9009\u4E00): \u2460 **User-driven normative** \u2014 \u7528\u6237\u8BF4 `\u4EE5\u540E` / `always` / `never` / `\u4E0B\u6B21` / `\u8BB0\u4E00\u4E0B`, \u6216\u5728 \u22652 \u5019\u9009\u95F4\u6743\u8861\u540E\u9501\u5B9A\u65B9\u5411, \u6216\u62D2\u4E86\u5EFA\u8BAE\u5E76\u7ED9\u4E86\u7406\u7531(\u7406\u7531\u5373\u77E5\u8BC6); \u2461 **Wrong-turn-and-revert** \u2014 \u4F60\u8BD5\u4E86 path X \u53CD\u601D\u540E\u6539\u8D70 path Y(\"\u5426\u5B9A+\u66FF\u4EE3\"\u4E24\u6B65\u7ED3\u6784, \u975E\u5355\u7EAF\u63A2\u7D22\u5931\u8D25)\u3002\n- **\u4E0D\u89E6\u53D1**: \u7528\u6237\u7EAF\u8BE2\u95EE / \u7B80\u5355 refactor\u00B7typo / \u51ED\u7A7A\"\u6211\u5B66\u5230\u4E86\"\u7684\u6D1E\u5BDF\u3002\n- **\u9632 loop**: \u540C turn \u6700\u591A\u81EA\u8C03 1 \u6B21; \u540C session \u540C outcome \u4E0D\u91CD\u590D; skill \u5185 Phase 2.5 viability gate \u515C\u5E95\u3002\n- **\u56DE\u6267 (marker-free)**: \u76F4\u63A5\u81EA\u8C03 `fabric-archive` skill \u5373\u53EF, \u65E0\u9700\u6253\u5370\u4EFB\u4F55\u6697\u53F7\u5B57\u7B26\u4E32 \u2014\u2014 skill \u9ED8\u8BA4\u628A AI \u81EA\u8C03\u8BC6\u522B\u4E3A E3(\u786E\u5B9A\u6027 else \u8DEF\u7531, \u4E0D\u518D\u4F9D\u8D56 AI \u8F93\u51FA\u7CBE\u786E\u5B57\u7B26\u4E32)\u3002skill \u843D pending \u540E\u8FD4\u56DE `pending_path`, \u4E0D\u8BE5\u8BB0\u5C31\u56DE `undo`(\u6211\u8C03 fab_review reject)\u3002\n\n## Cite policy (v2.2 C1: recall \u81EA\u52A8\u8BB0\u8D26, \u96F6\u9996\u884C\u8D1F\u62C5)\n\n- **\u6838\u5FC3 (recall-first \u81EA\u52A8\u8BB0\u8D26)**: \u6539\u4EFB\u4F55\u6587\u4EF6\u524D\u5148 `fab_recall(paths=[<\u88AB\u6539\u6587\u4EF6>])`\u3002\u7CFB\u7EDF\u6309\"\u672C session recall \u547D\u4E2D\u7684 path \u4E0E\u7F16\u8F91\u76EE\u6807\u91CD\u53E0\"\u81EA\u52A8\u628A\u53EC\u56DE\u7684 KB \u8BB0\u4E3A\u8BE5\u6B21 edit \u7684\u5F15\u7528 \u2014\u2014 **\u65E0\u9700\u624B\u5199\u4EFB\u4F55\u56DE\u590D\u9996\u884C**(C1 \u5220\u9664\u9996\u884C `KB:` contract \u516B\u80A1:\u5148\u60F3\u540E\u8BF4,recall \u624D\u662F\u5F15\u7528\u53D1\u751F\u7684\u771F\u5B9E\u4FE1\u53F7)\u3002PreToolUse \u68C0\u6D4B\u4E0D\u5230\u76F8\u5173 recall \u65F6\u7ED9\u4E00\u6761\u8F6F nudge(nudge \u975E gate,\u5B88 KT-DEC-0007)\u3002\n- **\u552F\u4E00\u8981\u5F00\u53E3\u7684\u65F6\u5019 (dismissed / override)**: \u4F60\u5224\u65AD\u67D0\u53EC\u56DE KB \u4E0D\u8BE5\u5E94\u7528\u65F6,\u8BF4\u4E00\u53E5 `dismissed: <id> (<reason>)`;reason \u679A\u4E3E `scope-mismatch | outdated | not-applicable | other:<text>`\u3002\u9700\u7CBE\u786E\u6807\u6CE8\u4ECD\u53EF\u7528\u9996\u884C `KB: <id> [applied|dismissed]`(\u89E3\u6790\u5668\u4FDD\u7559,\u5411\u540E\u517C\u5BB9)\u3002\n- **`[applied]` \u9A8C\u8BC1\u4E49\u52A1**: \u5F15\u7528\u4EFB\u4F55 id(\u81EA\u52A8\u6216\u624B\u5199)\u524D\u5FC5\u987B\u5148 fab_recall \u5B9E\u9645\u6293\u56DE KB(\u6309\u9700\u5BF9\u6B63\u6587\u8DEF\u5F84\u505A\u539F\u751F Read),\u9632\u6B62\u7F16\u9020 id\u3002\u9A8C\u8BC1\u4E0D\u901A\u8FC7 = \u4E0D\u80FD cite\u3002\n- **\u7A3D\u6838\u4E0E\u5B8C\u6574\u89C4\u7EA6**: `fabric audit cite` \u8F93\u51FA\u8986\u76D6\u7387(\u4E0D\u963B\u65AD\u5DE5\u4F5C,\u53EA\u8BB0\u5F55);contract operator / store \u524D\u7F00 / skip\u00B7dismissed \u8BCD\u5178 / \u7C7B\u578B\u8DEF\u7531 / \u88C1\u51B3\u9636\u68AF\u7B49\u5B8C\u6574\u89C4\u7EA6\u6743\u5A01\u8BE6\u53C2 `fabric-review` skill \u7684 `ref/cite-contract.md` \u2014\u2014 bootstrap \u53EA\u7559\u53EF\u6267\u884C core\u3002\n";
52
52
  /**
53
53
  * Canonical bootstrap body (en) — the English parallel of
54
54
  * {@link BOOTSTRAP_CANONICAL_ZH}. Structurally parallel (same H2 section count,
@@ -58,7 +58,7 @@ declare const BOOTSTRAP_CANONICAL_ZH = "# Fabric Bootstrap\n\n\u672C\u9879\u76EE
58
58
  * in English). Byte-locked: a zh-CN machine never sees this body and an en
59
59
  * machine never sees the ZH one, but both are install/doctor contracts.
60
60
  */
61
- declare const BOOTSTRAP_CANONICAL_EN = "# Fabric Bootstrap\n\nThis project uses Fabric to manage cross-client AI knowledge and behavior rules. This file is synced into the managed block on both clients by `fabric install` \u2014 **do not hand-edit the block on any client**; edit here + re-run `fabric install`.\n\n## For Developers\n\nThis file is the **AI client's policy & convention config**, not dev onboarding. You don't need to read the Self-archive / Cite / Phase 0.4 details.\nAs a dev you only need to: run `fabric install` once per repo, use `fabric store bind <alias>` / `fabric store switch-write <alias>` to wire up a write store, and run `fabric doctor` when something breaks.\n**Never hand-edit `.fabric/agents.meta.json`** \u2014 derived state is rebuilt by the engine.\n\n## Dev Quickstart\n\n**What Fabric is**: a cross-client (Claude Code / Codex CLI) AI knowledge layer. Store the team/project **decisions / pitfalls / guidelines / models / processes** as markdown; hooks surface them to the AI automatically so it doesn't re-learn every time.\n\n**What you DO** vs **what the engine does (DON'T hand-edit)**:\n\n| You DO | You DON'T |\n| --- | --- |\n| Run `fabric install` once per repo | Hand-edit `.fabric/agents.meta.json` |\n| Run `fabric doctor` (--fix self-heals) on trouble | Hand-edit `.cjs` under `.claude/hooks/` |\n| Use `fabric-archive` / `fabric-review` / `fabric store ...` to manage store-backed knowledge | Hand-write any non-store knowledge root |\n| `npm install -g @fenglimg/fabric-cli@latest` to upgrade | Memorize the 35 doctor lint codes |\n\n**4-step loop**: `fabric install` (once) \u2192 bind and pick a write store \u2192 AI works normally (hook on session start + edit) \u2192 the AI writes pending entries into the current write store via MCP and returns a `pending_path` \u2192 review with the `fabric-review` skill.\n\n**Real example**: a sprite black-edge root cause was the `atlas.premultiplyAlpha` flag being inverted \u2014 once archived into the store's `knowledge/pitfalls/`, the AI auto-references it next time a similar issue shows up.\n\nSee `docs/USER-QUICKSTART.md` for the full maintainer version.\n\n## Behavior Rules\n- **Before modifying any file**: first `fab_recall(paths=[<file-being-edited>])` \u2014\u2014 a single call returns the relevant KB descriptions + native read paths (`entries[].read_path`). `fab_recall` no longer delivers bodies; when you need a body, do a native Read of its `entries[].read_path` (`Read <store>/knowledge/<type>/<id>--*.md`), which the PostToolUse hook records as `knowledge_body_read`. Lean default: descriptions + index already suffice to discover entries; read a body once on demand, don't re-inject it every turn (KT-GLD-0005).\n- **Never hand-edit `.fabric/agents.meta.json`** (co-location index retired; knowledge lives in mounted stores). For anomalies run `fabric doctor` / `fabric doctor --fix` on fixable state.\n\n## Knowledge Base (KB)\n- **Discovery**: the SessionStart hook lists broad-scoped entries (scoped by `semantic_scope` across three tiers: `team` team-wide / `project:<id>` this-project-only (surfaces only in repos bound to that project) / `personal` `KP-*`, all three referenced the same way); editing a file may trigger a narrow hint via the PreToolUse hook.\n- **Scope's 3 axes (why something isn't surfacing)** (KT-MOD-0001): whether an entry surfaces is decided by three **orthogonal** axes \u2014 \u2460 `semantic_scope` audience (`team` / `project:<id>` / `personal`; the wrong project binding hides it) \u2461 `relevance_scope` timing (`broad` always-on / `narrow` only when you edit a matching file) \u2462 `store` physical lib (not read without `fabric store bind`). The axis names collide (\"team\" is both an audience value and a possible store alias), so when puzzled about \"why isn't this surfacing\" run `fabric audit why-not-surfaced <id>` for a per-cause diagnosis (store unbound / scope mismatch / narrow timing).\n- **Usage**: go one-step `fab_recall(paths=[...])` to fetch the relevant KB descriptions + read paths in one call; when you need a body, do a native Read of its `entries[].read_path` (no second MCP round-trip for the body).\n- **session_id**: when calling `fab_recall`, always pass the current client session id as the `session_id` argument (Claude Code's session id is in the stdin payload; Codex's corresponding identifier likewise). This lets `fabric doctor --archive-history` and the `fabric-hint.cjs` Stop hook track cross-session debt accurately.\n- **Skills (4)**: write flow `fabric-archive` (with source-mode cold-start backfill from git/docs) / `fabric-review` (with retire-deprecation + relate-edge sub-flows); store ops `fabric-store` / `fabric-sync`.\n- **Language**: rendered per the `language` field in `~/.fabric/fabric-global.json` (machine-wide tone).\n- **Archive cadence nudge** (rc.36): after each batch of edits (default ~20, matching the Stop hook threshold config `archive_edit_threshold`) / a significant decision, proactively propose the `fabric-archive` skill at a suitable turn \u2014 without an archive cadence the KB slowly dies.\n- **Review backlog nudge** (rc.36): to judge the pending backlog, go through `fab_pending action=\"list\"` or the `pending_path` returned by `fabric-review`; don't glob the project-local `.fabric/knowledge/pending`. When the visible pending count exceeds 10, proactively propose the `fabric-review` skill at a suitable turn to batch-review and avoid draft deadlock.\n\n## Self-archive policy (v2.2 C1: lean spec)\n\nWhen a clear archival signal appears, autonomously invoke the `fabric-archive` skill at the end of that turn (AI self-trigger entry E3):\n\n- **Trigger** (either): \u2460 **User-driven normative** \u2014 the user says `\u4EE5\u540E` / `always` / `never` / `\u4E0B\u6B21` / `\u8BB0\u4E00\u4E0B`, or locks a direction with rationale after weighing \u22652 candidates, or rejects a suggestion and states a reason (the reason is knowledge); \u2461 **Wrong-turn-and-revert** \u2014 you tried path X, then after reflection switched to path Y (a two-step \"negate + replace\" structure, not mere exploratory failure).\n- **Does NOT trigger**: pure user questions / simple refactor\u00B7typo / a baseless \"I learned something\" insight.\n- **Anti-loop**: at most 1 self-invocation per turn; no repeat for the same outcome in the same session; the skill's Phase 2.5 viability gate is the backstop.\n- **Receipt (marker-free)**: just invoke the `fabric-archive` skill directly \u2014 no marker string to print: the skill routes an AI self-invocation to E3 by default (deterministic else-branch, no longer dependent on the AI emitting an exact string). The skill returns `pending_path` after writing pending \u2014 reply `undo` if it shouldn't be recorded (I'll call fab_review reject).\n\n## Cite policy (v2.2 C1: recall auto-accounting, zero first-line burden)\n\n- **Core (recall-first auto-accounting)**: before changing any file, run `fab_recall(paths=[<file-being-edited>])` first. The system auto-accounts the recalled KB as that edit's citation by \"paths recall-hit this session overlap the edit target\" \u2014\u2014 **no hand-written first reply line needed** (C1 removes the first-line `KB:` contract boilerplate: think-then-speak, recall is the real signal that a citation happened). The PreToolUse hook gives a soft nudge when it detects no relevant recall (nudge, not a gate, per KT-DEC-0007).\n- **The only time to speak up (dismissed / override)**: when you judge a recalled KB should NOT apply, say one line `dismissed: <id> (<reason>)`; reason enum `scope-mismatch | outdated | not-applicable | other:<text>`. For precise annotation you may still use a first-line `KB: <id> [applied|dismissed]` (parser retained, backward compatible).\n- **`[applied]` verification duty**: citing any id (auto or hand-written) requires first fetching the KB via fab_recall (a native Read of its body path when needed) to prevent fabricated ids. Verification failing = you cannot cite.\n- **Audit & full spec**: `fabric audit cite` reports coverage (does not block your work, only records); the full spec (contract operators / store prefix / skip\u00B7dismissed dictionaries / type routing / adjudication ladder) lives authoritatively in the `fabric-review` skill's `ref/cite-contract.md` \u2014\u2014 bootstrap keeps only the executable core.\n";
61
+ declare const BOOTSTRAP_CANONICAL_EN = "# Fabric Bootstrap\n\nThis project uses Fabric to manage cross-client AI knowledge and behavior rules. This file is synced into the managed block on both clients by `fabric install` \u2014 **do not hand-edit the block on any client**; edit here + re-run `fabric install`.\n\n## For Developers\n\nThis file is the **AI client's policy & convention config**, not dev onboarding. You don't need to read the Self-archive / Cite / Phase 0.4 details.\nAs a dev you only need to: run `fabric install` once per repo, use `fabric store bind <alias>` / `fabric store switch-write <alias>` to wire up a write store, and run `fabric doctor` when something breaks.\n**Never hand-edit `.fabric/agents.meta.json`** \u2014 derived state is rebuilt by the engine.\n\n## Dev Quickstart\n\n**What Fabric is**: a cross-client (Claude Code / Codex CLI) AI knowledge layer. Store the team/project **decisions / pitfalls / guidelines / models / processes** as markdown; hooks surface them to the AI automatically so it doesn't re-learn every time.\n\n**What you DO** vs **what the engine does (DON'T hand-edit)**:\n\n| You DO | You DON'T |\n| --- | --- |\n| Run `fabric install` once per repo | Hand-edit `.fabric/agents.meta.json` |\n| Run `fabric doctor` (--fix self-heals) on trouble | Hand-edit `.cjs` under `.claude/hooks/` |\n| Use `fabric-archive` / `fabric-review` / `fabric store ...` to manage store-backed knowledge | Hand-write any non-store knowledge root |\n| `npm install -g @fenglimg/fabric-cli@latest` to upgrade | Memorize the 35 doctor lint codes |\n\n**4-step loop**: `fabric install` (once) \u2192 bind and pick a write store \u2192 AI works normally (hook on session start + edit) \u2192 the AI writes pending entries into the current write store via MCP and returns a `pending_path` \u2192 review with the `fabric-review` skill.\n\n**Real example**: a sprite black-edge root cause was the `atlas.premultiplyAlpha` flag being inverted \u2014 once archived into the store's `knowledge/pitfalls/`, the AI auto-references it next time a similar issue shows up.\n\nSee `docs/USER-QUICKSTART.md` for the full maintainer version.\n\n## Behavior Rules\n- **Pre-action gating (MUST before Edit/Write)**: (1) call `fab_recall(paths=[<file-being-edited>], session_id=<client-session-id>)`; (2) optionally native-Read selected `entries[].read_path` bodies (PostToolUse records `knowledge_body_read`); (3) when skipping a hit, say `dismissed: <id> (<reason>)`. `fab_recall` no longer delivers bodies; lean default is description+index discovery (KT-GLD-0005). PreToolUse is soft nudge only per KT-DEC-0007 (never permanent gate / no `decision:block`).\n- **Archive-as-truth**: the **only** path into canonical is `fab_propose` \u2192 pending \u2192 `fabric-review`/`fab_review` approve; never auto-promote chat/logs into canonical.\n- **Never hand-edit `.fabric/agents.meta.json`** (co-location index retired; knowledge lives in mounted stores). For anomalies run `fabric doctor` / `fabric doctor --fix` on fixable state.\n\n## Knowledge Base (KB)\n- **Discovery**: the SessionStart hook lists broad-scoped entries (scoped by `semantic_scope` across three tiers: `team` team-wide / `project:<id>` this-project-only (surfaces only in repos bound to that project) / `personal` `KP-*`, all three referenced the same way); editing a file may trigger a narrow hint via the PreToolUse hook.\n- **Scope's 3 axes (why something isn't surfacing)** (KT-MOD-0001): whether an entry surfaces is decided by three **orthogonal** axes \u2014 \u2460 `semantic_scope` audience (`team` / `project:<id>` / `personal`; the wrong project binding hides it) \u2461 `relevance_scope` timing (`broad` always-on / `narrow` only when you edit a matching file) \u2462 `store` physical lib (not read without `fabric store bind`). The axis names collide (\"team\" is both an audience value and a possible store alias), so when puzzled about \"why isn't this surfacing\" run `fabric audit why-not-surfaced <id>` for a per-cause diagnosis (store unbound / scope mismatch / narrow timing).\n- **Usage**: go one-step `fab_recall(paths=[...])` to fetch the relevant KB descriptions + read paths in one call; when you need a body, do a native Read of its `entries[].read_path` (no second MCP round-trip for the body).\n- **session_id**: when calling `fab_recall`, always pass the current client session id as the `session_id` argument (Claude Code's session id is in the stdin payload; Codex's corresponding identifier likewise). This lets `fabric doctor --archive-history` and the `fabric-hint.cjs` Stop hook track cross-session debt accurately.\n- **Skills (4)**: write flow `fabric-archive` (with source-mode cold-start backfill from git/docs) / `fabric-review` (with retire-deprecation + relate-edge sub-flows); store ops `fabric-store` / `fabric-sync`.\n- **Language**: rendered per the `language` field in `~/.fabric/fabric-global.json` (machine-wide tone).\n- **Archive cadence nudge** (rc.36 / finish\u2192archive): after a significant decision lands or an edit batch reaches config `archive_edit_threshold` (default 20), lightly self-trigger `fabric-archive` at a suitable turn (max 1 per turn; not a task engine / not Stop-hook flood). Stop hook remains a soft threshold nudge per KT-DEC-0007 \u2014 without an archive cadence the KB slowly dies.\n- **Review backlog nudge** (rc.36): to judge the pending backlog, go through `fab_pending action=\"list\"` or the `pending_path` returned by `fabric-review`; don't glob the project-local `.fabric/knowledge/pending`. When the visible pending count exceeds 10, proactively propose the `fabric-review` skill at a suitable turn to batch-review and avoid draft deadlock.\n\n## Self-archive policy (v2.2 C1: lean spec)\n\nWhen a clear archival signal appears, autonomously invoke the `fabric-archive` skill at the end of that turn (AI self-trigger entry E3):\n\n- **Trigger** (either): \u2460 **User-driven normative** \u2014 the user says `\u4EE5\u540E` / `always` / `never` / `\u4E0B\u6B21` / `\u8BB0\u4E00\u4E0B`, or locks a direction with rationale after weighing \u22652 candidates, or rejects a suggestion and states a reason (the reason is knowledge); \u2461 **Wrong-turn-and-revert** \u2014 you tried path X, then after reflection switched to path Y (a two-step \"negate + replace\" structure, not mere exploratory failure).\n- **Does NOT trigger**: pure user questions / simple refactor\u00B7typo / a baseless \"I learned something\" insight.\n- **Anti-loop**: at most 1 self-invocation per turn; no repeat for the same outcome in the same session; the skill's Phase 2.5 viability gate is the backstop.\n- **Receipt (marker-free)**: just invoke the `fabric-archive` skill directly \u2014 no marker string to print: the skill routes an AI self-invocation to E3 by default (deterministic else-branch, no longer dependent on the AI emitting an exact string). The skill returns `pending_path` after writing pending \u2014 reply `undo` if it shouldn't be recorded (I'll call fab_review reject).\n\n## Cite policy (v2.2 C1: recall auto-accounting, zero first-line burden)\n\n- **Core (recall-first auto-accounting)**: before changing any file, run `fab_recall(paths=[<file-being-edited>])` first. The system auto-accounts the recalled KB as that edit's citation by \"paths recall-hit this session overlap the edit target\" \u2014\u2014 **no hand-written first reply line needed** (C1 removes the first-line `KB:` contract boilerplate: think-then-speak, recall is the real signal that a citation happened). The PreToolUse hook gives a soft nudge when it detects no relevant recall (nudge, not a gate, per KT-DEC-0007).\n- **The only time to speak up (dismissed / override)**: when you judge a recalled KB should NOT apply, say one line `dismissed: <id> (<reason>)`; reason enum `scope-mismatch | outdated | not-applicable | other:<text>`. For precise annotation you may still use a first-line `KB: <id> [applied|dismissed]` (parser retained, backward compatible).\n- **`[applied]` verification duty**: citing any id (auto or hand-written) requires first fetching the KB via fab_recall (a native Read of its body path when needed) to prevent fabricated ids. Verification failing = you cannot cite.\n- **Audit & full spec**: `fabric audit cite` reports coverage (does not block your work, only records); the full spec (contract operators / store prefix / skip\u00B7dismissed dictionaries / type routing / adjudication ladder) lives authoritatively in the `fabric-review` skill's `ref/cite-contract.md` \u2014\u2014 bootstrap keeps only the executable core.\n";
62
62
  /**
63
63
  * Locale-keyed canonical bodies. The single content-layer source consumers
64
64
  * (install writer, doctor drift comparator) select from via
@@ -7,7 +7,7 @@ import {
7
7
  BOOTSTRAP_REGEX,
8
8
  matchBootstrapCanonicalLocale,
9
9
  resolveBootstrapCanonical
10
- } from "../chunk-DNIICOSG.js";
10
+ } from "../chunk-V7IUN5U2.js";
11
11
  import "../chunk-OX6DWUK4.js";
12
12
  import "../chunk-C7WZPYZE.js";
13
13
  export {
package/dist/theme.d.ts CHANGED
@@ -5,7 +5,7 @@ declare const ANSI: {
5
5
  };
6
6
  declare const PALETTE: {
7
7
  readonly success: "\u001B[38;2;46;204;113m";
8
- readonly warn: "\u001B[38;2;241;196;15m";
8
+ readonly warn: "\u001B[38;2;180;120;0m";
9
9
  readonly error: "\u001B[38;2;231;76;60m";
10
10
  readonly drift: "\u001B[38;2;155;89;182m";
11
11
  readonly ai: "\u001B[38;2;52;152;219m";
@@ -14,8 +14,11 @@ declare const PALETTE: {
14
14
  readonly muted: "\u001B[2m";
15
15
  };
16
16
  type ThemeToken = keyof typeof PALETTE;
17
+ declare const PALETTE_256: Record<ThemeToken, string>;
17
18
  declare function isColorEnabled(env?: NodeJS.ProcessEnv, isTTY?: boolean): boolean;
18
- declare function paint(token: ThemeToken, text: string, colorOn?: boolean): string;
19
+ type ColorDepth = "none" | "ansi16" | "ansi256" | "truecolor";
20
+ declare function detectColorDepth(env?: NodeJS.ProcessEnv, isTTY?: boolean): ColorDepth;
21
+ declare function paint(token: ThemeToken, text: string, colorOn?: boolean, depth?: ColorDepth): string;
19
22
  declare const SYMBOL_ASCII: {
20
23
  readonly ok: "[ok]";
21
24
  readonly warn: "[warn]";
@@ -31,4 +34,4 @@ declare const SCOPE_BADGE_TOKEN: {
31
34
  };
32
35
  declare function scopeBadge(scope: keyof typeof SCOPE_BADGE_TOKEN, colorOn?: boolean): string;
33
36
 
34
- export { ANSI, PALETTE, SYMBOL_ASCII, type ThemeToken, headerRule, isColorEnabled, paint, scopeBadge, sectionBar, symbol };
37
+ export { ANSI, type ColorDepth, PALETTE, PALETTE_256, SYMBOL_ASCII, type ThemeToken, detectColorDepth, headerRule, isColorEnabled, paint, scopeBadge, sectionBar, symbol };
package/dist/theme.js CHANGED
@@ -7,8 +7,8 @@ var ANSI = {
7
7
  var PALETTE = {
8
8
  success: "\x1B[38;2;46;204;113m",
9
9
  // emerald
10
- warn: "\x1B[38;2;241;196;15m",
11
- // amber
10
+ warn: "\x1B[38;2;180;120;0m",
11
+ // darker amber — ISS-20260713-068 light-terminal contrast
12
12
  error: "\x1B[38;2;231;76;60m",
13
13
  // alizarin
14
14
  drift: "\x1B[38;2;155;89;182m",
@@ -21,15 +21,35 @@ var PALETTE = {
21
21
  // amethyst (headers / emphasis)
22
22
  muted: ANSI.dim
23
23
  };
24
+ var PALETTE_256 = {
25
+ success: "\x1B[38;5;77m",
26
+ warn: "\x1B[38;5;178m",
27
+ error: "\x1B[38;5;203m",
28
+ drift: "\x1B[38;5;141m",
29
+ ai: "\x1B[38;5;75m",
30
+ human: "\x1B[38;5;80m",
31
+ accent: "\x1B[38;5;141m",
32
+ muted: ANSI.dim
33
+ };
24
34
  function isColorEnabled(env = process.env, isTTY) {
25
35
  if (env.NO_COLOR) return false;
26
36
  const force = env.FORCE_COLOR;
27
37
  if (force !== void 0) return force !== "0" && force.toLowerCase() !== "false";
28
38
  return Boolean(isTTY ?? process.stdout.isTTY);
29
39
  }
30
- function paint(token, text, colorOn = isColorEnabled()) {
31
- if (!colorOn) return text;
32
- return `${PALETTE[token]}${text}${ANSI.reset}`;
40
+ function detectColorDepth(env = process.env, isTTY) {
41
+ if (!isColorEnabled(env, isTTY)) return "none";
42
+ const colorterm = (env.COLORTERM || "").toLowerCase();
43
+ if (colorterm.includes("truecolor") || colorterm.includes("24bit")) return "truecolor";
44
+ const term = (env.TERM || "").toLowerCase();
45
+ if (term.includes("256color") || term.includes("256")) return "ansi256";
46
+ if (term === "linux" || term === "dumb") return "ansi16";
47
+ return "truecolor";
48
+ }
49
+ function paint(token, text, colorOn = isColorEnabled(), depth = detectColorDepth()) {
50
+ if (!colorOn || depth === "none") return text;
51
+ const pal = depth === "ansi256" ? PALETTE_256 : PALETTE;
52
+ return `${pal[token]}${text}${ANSI.reset}`;
33
53
  }
34
54
  var SYMBOL_ASCII = { ok: "[ok]", warn: "[warn]", error: "[error]" };
35
55
  var SYMBOL_GLYPH = { ok: "[ok] \u2713", warn: "[warn] !", error: "[error] x" };
@@ -54,7 +74,9 @@ function scopeBadge(scope, colorOn = isColorEnabled()) {
54
74
  export {
55
75
  ANSI,
56
76
  PALETTE,
77
+ PALETTE_256,
57
78
  SYMBOL_ASCII,
79
+ detectColorDepth,
58
80
  headerRule,
59
81
  isColorEnabled,
60
82
  paint,
@@ -1,2 +1,2 @@
1
- export { a as AgentsIdentitySource, d as AgentsMeta, e as AgentsMetaCountersEnvelope, g as AgentsMetaKnowledgeTypeCounters, A as AgentsMetaNode, b as AgentsTopologyType, h as AiLedgerEntry, i as AuditMode, C as ClientPaths, D as DefaultLayerFilter, F as FabricConfig, j as FabricLanguage, m as HumanLedgerEntry, H as HumanLockEntry, L as LedgerEntry, n as McpPayloadLimits, o as RecallScore, p as RecallScoreBreakdown, q as RuleDescription, r as RuleDescriptionIndexItem } from '../index-B2e0wKJi.js';
1
+ export { a as AgentsIdentitySource, d as AgentsMeta, e as AgentsMetaCountersEnvelope, g as AgentsMetaKnowledgeTypeCounters, A as AgentsMetaNode, b as AgentsTopologyType, h as AiLedgerEntry, i as AuditMode, C as ClientPaths, D as DefaultLayerFilter, F as FabricConfig, j as FabricLanguage, m as HumanLedgerEntry, H as HumanLockEntry, L as LedgerEntry, n as McpPayloadLimits, o as RecallScore, p as RecallScoreBreakdown, q as RuleDescription, r as RuleDescriptionIndexItem } from '../index-KvxqMZV1.js';
2
2
  import 'zod';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fenglimg/fabric-shared",
3
- "version": "2.3.0-rc.15",
3
+ "version": "2.3.0-rc.16",
4
4
  "description": "Fabric shared types — Zod schemas, i18n, atomic-write helpers, MCP payload guard, error classes. Consumed by @fenglimg/fabric-server + @fenglimg/fabric-cli.",
5
5
  "license": "MIT",
6
6
  "author": "wangzhichao <fenglimg90@gmail.com>",