@skillfm/local 2.0.4 → 2.0.6

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 (66) hide show
  1. package/dist/agent-hints.d.ts.map +1 -1
  2. package/dist/agent-hints.js +29 -14
  3. package/dist/agent-hints.js.map +1 -1
  4. package/dist/doctor.d.ts +26 -0
  5. package/dist/doctor.d.ts.map +1 -1
  6. package/dist/doctor.js +184 -0
  7. package/dist/doctor.js.map +1 -1
  8. package/dist/guard/bin.js +0 -0
  9. package/dist/guard/cli.d.ts.map +1 -1
  10. package/dist/guard/cli.js +26 -0
  11. package/dist/guard/cli.js.map +1 -1
  12. package/dist/harness/kernels/deny-pipeline.d.ts +21 -0
  13. package/dist/harness/kernels/deny-pipeline.d.ts.map +1 -0
  14. package/dist/harness/kernels/deny-pipeline.js +225 -0
  15. package/dist/harness/kernels/deny-pipeline.js.map +1 -0
  16. package/dist/harness/kernels/hook-file.d.ts +16 -0
  17. package/dist/harness/kernels/hook-file.d.ts.map +1 -0
  18. package/dist/harness/kernels/hook-file.js +229 -0
  19. package/dist/harness/kernels/hook-file.js.map +1 -0
  20. package/dist/harness/kernels/json-merge.d.ts +45 -0
  21. package/dist/harness/kernels/json-merge.d.ts.map +1 -0
  22. package/dist/harness/kernels/json-merge.js +123 -0
  23. package/dist/harness/kernels/json-merge.js.map +1 -0
  24. package/dist/harness/kernels/mcp-only.d.ts +23 -0
  25. package/dist/harness/kernels/mcp-only.d.ts.map +1 -0
  26. package/dist/harness/kernels/mcp-only.js +215 -0
  27. package/dist/harness/kernels/mcp-only.js.map +1 -0
  28. package/dist/harness/kernels/protocol-reject.d.ts +18 -0
  29. package/dist/harness/kernels/protocol-reject.d.ts.map +1 -0
  30. package/dist/harness/kernels/protocol-reject.js +117 -0
  31. package/dist/harness/kernels/protocol-reject.js.map +1 -0
  32. package/dist/harness/kernels/registry.d.ts +56 -0
  33. package/dist/harness/kernels/registry.d.ts.map +1 -0
  34. package/dist/harness/kernels/registry.js +139 -0
  35. package/dist/harness/kernels/registry.js.map +1 -0
  36. package/dist/harness/kernels/types.d.ts +86 -0
  37. package/dist/harness/kernels/types.d.ts.map +1 -0
  38. package/dist/harness/kernels/types.js +21 -0
  39. package/dist/harness/kernels/types.js.map +1 -0
  40. package/dist/index.js +467 -19
  41. package/dist/index.js.map +1 -1
  42. package/dist/mcp-output/builder.d.ts +24 -0
  43. package/dist/mcp-output/builder.d.ts.map +1 -0
  44. package/dist/mcp-output/builder.js +99 -0
  45. package/dist/mcp-output/builder.js.map +1 -0
  46. package/dist/mcp-output/deny-review.d.ts +64 -0
  47. package/dist/mcp-output/deny-review.d.ts.map +1 -0
  48. package/dist/mcp-output/deny-review.js +212 -0
  49. package/dist/mcp-output/deny-review.js.map +1 -0
  50. package/dist/mcp-output/types.d.ts +64 -0
  51. package/dist/mcp-output/types.d.ts.map +1 -0
  52. package/dist/mcp-output/types.js +21 -0
  53. package/dist/mcp-output/types.js.map +1 -0
  54. package/dist/skill-md/template.d.ts +30 -0
  55. package/dist/skill-md/template.d.ts.map +1 -0
  56. package/dist/skill-md/template.js +194 -0
  57. package/dist/skill-md/template.js.map +1 -0
  58. package/dist/skill-md/writer.d.ts +30 -0
  59. package/dist/skill-md/writer.d.ts.map +1 -0
  60. package/dist/skill-md/writer.js +129 -0
  61. package/dist/skill-md/writer.js.map +1 -0
  62. package/package.json +3 -2
  63. package/dist/lang.d.ts +0 -21
  64. package/dist/lang.d.ts.map +0 -1
  65. package/dist/lang.js +0 -62
  66. package/dist/lang.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deny-review.js","sourceRoot":"","sources":["../../src/mcp-output/deny-review.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * BSO M9.5 — MCP Protocol-Reject 输出层类型
