@fenglimg/fabric-cli 2.1.0-rc.2 → 2.2.0-rc.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/README.md +8 -5
  2. package/dist/chunk-27HK6H5Y.js +69 -0
  3. package/dist/{chunk-BATF4PEJ.js → chunk-2KBCTMID.js} +31 -8
  4. package/dist/chunk-3D7B2UAZ.js +149 -0
  5. package/dist/{chunk-MF3OTILQ.js → chunk-3IOLS5EK.js} +48 -42
  6. package/dist/{plan-context-hint-FC6P3WFE.js → chunk-722JU5BP.js} +52 -12
  7. package/dist/{chunk-F46ORPOA.js → chunk-7ZDXBOOU.js} +271 -166
  8. package/dist/{doctor-QVNPHLJK.js → chunk-E7HJUU34.js} +248 -72
  9. package/dist/chunk-EOT63RDH.js +36 -0
  10. package/dist/chunk-FNHDQTPC.js +16 -0
  11. package/dist/chunk-HORSMSZL.js +26 -0
  12. package/dist/chunk-NLNH64A3.js +43 -0
  13. package/dist/{chunk-WU6GAPKH.js → chunk-PTGQAZEW.js} +12 -4
  14. package/dist/chunk-QFIVFZRH.js +13 -0
  15. package/dist/chunk-QPAW6IYT.js +387 -0
  16. package/dist/{chunk-COI5VDFU.js → chunk-WA3DYGSY.js} +1 -2
  17. package/dist/{config-XJIPZNUP.js → config-A3LTECAY.js} +4 -3
  18. package/dist/context-UJCGYOT6.js +117 -0
  19. package/dist/doctor-MDTZWKBK.js +24 -0
  20. package/dist/index.d.ts +2 -2
  21. package/dist/index.js +167 -16
  22. package/dist/info-7FKBTMVO.js +139 -0
  23. package/dist/install-v2-RINEA24K.js +3279 -0
  24. package/dist/{metrics-ACEQFPDU.js → metrics-HMFH4YHK.js} +22 -9
  25. package/dist/{onboard-coverage-MFCAEBDO.js → onboard-coverage-XSG77LL3.js} +48 -27
  26. package/dist/plan-context-hint-5TNGH3R4.js +12 -0
  27. package/dist/scope-explain-HLJZ2M33.js +48 -0
  28. package/dist/status-4R3TM4FJ.js +37 -0
  29. package/dist/store-HOCORVL3.js +563 -0
  30. package/dist/sync-DT5UJMMR.js +418 -0
  31. package/dist/{uninstall-TAXSUSKH.js → uninstall-IFN2KYBK.js} +128 -140
  32. package/dist/whoami-ITGEFWH4.js +49 -0
  33. package/package.json +7 -5
  34. package/templates/hooks/cite-policy-evict.cjs +412 -160
  35. package/templates/hooks/configs/README.md +14 -27
  36. package/templates/hooks/configs/claude-code.json +17 -2
  37. package/templates/hooks/configs/codex-hooks.json +15 -3
  38. package/templates/hooks/fabric-hint.cjs +573 -180
  39. package/templates/hooks/knowledge-hint-broad.cjs +648 -190
  40. package/templates/hooks/knowledge-hint-narrow.cjs +123 -77
  41. package/templates/hooks/lib/banner-i18n.cjs +31 -0
  42. package/templates/hooks/lib/bindings-snapshot-reader.cjs +118 -7
  43. package/templates/hooks/lib/cite-line-parser.cjs +12 -20
  44. package/templates/hooks/lib/client-adapter.cjs +66 -7
  45. package/templates/hooks/lib/injection-log.cjs +91 -0
  46. package/templates/hooks/lib/nudge-policy.cjs +117 -0
  47. package/templates/hooks/lib/state-store.cjs +90 -11
  48. package/templates/hooks/post-tooluse-mutation.cjs +386 -0
  49. package/templates/hooks/session-end-marker.cjs +140 -0
  50. package/templates/skills/fabric/SKILL.md +100 -0
  51. package/templates/skills/fabric-archive/SKILL.md +35 -24
  52. package/templates/skills/fabric-archive/ref/dry-run-scope.md +1 -1
  53. package/templates/skills/fabric-archive/ref/i18n-policy.md +2 -3
  54. package/templates/skills/fabric-archive/ref/phase-1-5-onboard.md +2 -3
  55. package/templates/skills/fabric-archive/ref/phase-1-cross-session.md +1 -1
  56. package/templates/skills/fabric-archive/ref/phase-2-5-viability.md +1 -1
  57. package/templates/skills/fabric-archive/ref/phase-3-6-related-edges.md +18 -0
  58. package/templates/skills/fabric-archive/ref/phase-3-7-semantic-scope.md +47 -0
  59. package/templates/skills/fabric-audit/SKILL.md +63 -0
  60. package/templates/skills/fabric-connect/SKILL.md +48 -0
  61. package/templates/skills/fabric-import/SKILL.md +7 -7
  62. package/templates/skills/fabric-import/ref/i18n-policy.md +2 -3
  63. package/templates/skills/fabric-import/ref/state-recovery.md +1 -2
  64. package/templates/skills/fabric-review/SKILL.md +16 -5
  65. package/templates/skills/fabric-review/ref/cite-contract.md +56 -0
  66. package/templates/skills/fabric-review/ref/i18n-policy.md +2 -3
  67. package/templates/skills/fabric-review/ref/output-contract.md +1 -1
  68. package/templates/skills/fabric-review/ref/per-mode-flows.md +2 -2
  69. package/templates/skills/fabric-review/ref/worked-examples.md +1 -1
  70. package/templates/skills/fabric-store/SKILL.md +44 -0
  71. package/templates/skills/fabric-sync/SKILL.md +1 -1
  72. package/templates/skills/lib/shared-policy.md +2 -2
  73. package/dist/chunk-HFQVXY6P.js +0 -86
  74. package/dist/chunk-L4Q55UC4.js +0 -52
  75. package/dist/chunk-LFIKMVY7.js +0 -27
  76. package/dist/chunk-PWLW3B57.js +0 -18
  77. package/dist/chunk-RYAFBNES.js +0 -33
  78. package/dist/chunk-T5RPGCCM.js +0 -40
  79. package/dist/chunk-WWNXR34K.js +0 -49
  80. package/dist/install-2HDO5FTQ.js +0 -2683
  81. package/dist/scope-explain-2F2R5URO.js +0 -33
  82. package/dist/status-GLQWLWH6.js +0 -23
  83. package/dist/store-XTSE5TY6.js +0 -105
  84. package/dist/sync-BJCWDPNC.js +0 -245
  85. package/dist/whoami-B6AEMSEV.js +0 -31
  86. package/templates/hooks/configs/cursor-hooks.json +0 -18
  87. package/templates/hooks/lib/cite-contract-reminder.cjs +0 -179
  88. package/templates/hooks/lib/summary-fallback.cjs +0 -210