3
+ *
4
+ * Refs:
5
+ * - docs/prd/PRD-BSO-M9-HARNESS-HOOKS.md §3.3
6
+ * - docs/research/EMERGING-AGENT-PRODUCTS-2026-04-19.md §3
7
+ * - MCP spec 2025-11-25
8
+ * · tools/call response with isError
9
+ * · elicitation/create
10
+ * · URLElicitationRequiredError (-32042)
11
+ */
12
+ export declare const MCP_OUTPUT_VERSION = "v2";
13
+ export declare const MCP_OUTPUT_FEATURES: readonly ["isError", "elicitation", "url-elicitation-required-error"];
14
+ export type McpOutputFeature = (typeof MCP_OUTPUT_FEATURES)[number];
15
+ export interface RejectInput {
16
+ /** 任务 id(生命周期内唯一,用于 elicitation 配对) */
17
+ task_id: string;
18
+ /** 触发的 9 红线 ID(S1-S9) */
19
+ redline?: string;
20
+ /** 风险等级 */
21
+ tier?: 'A' | 'B' | 'C';
22
+ /** 失败原因(中文,给用户看) */
23
+ reason: string;
24
+ /** 操作建议(中文,给用户看) */
25
+ hint?: string;
26
+ /** 触发的 tool 名 */
27
+ tool?: string;
28
+ /** sidecar 自身 base URL(构造 /deny-review/:task_id 用) */
29
+ sidecarBaseUrl: string;
30
+ /** request id (jsonrpc) — 镜像回 MCP error response */
31
+ requestId?: string | number | null;
32
+ }
33
+ export interface McpRejectEnvelope {
34
+ /** RFC 8259: 协议层错误(机制 A)*/
35
+ error?: {
36
+ jsonrpc: '2.0';
37
+ id: string | number | null;
38
+ error: {
39
+ code: -32042;
40
+ message: string;
41
+ data: {
42
+ elicitations: Array<{
43
+ mode: 'url';
44
+ elicitationId: string;
45
+ url: string;
46
+ message: string;
47
+ }>;
48
+ };
49
+ };
50
+ };
51
+ /** result + isError(机制 B,最广兼容)*/
52
+ result: {
53
+ jsonrpc: '2.0';
54
+ id: string | number | null;
55
+ result: {
56
+ content: Array<{
57
+ type: 'text';
58
+ text: string;
59
+ }>;
60
+ isError: true;
61
+ };
62
+ };
63
+ }
64
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/mcp-output/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH,eAAO,MAAM,kBAAkB,OAAO,CAAC;AAEvC,eAAO,MAAM,mBAAmB,uEAItB,CAAC;AAEX,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AAMpE,MAAM,WAAW,WAAW;IAC1B,uCAAuC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,yBAAyB;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW;IACX,IAAI,CAAC,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;IACvB,oBAAoB;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,oBAAoB;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iBAAiB;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sDAAsD;IACtD,cAAc,EAAE,MAAM,CAAC;IACvB,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;CACpC;AAMD,MAAM,WAAW,iBAAiB;IAChC,2BAA2B;IAC3B,KAAK,CAAC,EAAE;QACN,OAAO,EAAE,KAAK,CAAC;QACf,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;QAC3B,KAAK,EAAE;YACL,IAAI,EAAE,CAAC,KAAK,CAAC;YACb,OAAO,EAAE,MAAM,CAAC;YAChB,IAAI,EAAE;gBACJ,YAAY,EAAE,KAAK,CAAC;oBAClB,IAAI,EAAE,KAAK,CAAC;oBACZ,aAAa,EAAE,MAAM,CAAC;oBACtB,GAAG,EAAE,MAAM,CAAC;oBACZ,OAAO,EAAE,MAAM,CAAC;iBACjB,CAAC,CAAC;aACJ,CAAC;SACH,CAAC;KACH,CAAC;IACF,iCAAiC;IACjC,MAAM,EAAE;QACN,OAAO,EAAE,KAAK,CAAC;QACf,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;QAC3B,MAAM,EAAE;YACN,OAAO,EAAE,KAAK,CAAC;gBAAE,IAAI,EAAE,MAAM,CAAC;gBAAC,IAAI,EAAE,MAAM,CAAA;aAAE,CAAC,CAAC;YAC/C,OAAO,EAAE,IAAI,CAAC;SACf,CAAC;KACH,CAAC;CACH"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * BSO M9.5 — MCP Protocol-Reject 输出层类型
3
+ *
4
+ * Refs:
5
+ * - docs/prd/PRD-BSO-M9-HARNESS-HOOKS.md §3.3
6
+ * - docs/research/EMERGING-AGENT-PRODUCTS-2026-04-19.md §3
7
+ * - MCP spec 2025-11-25
8
+ * · tools/call response with isError
9
+ * · elicitation/create
10
+ * · URLElicitationRequiredError (-32042)
11
+ */
12
+ // ============================================================================
13
+ // 输出层版本(doctor probe 用)
14
+ // ============================================================================
15
+ export const MCP_OUTPUT_VERSION = 'v2';
16
+ export const MCP_OUTPUT_FEATURES = [
17
+ 'isError',
18
+ 'elicitation',
19
+ 'url-elicitation-required-error',
20
+ ];
21
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/mcp-output/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,+EAA+E;AAC/E,wBAAwB;AACxB,+EAA+E;AAE/E,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAEvC,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,SAAS;IACT,aAAa;IACb,gCAAgC;CACxB,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * BSO M9 v0.3 — Layer 1: SKILL.md 模板(兼容 Anthropic Skills 格式)
3
+ *
4
+ * Refs:
5
+ * - docs/prd/PRD-BSO-M9-HARNESS-HOOKS.md §3.2
6
+ * - 主公决策 Q2=B': Layer 1 文件格式 100% 对齐 Anthropic Skills 标准;
7
+ * Layer 2/3 拦截协议保持 SkillFM 差异化。
8
+ *
9
+ * 文件格式:YAML frontmatter + Markdown body
10
+ * frontmatter 字段(Anthropic Skills 标准):
11
+ * - name: 唯一 slug
12
+ * - description: 何时触发本 skill 的描述(写给 LLM 看)
13
+ * - license: 默认 Apache-2.0
14
+ * - allowed-tools: skill 调用的 tool 白名单
15
+ * - metadata: 自定义字段(嵌套,不污染顶层)
16
+ *
17
+ * 写入位置(由 writer.ts 决定):
18
+ * - 项目级:./SKILL.md
19
+ * - Anthropic Claude Code 用户级(可选):~/.claude/skills/skillfm-bso/SKILL.md
20
+ */
21
+ export type SkillLang = 'zh' | 'en' | 'auto';
22
+ export declare const SKILL_MD_BEGIN = "<!-- SKILLFM-SKILL-BEGIN: do not edit, managed by @skillfm/local -->";
23
+ export declare const SKILL_MD_END = "<!-- SKILLFM-SKILL-END -->";
24
+ export interface BuildSkillMdOptions {
25
+ lang?: SkillLang;
26
+ /** 是否包含 SKILLFM-BEGIN/END 边界(写到现有文件时建议 true)*/
27
+ withBoundaryMarkers?: boolean;
28
+ }
29
+ export declare function buildSkillMd(opts?: BuildSkillMdOptions): string;
30
+ //# sourceMappingURL=template.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../src/skill-md/template.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AA+CH,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,CAAC;AAwI7C,eAAO,MAAM,cAAc,yEAAyE,CAAC;AACrG,eAAO,MAAM,YAAY,+BAA+B,CAAC;AAMzD,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,+CAA+C;IAC/C,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED,wBAAgB,YAAY,CAAC,IAAI,GAAE,mBAAwB,GAAG,MAAM,CASnE"}
@@ -0,0 +1,194 @@
1
+ /**
2
+ * BSO M9 v0.3 — Layer 1: SKILL.md 模板(兼容 Anthropic Skills 格式)
3
+ *
4
+ * Refs:
5
+ * - docs/prd/PRD-BSO-M9-HARNESS-HOOKS.md §3.2
6
+ * - 主公决策 Q2=B': Layer 1 文件格式 100% 对齐 Anthropic Skills 标准;
7
+ * Layer 2/3 拦截协议保持 SkillFM 差异化。
8
+ *
9
+ * 文件格式:YAML frontmatter + Markdown body
10
+ * frontmatter 字段(Anthropic Skills 标准):
11
+ * - name: 唯一 slug
12
+ * - description: 何时触发本 skill 的描述(写给 LLM 看)
13
+ * - license: 默认 Apache-2.0
14
+ * - allowed-tools: skill 调用的 tool 白名单
15
+ * - metadata: 自定义字段(嵌套,不污染顶层)
16
+ *
17
+ * 写入位置(由 writer.ts 决定):
18
+ * - 项目级:./SKILL.md
19
+ * - Anthropic Claude Code 用户级(可选):~/.claude/skills/skillfm-bso/SKILL.md
20
+ */
21
+ import { readFileSync } from 'node:fs';
22
+ import { join } from 'node:path';
23
+ import { fileURLToPath } from 'node:url';
24
+ // ============================================================================
25
+ // 元信息(运行时读包 version,避免硬编码漂移)
26
+ // ============================================================================
27
+ function loadPackageVersion() {
28
+ const here = __dirnameSafe();
29
+ // 候选路径(覆盖 dist/skill-md/, src/skill-md/, 以及 npm install 安装路径)
30
+ const candidates = [
31
+ join(here, '..', '..', 'package.json'), // dist/skill-md/template.js → ../../package.json
32
+ join(here, '..', 'package.json'),
33
+ join(here, '..', '..', '..', 'package.json'),
34
+ ];
35
+ for (const p of candidates) {
36
+ try {
37
+ const raw = readFileSync(p, 'utf-8');
38
+ const pkg = JSON.parse(raw);
39
+ if (pkg?.name === '@skillfm/local' && typeof pkg.version === 'string') {
40
+ return pkg.version;
41
+ }
42
+ }
43
+ catch {
44
+ // continue
45
+ }
46
+ }
47
+ return 'unknown';
48
+ }
49
+ function __dirnameSafe() {
50
+ try {
51
+ if (typeof import.meta !== 'undefined' && import.meta.url) {
52
+ return fileURLToPath(new URL('.', import.meta.url));
53
+ }
54
+ }
55
+ catch {
56
+ // fall through
57
+ }
58
+ return process.cwd();
59
+ }
60
+ const DEFAULT_FRONTMATTER = () => ({
61
+ name: 'skillfm-bso-priming',
62
+ description: 'SkillFM BSO 协议 priming — 触发条件:当前 workspace 装了 @skillfm/local 且任务涉及破坏性操作(写文件 / 改代码 / 跑命令 / 调外部 API / 涉及支付)时自动加载',
63
+ license: 'Apache-2.0',
64
+ 'allowed-tools': [
65
+ 'mcp__skillfm__brain_run',
66
+ 'mcp__skillfm__list_skills',
67
+ 'mcp__skillfm__my_status',
68
+ 'mcp__skillfm__guard_status',
69
+ ],
70
+ metadata: {
71
+ skillfm_version: loadPackageVersion(),
72
+ bso_version: 'v1.1',
73
+ layer: 1,
74
+ homepage: 'https://skillfm.ai',
75
+ },
76
+ });
77
+ function renderFrontmatterYaml(fm) {
78
+ // 手写极简 YAML(避免引入 yaml 依赖;@skillfm/local zero-dep 原则)
79
+ const lines = [
80
+ '---',
81
+ `name: ${fm.name}`,
82
+ `description: ${quoteIfNeeded(fm.description)}`,
83
+ `license: ${fm.license}`,
84
+ 'allowed-tools:',
85
+ ...fm['allowed-tools'].map((t) => ` - ${t}`),
86
+ 'metadata:',
87
+ ` skillfm_version: "${fm.metadata.skillfm_version}"`,
88
+ ` bso_version: "${fm.metadata.bso_version}"`,
89
+ ` layer: ${fm.metadata.layer}`,
90
+ ` homepage: ${fm.metadata.homepage}`,
91
+ '---',
92
+ ];
93
+ return lines.join('\n');
94
+ }
95
+ function quoteIfNeeded(s) {
96
+ // 含特殊字符(含 ":"、换行、单/双引号、#)→ 加双引号 + escape
97
+ if (/[:"\n#]/.test(s) || /^[ \t]/.test(s)) {
98
+ return `"${s.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`;
99
+ }
100
+ return s;
101
+ }
102
+ // ============================================================================
103
+ // body 模板(zh / en)
104
+ // ============================================================================
105
+ const BODY_ZH = `# SkillFM BSO 协议 priming
106
+
107
+ ## 你必须知道
108
+
109
+ 本 workspace 启用了 SkillFM BSO(Behavioral Soul Override)协议。
110
+ 任何破坏性操作(写文件 / 改代码 / 跑命令 / 调外部 API / 涉及支付)开始前,
111
+ 必须先调用 \`mcp__skillfm__brain_run\`,拿到 ScriptCard 后按 \`must_do\` 顺序执行。
112
+
113
+ 未先 call brain_run 直接执行破坏性操作 → harness 层 hook 会 \`exit 2\` 阻断;
114
+ 若 hook 失效 → MCP 协议层会以 \`URLElicitationRequiredError\` 要求用户在
115
+ SkillFM 控制台审阅;若两者都被绕过 → sidecar 9 红线在协议契约层兜底拒绝。
116
+
117
+ ## 三层防御一览(仅供你理解,不必复述)
118
+
119
+ - L1 你的 priming(本文件) · 跟随率 70-95%
120
+ - L2 sidecar 协议 + MCP reject · 协议级强制
121
+ - L3 brain 仲裁 + harness hook · 机械级强制
122
+
123
+ ## 何时该 call brain_run
124
+
125
+ - 涉及业务流程编排(多步骤 + 风险评级)
126
+ - 用户首次发出某类请求(无历史 ScriptCard 缓存)
127
+ - 检测到 \`mode=strict\` / Tier ≥ B 的任务
128
+ - 用户要赚钱 / 出交付物 / 走对外发布场景
129
+
130
+ ## 边界
131
+
132
+ - 不要编造价格、收入、市场数据 — 引用 pipeline 返回的数字
133
+ - 用户要交付物且你能帮忙 → 走 \`brain_run\`,不要凭记忆手搓
134
+ - 移除:\`skillfm uninstall\` 或直接删本块(含 \`<!-- SKILLFM-BEGIN -->\` 边界)
135
+ `;
136
+ const BODY_EN = `# SkillFM BSO Protocol priming
137
+
138
+ ## You must know
139
+
140
+ This workspace has the SkillFM BSO (Behavioral Soul Override) protocol enabled.
141
+ Before ANY destructive operation (file write / code edit / shell command /
142
+ external API call / payment), you MUST first call \`mcp__skillfm__brain_run\`
143
+ and follow the returned ScriptCard's \`must_do\` order.
144
+
145
+ Skipping brain_run and going straight to destructive ops → the harness-layer
146
+ hook will \`exit 2\` to block you; if the hook is disabled → the MCP protocol
147
+ layer will return \`URLElicitationRequiredError\` forcing the user to review in
148
+ SkillFM console; if both are bypassed → the sidecar 9 redlines reject at the
149
+ contract layer.
150
+
151
+ ## Three-layer defense (for your understanding; do not narrate)
152
+
153
+ - L1 your priming (this file) · 70-95% follow rate
154
+ - L2 sidecar + MCP reject · protocol-level enforcement
155
+ - L3 brain arbitration + harness hook · mechanical enforcement
156
+
157
+ ## When to call brain_run
158
+
159
+ - Multi-step business orchestration with risk tiers
160
+ - First time the user makes this kind of request (no prior ScriptCard cache)
161
+ - Detected \`mode=strict\` or Tier ≥ B tasks
162
+ - User wants to earn money / produce deliverables / publish externally
163
+
164
+ ## Boundary
165
+
166
+ - Never fabricate pricing / earnings / market data — quote pipeline output
167
+ - If the user wants a deliverable you could help with → route through \`brain_run\`
168
+ - To remove: \`skillfm uninstall\` or delete this block (incl. SKILLFM-BEGIN markers)
169
+ `;
170
+ // ============================================================================
171
+ // 边界标记(与 priming.ts 一致,复用 uninstall 命令)
172
+ // ============================================================================
173
+ export const SKILL_MD_BEGIN = '<!-- SKILLFM-SKILL-BEGIN: do not edit, managed by @skillfm/local -->';
174
+ export const SKILL_MD_END = '<!-- SKILLFM-SKILL-END -->';
175
+ export function buildSkillMd(opts = {}) {
176
+ const lang = resolveLang(opts.lang);
177
+ const fm = renderFrontmatterYaml(DEFAULT_FRONTMATTER());
178
+ const body = lang === 'zh' ? BODY_ZH : BODY_EN;
179
+ const content = `${fm}\n\n${body}`;
180
+ if (opts.withBoundaryMarkers) {
181
+ return `${SKILL_MD_BEGIN}\n${content}${SKILL_MD_END}\n`;
182
+ }
183
+ return content;
184
+ }
185
+ function resolveLang(lang) {
186
+ if (lang === 'zh')
187
+ return 'zh';
188
+ if (lang === 'en')
189
+ return 'en';
190
+ // auto
191
+ const lc = (process.env.LANG || process.env.LC_ALL || process.env.LC_MESSAGES || '').toLowerCase();
192
+ return lc.includes('zh') ? 'zh' : 'en';
193
+ }
194
+ //# sourceMappingURL=template.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template.js","sourceRoot":"","sources":["../../src/skill-md/template.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * BSO M9 v0.3 — Layer 1: SKILL.md 写入器
3
+ *
4
+ * Refs:
5
+ * - docs/prd/PRD-BSO-M9-HARNESS-HOOKS.md §3.2.2
6
+ *
7
+ * 写入策略:
8
+ * - 项目级 ./SKILL.md:必写(所有 host 都拿到 priming)
9
+ * - Anthropic Claude Code 用户级 ~/.claude/skills/skillfm-bso/SKILL.md:可选
10
+ * (由 init flag --copy-to-user 触发,本里程碑只提供 hint)
11
+ *
12
+ * 已存在 ./SKILL.md:
13
+ * - 内含 SKILLFM-SKILL-BEGIN/END → upgrade-safe replace
14
+ * - 不含我们的标记 → backup 后 append(不覆盖用户已有 skill)
15
+ */
16
+ import { type SkillLang } from './template.js';
17
+ export interface SkillMdWriteResult {
18
+ path: string;
19
+ action: 'created' | 'appended' | 'replaced' | 'already-present';
20
+ bytesWritten: number;
21
+ backupPath?: string;
22
+ }
23
+ export interface WriteSkillMdOptions {
24
+ cwd: string;
25
+ lang?: SkillLang;
26
+ }
27
+ export declare function writeProjectSkillMd(opts: WriteSkillMdOptions): SkillMdWriteResult;
28
+ export declare function userScopeSkillMdPath(): string;
29
+ export declare function writeUserScopeSkillMd(lang?: SkillLang): SkillMdWriteResult;
30
+ //# sourceMappingURL=writer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"writer.d.ts","sourceRoot":"","sources":["../../src/skill-md/writer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAWH,OAAO,EAIL,KAAK,SAAS,EACf,MAAM,eAAe,CAAC;AAMvB,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,UAAU,GAAG,iBAAiB,CAAC;IAChE,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAMD,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,mBAAmB,GAAG,kBAAkB,CAqEjF;AAMD,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C;AAED,wBAAgB,qBAAqB,CAAC,IAAI,CAAC,EAAE,SAAS,GAAG,kBAAkB,CAqC1E"}
@@ -0,0 +1,129 @@
1
+ /**
2
+ * BSO M9 v0.3 — Layer 1: SKILL.md 写入器
3
+ *
4
+ * Refs:
5
+ * - docs/prd/PRD-BSO-M9-HARNESS-HOOKS.md §3.2.2
6
+ *
7
+ * 写入策略:
8
+ * - 项目级 ./SKILL.md:必写(所有 host 都拿到 priming)
9
+ * - Anthropic Claude Code 用户级 ~/.claude/skills/skillfm-bso/SKILL.md:可选
10
+ * (由 init flag --copy-to-user 触发,本里程碑只提供 hint)
11
+ *
12
+ * 已存在 ./SKILL.md:
13
+ * - 内含 SKILLFM-SKILL-BEGIN/END → upgrade-safe replace
14
+ * - 不含我们的标记 → backup 后 append(不覆盖用户已有 skill)
15
+ */
16
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, } from 'node:fs';
17
+ import { dirname, join } from 'node:path';
18
+ import { homedir } from 'node:os';
19
+ import { backupFileBeforeWrite } from '../soul-security.js';
20
+ import { buildSkillMd, SKILL_MD_BEGIN, SKILL_MD_END, } from './template.js';
21
+ export function writeProjectSkillMd(opts) {
22
+ const filePath = join(opts.cwd, 'SKILL.md');
23
+ const existed = existsSync(filePath);
24
+ const original = existed ? readFileSync(filePath, 'utf-8') : '';
25
+ const wrapped = buildSkillMd({ lang: opts.lang, withBoundaryMarkers: true });
26
+ // upgrade-safe 检查
27
+ const hasOurBlock = original.includes(SKILL_MD_BEGIN);
28
+ if (hasOurBlock && original.includes(wrapped.trimEnd())) {
29
+ return {
30
+ path: filePath,
31
+ action: 'already-present',
32
+ bytesWritten: 0,
33
+ };
34
+ }
35
+ // 文件不存在 → 直接写(无边界,因为整文件就是我们的)
36
+ if (!existed) {
37
+ mkdirSync(dirname(filePath), { recursive: true });
38
+ const standalone = buildSkillMd({ lang: opts.lang, withBoundaryMarkers: false });
39
+ writeFileSync(filePath, standalone, { encoding: 'utf-8', mode: 0o644 });
40
+ return {
41
+ path: filePath,
42
+ action: 'created',
43
+ bytesWritten: Buffer.byteLength(standalone, 'utf-8'),
44
+ };
45
+ }
46
+ // backup
47
+ let backupPath;
48
+ try {
49
+ const r = backupFileBeforeWrite(filePath, original);
50
+ backupPath = r.backup_path;
51
+ }
52
+ catch {
53
+ // not critical
54
+ }
55
+ let next;
56
+ let action;
57
+ if (hasOurBlock) {
58
+ // replace 旧 block
59
+ const startIdx = original.indexOf(SKILL_MD_BEGIN);
60
+ const endIdx = original.indexOf(SKILL_MD_END);
61
+ if (startIdx === -1 || endIdx === -1 || endIdx < startIdx) {
62
+ // 标记残缺 — 保守 append
63
+ next = `${original}${original.endsWith('\n') ? '' : '\n'}\n${wrapped}`;
64
+ action = 'appended';
65
+ }
66
+ else {
67
+ const before = original.slice(0, startIdx).replace(/\n+$/, '\n');
68
+ const after = original.slice(endIdx + SKILL_MD_END.length).replace(/^\n+/, '');
69
+ next = `${before}\n${wrapped}${after}`.replace(/\n{3,}/g, '\n\n');
70
+ action = 'replaced';
71
+ }
72
+ }
73
+ else {
74
+ // 用户已有 SKILL.md(自定义 skill)→ append 我们的 block 在尾部
75
+ next = `${original}${original.endsWith('\n') ? '' : '\n'}\n${wrapped}`;
76
+ action = 'appended';
77
+ }
78
+ writeFileSync(filePath, next, { encoding: 'utf-8', mode: 0o644 });
79
+ return {
80
+ path: filePath,
81
+ action,
82
+ bytesWritten: Buffer.byteLength(next, 'utf-8'),
83
+ backupPath,
84
+ };
85
+ }
86
+ // ============================================================================
87
+ // 用户级 hint(不实际写,只返回路径让 init 决定是否问用户)
88
+ // ============================================================================
89
+ export function userScopeSkillMdPath() {
90
+ return join(homedir(), '.claude', 'skills', 'skillfm-bso', 'SKILL.md');
91
+ }
92
+ export function writeUserScopeSkillMd(lang) {
93
+ const filePath = userScopeSkillMdPath();
94
+ const standalone = buildSkillMd({ lang, withBoundaryMarkers: false });
95
+ const existed = existsSync(filePath);
96
+ if (existed) {
97
+ const original = readFileSync(filePath, 'utf-8');
98
+ if (original.trim() === standalone.trim()) {
99
+ return {
100
+ path: filePath,
101
+ action: 'already-present',
102
+ bytesWritten: 0,
103
+ };
104
+ }
105
+ let backupPath;
106
+ try {
107
+ const r = backupFileBeforeWrite(filePath, original);
108
+ backupPath = r.backup_path;
109
+ }
110
+ catch {
111
+ // ignore
112
+ }
113
+ writeFileSync(filePath, standalone, { encoding: 'utf-8', mode: 0o644 });
114
+ return {
115
+ path: filePath,
116
+ action: 'replaced',
117
+ bytesWritten: Buffer.byteLength(standalone, 'utf-8'),
118
+ backupPath,
119
+ };
120
+ }
121
+ mkdirSync(dirname(filePath), { recursive: true });
122
+ writeFileSync(filePath, standalone, { encoding: 'utf-8', mode: 0o644 });
123
+ return {
124
+ path: filePath,
125
+ action: 'created',
126
+ bytesWritten: Buffer.byteLength(standalone, 'utf-8'),
127
+ };
128
+ }
129
+ //# sourceMappingURL=writer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"writer.js","sourceRoot":"","sources":["../../src/skill-md/writer.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skillfm/local",
3
- "version": "2.0.4",
3
+ "version": "2.0.6",
4
4
  "description": "SkillFM local sidecar — a tiny localhost HTTP proxy that lets any AI agent activate and run SkillFM skills in the current conversation without restarting its MCP runtime. Writes ~/.skillfm/local.json for service discovery.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -27,7 +27,8 @@
27
27
  "dev": "tsx src/index.ts",
28
28
  "typecheck": "tsc --noEmit",
29
29
  "start": "node dist/index.js start",
30
- "test": "tsx --test src/harness/detector.test.ts src/harness/priming.test.ts src/harness/writers.test.ts src/guard/state.test.ts src/soul.test.ts",
30
+ "test": "tsx --test src/harness/detector.test.ts src/harness/priming.test.ts src/harness/writers.test.ts src/guard/state.test.ts src/soul.test.ts src/harness/kernels/registry.test.ts src/mcp-output/builder.test.ts src/mcp-output/deny-review.test.ts src/mcp-output/integration.test.ts src/skill-md/template.test.ts src/skill-md/writer.test.ts",
31
+ "test:acceptance": "npm run build && bash scripts/acceptance-matrix.sh",
31
32
  "postpublish": "curl -sS -m 10 -X PUT 'https://registry.npmmirror.com/-/package/@skillfm/local/syncs?sync_upstream=true' > /dev/null && echo '✓ npmmirror sync triggered' || echo '⚠ npmmirror sync failed (非阻塞,可手动触发)'"
32
33
  },
33
34
  "dependencies": {},
package/dist/lang.d.ts DELETED
@@ -1,21 +0,0 @@
1
- /**
2
- * 用户语言检测 — sidecar 在输出 hint_for_agent 前决定语言
3
- *
4
- * 目标: agent 读到 sidecar 返回的指令时, 按用户本机环境的语言回应.
5
- * 当前仅识别 zh / en 两档, 后续可扩展 ja / ko / es 等.
6
- *
7
- * 检测顺序 (首个命中即返回):
8
- * 1. 环境变量 SKILLFM_LANG=zh|en — 用户/企业显式覆盖
9
- * 2. env.LANGUAGE — Linux/ glibc 优先 (逗号分隔, 取第一个)
10
- * 3. env.LC_ALL / LC_MESSAGES / LANG — POSIX locale
11
- * 4. Intl.DateTimeFormat().resolvedOptions().locale — macOS/Windows 可靠回落
12
- * 5. 默认 'en'
13
- *
14
- * 任何字符串若开头(或整串 lowercase)含 "zh" → 返回 'zh'; 否则 'en'.
15
- */
16
- export type Lang = 'zh' | 'en';
17
- /**
18
- * 检测当前用户语言. 纯函数, 给 env 和 intlLocale 方便测试.
19
- */
20
- export declare function detectLang(env?: NodeJS.ProcessEnv, intlLocale?: () => string): Lang;
21
- //# sourceMappingURL=lang.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"lang.d.ts","sourceRoot":"","sources":["../src/lang.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,MAAM,MAAM,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAS/B;;GAEG;AACH,wBAAgB,UAAU,CACxB,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,UAAU,GAAE,MAAM,MAMjB,GACA,IAAI,CA2BN"}
package/dist/lang.js DELETED
@@ -1,62 +0,0 @@
1
- /**
2
- * 用户语言检测 — sidecar 在输出 hint_for_agent 前决定语言
3
- *
4
- * 目标: agent 读到 sidecar 返回的指令时, 按用户本机环境的语言回应.
5
- * 当前仅识别 zh / en 两档, 后续可扩展 ja / ko / es 等.
6
- *
7
- * 检测顺序 (首个命中即返回):
8
- * 1. 环境变量 SKILLFM_LANG=zh|en — 用户/企业显式覆盖
9
- * 2. env.LANGUAGE — Linux/ glibc 优先 (逗号分隔, 取第一个)
10
- * 3. env.LC_ALL / LC_MESSAGES / LANG — POSIX locale
11
- * 4. Intl.DateTimeFormat().resolvedOptions().locale — macOS/Windows 可靠回落
12
- * 5. 默认 'en'
13
- *
14
- * 任何字符串若开头(或整串 lowercase)含 "zh" → 返回 'zh'; 否则 'en'.
15
- */
16
- const ZH_PATTERN = /(^|[_-])zh([_-]|$)|^zh/;
17
- function matchZh(raw) {
18
- if (!raw)
19
- return false;
20
- return ZH_PATTERN.test(raw.toLowerCase());
21
- }
22
- /**
23
- * 检测当前用户语言. 纯函数, 给 env 和 intlLocale 方便测试.
24
- */
25
- export function detectLang(env = process.env, intlLocale = () => {
26
- try {
27
- return Intl.DateTimeFormat().resolvedOptions().locale;
28
- }
29
- catch {
30
- return '';
31
- }
32
- }) {
33
- // 1. 显式覆盖
34
- const explicit = (env.SKILLFM_LANG || '').trim().toLowerCase();
35
- if (explicit === 'zh' || explicit === 'en')
36
- return explicit;
37
- if (explicit && matchZh(explicit))
38
- return 'zh';
39
- // 2. LANGUAGE (glibc list, first wins)
40
- const languageFirst = (env.LANGUAGE || '').split(':')[0];
41
- if (languageFirst) {
42
- if (matchZh(languageFirst))
43
- return 'zh';
44
- // 非 zh 的显式值不要立刻返回 en, 让后面 locale 有机会补判
45
- }
46
- // 3. POSIX locale 链
47
- const posix = env.LC_ALL || env.LC_MESSAGES || env.LANG || '';
48
- if (posix && matchZh(posix))
49
- return 'zh';
50
- // 4. Intl (macOS / Windows 兜底)
51
- try {
52
- const intl = intlLocale();
53
- if (matchZh(intl))
54
- return 'zh';
55
- }
56
- catch {
57
- /* ignore */
58
- }
59
- // 5. 默认英文
60
- return 'en';
61
- }
62
- //# sourceMappingURL=lang.js.map
package/dist/lang.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"lang.js","sourceRoot":"","sources":["../src/lang.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,MAAM,UAAU,GAAG,wBAAwB,CAAC;AAE5C,SAAS,OAAO,CAAC,GAA8B;IAC7C,IAAI,CAAC,GAAG;QAAE,OAAO,KAAK,CAAC;IACvB,OAAO,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC;AAC5C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CACxB,MAAyB,OAAO,CAAC,GAAG,EACpC,aAA2B,GAAG,EAAE;IAC9B,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,cAAc,EAAE,CAAC,eAAe,EAAE,CAAC,MAAM,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;IAED,UAAU;IACV,MAAM,QAAQ,GAAG,CAAC,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC/D,IAAI,QAAQ,KAAK,IAAI,IAAI,QAAQ,KAAK,IAAI;QAAE,OAAO,QAAgB,CAAC;IACpE,IAAI,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAC;IAE/C,uCAAuC;IACvC,MAAM,aAAa,GAAG,CAAC,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACzD,IAAI,aAAa,EAAE,CAAC;QAClB,IAAI,OAAO,CAAC,aAAa,CAAC;YAAE,OAAO,IAAI,CAAC;QACxC,uCAAuC;IACzC,CAAC;IAED,oBAAoB;IACpB,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;IAC9D,IAAI,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEzC,+BAA+B;IAC/B,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,UAAU,EAAE,CAAC;QAC1B,IAAI,OAAO,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,YAAY;IACd,CAAC;IAED,UAAU;IACV,OAAO,IAAI,CAAC;AACd,CAAC"}