@@ -0,0 +1,56 @@
1
+ # Cite-contract + 裁决阶梯参考 (v2.2 SK5)
2
+
3
+ > 本文是 cite policy 与裁决(adjudication)的**权威详参**,从 bootstrap (`.fabric/AGENTS.md`) 下沉至此,避免 bootstrap 随治理细节膨胀。bootstrap 只留**可执行 core**(cite 行格式 + 验证义务 + operator 例),完整 enum 词典 / 类型路由 / 稽核 / backward-compat / 裁决阶梯看这里。`fabric doctor --cite-coverage` 的稽核口径以本文为准。
4
+
5
+ ## 1. Cite 行格式 (回顾)
6
+
7
+ edit / decide / propose plan 之前,**回复首行**:
8
+
9
+ ```
10
+ KB: <id> (<≤8字 用法>) [applied|dismissed:<reason>]
11
+ KB: none [<reason>]
12
+ ```
13
+
14
+ - `[applied]` 前必须先 `fab_recall`(并按需对其正文路径做原生 Read)实际抓 KB body —— 防编造 id。验证不通过 = 不能 cite。
15
+ - **store 前缀** (多 store):read-set 含多 store 且同一 local id 跨 store shadow 时,cite 必须 store-qualified:`KB: <store-alias>:<id> ...`(如 `KB: team:KT-DEC-0001 (auth) [applied]`)。单 store / 无歧义时裸 `KB: <id>` 仍 valid。personal-only 条目 cite 进团队产物 = 强 warning(防泄漏 R5#3)。
16
+
17
+ ## 2. Contract 语法 (decisions/pitfalls 类 `[applied]`)
18
+
19
+ cite 尾段加 contract:`→ <operator> [<operator> ...]`
20
+
21
+ | operator | 含义 |
22
+ |---|---|
23
+ | `edit:<glob>` | 本 cite 承诺会改的文件范围 |
24
+ | `!edit:<glob>` | 承诺**不**改的范围 |
25
+ | `require:<symbol>` | 实现必须含某 symbol |
26
+ | `forbid:<symbol>` | 实现必须不含某 symbol |
27
+ | `skip:<reason>` | 本条 applied 但某 operator 跳过,附理由 |
28
+
29
+ 例:`KB: K-001 (auth) [applied] → edit:src/auth/**/*.ts !edit:src/legacy/**`
30
+
31
+ ## 3. 枚举词典
32
+
33
+ - **skip reason**:`sequencing | conditional | semantic | aesthetic | architectural | other:<text>`
34
+ - **dismissed reason**:`scope-mismatch | outdated | not-applicable | other:<text>`
35
+ - **`KB: none` sentinel**:`[no-relevant]`(已调 recall/plan_context 但无可用条目) / `[not-applicable]`(当前动作不在 cite 范围:纯探索 / Bash 只读 / 用户问答)。裸 `KB: none` 仍 valid,归 `[unspecified]`(legacy 兼容)。
36
+
37
+ ## 4. 类型路由
38
+
39
+ - `models` 类引用 = reference cite,**不需 contract**。
40
+ - `guidelines` / `processes` 类暂不强制 contract,推后 LLM-judge。
41
+ - `decisions` / `pitfalls` 类 `[applied]` **需** contract。
42
+
43
+ ## 5. 稽核 + Backward compat
44
+
45
+ - 稽核:`fabric doctor --cite-coverage [--since=7d] [--client=cc|codex|all]` 输出覆盖率,含 `KB: none` sentinel 拆分。不阻断工作,只记录。
46
+ - Backward compat:解析器同时接受老 4-state tags(`planned` / `recalled` / `chained-from <id>`),都映射到 `[applied]` 语义;旧 session cite 仍计入 cite-coverage。
47
+
48
+ ## 6. 裁决阶梯 (adjudication ladder)
49
+
50
+ 执行中遇到**需要拍板**的分歧(plan 选型 / review 取舍 / cross-LLM 不一致),按三级阶梯收口,**只有真正属于 human 的决定才阻塞**:
51
+
52
+ 1. **AI 自决** — 已有清晰证据 + 明确推荐时,直接执行,记 rationale。不为有默认值的选择拆 sub-question。
53
+ 2. **多-LLM 评审(含 ≥1 零上下文冷评)** — 主观 / 高风险 / 跨 LLM 分歧时,maestro delegate ≥2 LLM(至少一个零上下文,防执行者自我合理化)。一致 PASS 自动闭;一致 BLOCK + fix verbatim 采纳重跑。
54
+ 3. **非阻塞队列** — 仍分歧 / 主观 / 不可逆 / 属 frame 级(只有 human 能挑战 frame)→ 升 `needs_adjudication` 非阻塞队列,带两方理由 + AI 倾向裁决,继续推进不卡死。
55
+
56
+ **Anchor**:critic 只能 frame 内审计;多-LLM 收敛 ≠ 正确,frame 级判断留给 human。cross-LLM 给 suggested fix 时直接 verbatim 采纳(+ trade-off 注释)。
@@ -39,13 +39,13 @@ Rendering rule:
39
39
 
40
40
  - `fabric_language === "zh-CN"` → emit the zh-CN variant; pure monolingual, no language mixing inside a single user-facing block.
41
41
  - `fabric_language === "en"` → emit the en variant; pure monolingual, no language mixing inside a single user-facing block.
42
- - `fabric_language === "zh-CN-hybrid"` → emit Chinese narrative prose with English technical terms preserved. Protected tokens (always EN): MCP tool names (e.g. `fab_get_knowledge_sections`), CLI command names (e.g. `fabric install`), file paths, technical concepts (`Skill`, `SessionStart`, `hook`, `MCP`, `revision_hash`, `pending`, `proven`, `verified`, `draft`).
42
+ - `fabric_language === "zh-CN-hybrid"` → emit Chinese narrative prose with English technical terms preserved. Protected tokens (always EN): MCP tool names (e.g. `fab_recall`), CLI command names (e.g. `fabric install`), file paths, technical concepts (`Skill`, `SessionStart`, `hook`, `MCP`, `revision_hash`, `pending`, `proven`, `verified`, `draft`).
43
43
  - `fabric_language === "match-existing"` or any other value → emit the en variant; pure monolingual.
44
44
 
45
45
  Protected tokens (`fab_review`, `relevance_scope`, `relevance_paths`,
46
46
  `narrow`, `broad`, `source_sessions`, `proposed_reason`, `session_context`,
47
47
  `pending_path`, `layer`, `team`, `personal`, `knowledge_scope_degraded`,
48
- `MUST`, `NEVER`, `.fabric/knowledge/`, etc.) are NEVER translated — they
48
+ `MUST`, `NEVER`, `knowledge/pending`, etc.) are NEVER translated — they
49
49
  appear verbatim in both language variants. The bilingualization scope is
50
50
  prose ONLY.
51
51
 
@@ -108,4 +108,3 @@ the option-list invariants that downstream tooling (the Skill's own
108
108
  `switch` statements over `choice`, plus any future MCP-level audit lint
109
109
  that scans for these specific string literals) depends on. Keeping
110
110
  `options[]` English-only is contract-locked across all three skills.
111
-
@@ -44,7 +44,7 @@ After each invocation, the skill MUST produce a brief roll-up to the user. UX i1
44
44
  - knowledge_deferred ×D
45
45
  ```
46
46
 
47
- Also surface a one-line `git status` of `.fabric/knowledge/` so the user sees the file moves caused by approve / layer-flip.
47
+ Also surface the target store alias/UUID for every mutation so the user can inspect that store repo's `git status` when needed.
48
48
 
49
49
  ## events.jsonl Constraint Note
50
50
 
@@ -75,7 +75,7 @@ Full bilingual rendering blocks + step-by-step procedures for the four modes ref
75
75
 
76
76
  1. Extract the topic keyword(s) from the user's message (e.g. "find about deepMerge" → query="deepMerge").
77
77
  2. Call `fab_review action="search"` with `query` and any obvious filters (if user said "team-only" → `filters.layer="team"`).
78
- 3. Server returns `items[]` ranked by relevance — these are entries already in `.fabric/knowledge/{layer}/{type}/` (NOT pending), unless `filters` says otherwise.
78
+ 3. Server returns `items[]` ranked by relevance — these are entries already in mounted store `knowledge/<type>/` (NOT pending), unless `filters` says otherwise.
79
79
  4. Render top-N (cap at `review_topic_result_cap`, config-resolved, default 8) results with title / summary / pending_path.
80
80
  5. If the user follow-up indicates intent to act ("approve all", "modify the second one"), pivot into the corresponding pending mode action — the search result already gives the `pending_path` needed for the action.
81
81
  6. NEVER surface a per-item AskUserQuestion just for browsing — only when the user signals an action verb.
@@ -134,7 +134,7 @@ Full bilingual rendering blocks + step-by-step procedures for the four modes ref
134
134
  ## Mode: revisit — Specific Entry Deep Dive
135
135
 
136
136
  1. The user referenced a specific entry (by id `KT-D-7` or by slug `single-cjs-hook`).
137
- 2. Call `fab_review action="list"` with `filters` narrowed by best-guess fields; if the entry is canonical (has stable_id), `Read` the file directly at `.fabric/knowledge/{layer}/{type}/<id>--<slug>.md`.
137
+ 2. Call `fab_review action="list"` with `filters` narrowed by best-guess fields; if the entry is canonical (has stable_id), use the path returned by `fab_review` instead of inventing a store path.
138
138
  3. Display the full body (frontmatter + content). Tail the events.jsonl for any history events tagged with this stable_id.
139
139
  4. Surface AskUserQuestion `{options: ["approve", "modify", "reject", "skip"]}` only if the entry is still pending; for canonical entries the only mutation path is `modify` (incl. layer flip).
140
140
 
@@ -36,7 +36,7 @@ Inferred mode: `revisit` (Step 1 keyword "look at <id>").
36
36
 
37
37
  Skill flow:
38
38
 
39
- 1. Read `.fabric/knowledge/team/guidelines/KT-G-0003--indent-style.md`. Display body to user.
39
+ 1. Read the canonical path returned by `fab_review search` for `KT-G-0003`. Display body to user.
40
40
  2. AskUserQuestion `{options: ["approve", "modify", "reject", "skip"]}` — user picks `modify`.
41
41
  3. Skill detects user-stated intent "actually personal not team" — surface AskUserQuestion `{options: ["team", "personal"]}` with current layer=team noted; user confirms `personal`.
42
42
  4. Call:
@@ -0,0 +1,44 @@
1
+ ---
2
+ name: fabric-store
3
+ description: 知识 store 运维门面 — 创建 / 挂载 / 绑定 / 列出 / 切换写目标。CLI `fabric store …` 做事,本 skill 按用户意图选命令。NOT for git-managing 用户自己的产品仓。Triggers 创建 store/挂载 store/绑定知识库/store 列表/切换写库/set up knowledge store.
4
+ ---
5
+
6
+ # fabric-store — 知识 store 运维
7
+
8
+ 每个「知识 store」操作的对话入口。CLI (`fabric store …`) 是引擎;本 skill 按用户意图挑命令。*store* 是 `~/.fabric/stores/<uuid>/` 下的平行 git 仓 —— 与用户的产品仓不同。同步 (pull+push) 见姊妹 skill `fabric-sync`。
9
+
10
+ ## When to use
11
+
12
+ - 「创建团队 store」「建个人知识 store」
13
+ - 「挂载团队 store」「这个项目要绑团队 store」
14
+ - 「列出挂了哪些 store?」「我的共享决策写到哪个 store?」
15
+
16
+ ## When NOT to use
17
+
18
+ - git 同步用户自己的产品仓 (那是普通 `git`)。
19
+ - 同步知识 store (pull/push 冲突解决) → 用 `fabric-sync` skill。
20
+ - 写知识条目 → 用 `fabric-archive` / `fabric-review`。
21
+
22
+ ## 意图 → 命令映射
23
+
24
+ | 意图 | 命令 |
25
+ |---|---|
26
+ | 创建全新本地 store | `fabric store create --alias <a> [--remote <url>]` |
27
+ | 挂载已存在的磁盘 store | `fabric store add --uuid <u> --alias <a> [--remote <url>]` |
28
+ | 本项目声明需要某 store | `fabric store bind <alias-or-uuid>` |
29
+ | 列出挂载的 store | `fabric store list` |
30
+ | 设置非 personal scope 的写目标 | `fabric store switch-write <alias>` |
31
+ | 解释某 alias 如何解析 | `fabric store explain <alias>` |
32
+ | 同步 (pull+push) | 见 `fabric-sync` skill |
33
+
34
+ ## Precondition
35
+
36
+ 已 `fabric install --global` (存在 `~/.fabric` + 全局 store registry)。无全局配置 → 提示先 `fabric install --global`,停止。
37
+
38
+ ## Constraints
39
+
40
+ - `store remove` 是 *detach ≠ delete*:从 registry 卸载但 MUST 保留磁盘 git 树。
41
+ - `store add` MUST 拒绝磁盘无 store 树的 uuid (无「幽灵挂载」) —— 先 clone (`fabric install --global --url <remote>`) 或 `store create`。
42
+ - 知识条目写在各 store 的 `knowledge/` 下;本 skill 只管 store 生命周期,不写条目。
43
+ - Personal-scope 写永远落在隐式 personal store,与 active write store 无关。
44
+ - Hook/skill NEVER 直接解析 store 或执行 store 内文件 (S65 RCE 防线:store 是数据-only);所有 store 状态 MUST 经 CLI JSON 输出获取。
@@ -26,7 +26,7 @@ description: 多 store git 同步辅助 — 遍历挂载的知识 store, pull --
26
26
  ## Phase 2 — AI-assisted conflict resolution (仅冲突时)
27
27
 
28
28
  冲突 store 的工作区停在 rebase 中途。辅助用户:
29
- 1. 展示冲突文件 (store 知识树 `.fabric/knowledge/<type>/*.md` 中的 `<<<<<<<`/`=======`/`>>>>>>>` 段)。
29
+ 1. 展示冲突文件 (store 知识树 `knowledge/<type>/*.md` 中的 `<<<<<<<`/`=======`/`>>>>>>>` 段)。
30
30
  2. 对每个冲突,MUST 解释两侧 (ours = 本地草稿/晋升, theirs = 远端协作者) 并给出**合并建议**(知识条目通常可并存或取更成熟 maturity)。NEVER 擅自丢弃任一侧未经用户确认。
31
31
  3. 用户解决后 → `fabric sync --continue` (git rebase --continue + 恢复遍历剩余 store)。
32
32
  4. 用户选择放弃该 store → `fabric sync --abort` (git rebase --abort,该 store 留未同步,继续遍历其余)。
@@ -11,13 +11,13 @@ When rendering bilingual (zh-CN ↔ en) output, prose is translated but the
11
11
  following classes of token appear **verbatim in both variants**:
12
12
 
13
13
  - **MCP tool + field names**: `fab_extract_knowledge`, `fab_review`,
14
- `fab_recall`, `fab_plan_context`, `fab_get_knowledge_sections`,
14
+ `fab_recall`, `fab_archive_scan`,
15
15
  `relevance_scope`, `relevance_paths`, `source_sessions`, `proposed_reason`,
16
16
  `session_context`, `intent_clues`, `tech_stack`, `impact`, `must_read_if`,
17
17
  `evidence_paths`, `tags`, `pending_path`, `layer`.
18
18
  - **Enum / routing values**: `narrow`, `broad`, `team`, `personal`, `draft`,
19
19
  `verified`, `proven`, `knowledge_scope_degraded`.
20
- - **Imperatives + paths**: `MUST`, `NEVER`, `.fabric/knowledge/`, file paths.
20
+ - **Imperatives + paths**: `MUST`, `NEVER`, `knowledge/pending`, file paths.
21
21
 
22
22
  The authoritative machine-checked list is `PROTECTED_TOKENS` in
23
23
  `@fenglimg/fabric-shared` (enforced by `scripts/lint-protected-tokens.ts`).
@@ -1,86 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- loadProjectConfig,
4
- saveProjectConfig
5
- } from "./chunk-LFIKMVY7.js";
6
- import {
7
- loadGlobalConfig,
8
- resolveGlobalRoot,
9
- saveGlobalConfig
10
- } from "./chunk-RYAFBNES.js";
11
-
12
- // src/store/store-ops.ts
13
- import {
14
- addMountedStore,
15
- bindRequiredStore,
16
- detachMountedStore,
17
- explainStore
18
- } from "@fenglimg/fabric-shared";
19
- var NO_GLOBAL_CONFIG = "no global Fabric config found \u2014 run `fabric install --global <url>` first";
20
- function requireConfig(globalRoot) {
21
- const config = loadGlobalConfig(globalRoot);
22
- if (config === null) {
23
- throw new Error(NO_GLOBAL_CONFIG);
24
- }
25
- return config;
26
- }
27
- function storeList(globalRoot = resolveGlobalRoot()) {
28
- return requireConfig(globalRoot).stores;
29
- }
30
- function storeAdd(store, globalRoot = resolveGlobalRoot()) {
31
- const next = addMountedStore(requireConfig(globalRoot), store);
32
- saveGlobalConfig(next, globalRoot);
33
- return next;
34
- }
35
- function storeRemove(alias, globalRoot = resolveGlobalRoot()) {
36
- const result = detachMountedStore(requireConfig(globalRoot), alias);
37
- saveGlobalConfig(result.config, globalRoot);
38
- return result;
39
- }
40
- function storeExplain(alias, globalRoot = resolveGlobalRoot()) {
41
- return explainStore(requireConfig(globalRoot), alias);
42
- }
43
- var NO_PROJECT_CONFIG = "no project Fabric config \u2014 run `fabric install` in this repo first";
44
- function requireProjectConfig(projectRoot) {
45
- const config = loadProjectConfig(projectRoot);
46
- if (config === null) {
47
- throw new Error(NO_PROJECT_CONFIG);
48
- }
49
- return config;
50
- }
51
- function storeBind(projectRoot, entry) {
52
- const config = requireProjectConfig(projectRoot);
53
- const next = {
54
- ...config,
55
- required_stores: bindRequiredStore(config.required_stores ?? [], entry)
56
- };
57
- saveProjectConfig(next, projectRoot);
58
- return next;
59
- }
60
- function storeSwitchWrite(projectRoot, alias) {
61
- const config = requireProjectConfig(projectRoot);
62
- const next = { ...config, active_write_store: alias };
63
- saveProjectConfig(next, projectRoot);
64
- return next;
65
- }
66
- function missingRequiredStores(projectRoot, globalRoot = resolveGlobalRoot()) {
67
- const project = loadProjectConfig(projectRoot);
68
- if (project === null || project.required_stores === void 0) {
69
- return [];
70
- }
71
- const global = loadGlobalConfig(globalRoot);
72
- const mounted = new Set(
73
- (global?.stores ?? []).flatMap((s) => [s.alias, s.store_uuid])
74
- );
75
- return project.required_stores.filter((r) => !mounted.has(r.id));
76
- }
77
-
78
- export {
79
- storeList,
80
- storeAdd,
81
- storeRemove,
82
- storeExplain,
83
- storeBind,
84
- storeSwitchWrite,
85
- missingRequiredStores
86
- };
@@ -1,52 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- loadProjectConfig
4
- } from "./chunk-LFIKMVY7.js";
5
- import {
6
- loadGlobalConfig,
7
- resolveGlobalRoot
8
- } from "./chunk-RYAFBNES.js";
9
-
10
- // src/store/scope-explain.ts
11
- import {
12
- createStoreResolver
13
- } from "@fenglimg/fabric-shared";
14
- function buildResolveInput(projectRoot, globalRoot = resolveGlobalRoot()) {
15
- const global = loadGlobalConfig(globalRoot);
16
- if (global === null) {
17
- return null;
18
- }
19
- const project = loadProjectConfig(projectRoot);
20
- return {
21
- uid: global.uid,
22
- mountedStores: global.stores.map((s) => ({
23
- store_uuid: s.store_uuid,
24
- alias: s.alias,
25
- ...s.remote === void 0 ? {} : { remote: s.remote },
26
- writable: s.writable ?? true,
27
- personal: s.personal ?? false
28
- })),
29
- requiredStores: (project?.required_stores ?? []).map((r) => ({
30
- id: r.id,
31
- ...r.suggested_remote === void 0 ? {} : { suggested_remote: r.suggested_remote }
32
- })),
33
- ...project?.active_write_store === void 0 ? {} : { activeWriteAlias: project.active_write_store }
34
- };
35
- }
36
- function scopeExplain(projectRoot, scope, globalRoot = resolveGlobalRoot()) {
37
- const input = buildResolveInput(projectRoot, globalRoot);
38
- if (input === null) {
39
- return null;
40
- }
41
- const resolver = createStoreResolver();
42
- return {
43
- scope,
44
- readSet: resolver.resolveReadSet(input),
45
- writeTarget: resolver.resolveWriteTarget(input, scope).target
46
- };
47
- }
48
-
49
- export {
50
- buildResolveInput,
51
- scopeExplain
52
- };
@@ -1,27 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // src/store/project-config-io.ts
4
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
5
- import { join } from "path";
6
- import { fabricConfigSchema } from "@fenglimg/fabric-shared";
7
- function projectConfigPath(projectRoot) {
8
- return join(projectRoot, ".fabric", "fabric-config.json");
9
- }
10
- function loadProjectConfig(projectRoot) {
11
- const path = projectConfigPath(projectRoot);
12
- if (!existsSync(path)) {
13
- return null;
14
- }
15
- return fabricConfigSchema.parse(JSON.parse(readFileSync(path, "utf8")));
16
- }
17
- function saveProjectConfig(config, projectRoot) {
18
- const validated = fabricConfigSchema.parse(config);
19
- mkdirSync(join(projectRoot, ".fabric"), { recursive: true });
20
- writeFileSync(projectConfigPath(projectRoot), `${JSON.stringify(validated, null, 2)}
21
- `, "utf8");
22
- }
23
-
24
- export {
25
- loadProjectConfig,
26
- saveProjectConfig
27
- };
@@ -1,18 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // src/i18n.ts
4
- import {
5
- createTranslator,
6
- detectNodeLocale,
7
- resolveFabricLocale
8
- } from "@fenglimg/fabric-shared";
9
- var locale = detectNodeLocale();
10
- var t = createTranslator(locale);
11
- function getDoctorTranslator(projectRoot) {
12
- return createTranslator(resolveFabricLocale(projectRoot));
13
- }
14
-
15
- export {
16
- t,
17
- getDoctorTranslator
18
- };
@@ -1,33 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // src/store/global-config-io.ts
4
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
5
- import { homedir } from "os";
6
- import { join } from "path";
7
- import { globalConfigSchema } from "@fenglimg/fabric-shared";
8
- function resolveGlobalRoot() {
9
- return join(process.env.FABRIC_HOME ?? homedir(), ".fabric");
10
- }
11
- function globalConfigPath(globalRoot = resolveGlobalRoot()) {
12
- return join(globalRoot, "fabric-global.json");
13
- }
14
- function loadGlobalConfig(globalRoot = resolveGlobalRoot()) {
15
- const path = globalConfigPath(globalRoot);
16
- if (!existsSync(path)) {
17
- return null;
18
- }
19
- return globalConfigSchema.parse(JSON.parse(readFileSync(path, "utf8")));
20
- }
21
- function saveGlobalConfig(config, globalRoot = resolveGlobalRoot()) {
22
- const validated = globalConfigSchema.parse(config);
23
- mkdirSync(globalRoot, { recursive: true });
24
- writeFileSync(globalConfigPath(globalRoot), `${JSON.stringify(validated, null, 2)}
25
- `, "utf8");
26
- }
27
-
28
- export {
29
- resolveGlobalRoot,
30
- globalConfigPath,
31
- loadGlobalConfig,
32
- saveGlobalConfig
33
- };
@@ -1,40 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- loadProjectConfig
4
- } from "./chunk-LFIKMVY7.js";
5
- import {
6
- loadGlobalConfig,
7
- resolveGlobalRoot
8
- } from "./chunk-RYAFBNES.js";
9
-
10
- // src/store/info-ops.ts
11
- function whoami(globalRoot = resolveGlobalRoot()) {
12
- const config = loadGlobalConfig(globalRoot);
13
- if (config === null) {
14
- return null;
15
- }
16
- return {
17
- uid: config.uid,
18
- stores: config.stores.map((s) => ({
19
- alias: s.alias,
20
- store_uuid: s.store_uuid,
21
- local_only: s.remote === void 0
22
- }))
23
- };
24
- }
25
- function projectStatus(projectRoot, globalRoot = resolveGlobalRoot()) {
26
- const global = loadGlobalConfig(globalRoot);
27
- const project = loadProjectConfig(projectRoot);
28
- return {
29
- uid: global?.uid ?? null,
30
- mounted: (global?.stores ?? []).map((s) => s.alias),
31
- project_id: project?.project_id ?? null,
32
- required: (project?.required_stores ?? []).map((r) => r.id),
33
- active_write_store: project?.active_write_store ?? null
34
- };
35
- }
36
-
37
- export {
38
- whoami,
39
- projectStatus
40
- };
@@ -1,49 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // src/colors.ts
4
- import pc from "picocolors";
5
- import stringWidth from "string-width";
6
- function isColorEnabled() {
7
- return !process.env.NO_COLOR && Boolean(process.stdout.isTTY) && Boolean(process.stderr.isTTY);
8
- }
9
- function colorize(painter) {
10
- return (value) => isColorEnabled() ? painter(value) : value;
11
- }
12
- var paint = {
13
- success: colorize(pc.green),
14
- warn: colorize(pc.yellow),
15
- error: colorize(pc.red),
16
- drift: colorize(pc.magenta),
17
- ai: colorize(pc.blue),
18
- human: colorize(pc.cyan),
19
- muted: colorize(pc.dim)
20
- };
21
- var symbol = {
22
- get ok() {
23
- return isColorEnabled() ? paint.success("\u2713") : "[ok]";
24
- },
25
- get warn() {
26
- return isColorEnabled() ? paint.warn("!") : "[warn]";
27
- },
28
- get error() {
29
- return isColorEnabled() ? paint.error("x") : "[error]";
30
- }
31
- };
32
- function displayWidth(value) {
33
- return stringWidth(value);
34
- }
35
- function padEnd(value, width, char = " ") {
36
- const fill = char.length > 0 ? char : " ";
37
- let result = value;
38
- while (displayWidth(result) < width) {
39
- result += fill;
40
- }
41
- return result;
42
- }
43
-
44
- export {
45
- paint,
46
- symbol,
47
- displayWidth,
48
- padEnd
49
- };