@bossmissing/agent-meta 0.1.0 → 0.2.0

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 (35) hide show
  1. package/README.md +46 -2
  2. package/assets/skills/ironbank/ironbank-citations/SKILL.md +195 -0
  3. package/assets/skills/ironbank/ironbank-docs-research/SKILL.md +205 -0
  4. package/assets/skills/ironbank/ironbank-mcp-reference/SKILL.md +413 -0
  5. package/dist/cli.js +72 -1
  6. package/dist/commands/config.d.ts +5 -0
  7. package/dist/commands/config.js +50 -0
  8. package/dist/commands/doctor.d.ts +14 -0
  9. package/dist/commands/doctor.js +187 -0
  10. package/dist/commands/init.d.ts +2 -0
  11. package/dist/commands/init.js +39 -1
  12. package/dist/commands/new-change.d.ts +12 -0
  13. package/dist/commands/new-change.js +125 -0
  14. package/dist/commands/new-domain.js +2 -0
  15. package/dist/commands/preflight.d.ts +14 -0
  16. package/dist/commands/preflight.js +103 -0
  17. package/dist/commands/review.d.ts +18 -0
  18. package/dist/commands/review.js +102 -0
  19. package/dist/core/checklist.d.ts +31 -0
  20. package/dist/core/checklist.js +43 -0
  21. package/dist/core/doc-scopes.d.ts +18 -0
  22. package/dist/core/doc-scopes.js +55 -0
  23. package/dist/core/frontmatter.d.ts +7 -0
  24. package/dist/core/frontmatter.js +35 -0
  25. package/dist/core/mcp-packs.d.ts +26 -0
  26. package/dist/core/mcp-packs.js +83 -0
  27. package/dist/generators/hook-generator.d.ts +14 -0
  28. package/dist/generators/hook-generator.js +55 -0
  29. package/dist/generators/mcp-generator.d.ts +9 -0
  30. package/dist/generators/mcp-generator.js +68 -0
  31. package/dist/templates/index.d.ts +7 -2
  32. package/dist/templates/index.js +125 -9
  33. package/dist/validators/domain-validator.js +30 -1
  34. package/dist/validators/openspec-validator.js +33 -4
  35. package/package.json +9 -15
@@ -25,19 +25,25 @@ const AGENTS_MD = `# AGENTS.md
25
25
 
26
26
  - Read the nearest applicable \`AGENTS.md\` before modifying files.
27
27
  - Read related domain documentation before changing business behavior.
28
+ - Do not modify third-party or vendored code (\`node_modules/\`, \`vendor/\`, \`third_party/\`, \`patches/\`). Wrap or extend it instead; if patching is unavoidable, record an ADR first.
29
+ - Do not use user-level (global) skills, plugins, or MCP tools unless the human explicitly asks for them. Prefer tools, scripts, and skills defined inside this repository.
30
+ - Never violate declared hard constraints (\`docs/domain/*/rules.md\` 硬限制 sections and \`docs/engineering/constraints.md\`). If a limit is not declared, ask the human instead of assuming it is negotiable.
31
+ - If you are guessing, fabricating, or cannot verify a conclusion, stop and ask the human.
28
32
  - Do not duplicate domain rules in this file.
29
33
  - Update OpenSpec specs when externally observable behavior changes.
30
34
  - Add or update tests for behavior changes.
31
35
  - Do not mix unrelated refactors into a feature change.
32
-
36
+ {{extra_rules}}
33
37
  ## High-Risk Areas
34
38
 
35
- Before changing payment, order, commission, settlement, withdrawal, permissions, webhooks, inventory, or audit logging, read the applicable documentation under \`docs/domain/\`.
39
+ Before changing payment, order, commission, settlement, withdrawal, permissions, webhooks, inventory, or audit logging, read the applicable documentation under \`docs/domain/\`. Hard constraints for these areas are declared in each domain's \`rules.md\` under 硬限制(不可违反).
36
40
 
37
41
  ## Definition of Done
38
42
 
39
43
  - Relevant tests pass.
40
44
  - Type checking and lint pass where configured.
45
+ - A human has reviewed the change.
46
+ - All declared hard constraints hold.
41
47
  - Behavior changes include documentation or specification updates where applicable.
42
48
  - High-risk changes include rollback and failure-path consideration.
43
49
  `;
@@ -98,14 +104,21 @@ applies_to: []
98
104
 
99
105
  <!-- 仅列出该领域特有术语;通用术语应放到 docs/domain/glossary.md。 -->
100
106
 
101
- ## 不变量
107
+ ## 硬限制(不可违反)
102
108
 
103
- <!-- 无论何时都必须成立的规则。 -->
109
+ <!-- 安全、数据一致性、API 契约、性能预算、兼容性、合规。 -->
110
+ <!-- 没写在这里的限制,AI 会当成可协商的。 -->
104
111
 
105
112
  -
106
113
  -
107
114
  -
108
115
 
116
+ ## 软限制(可权衡)
117
+
118
+ <!-- 代码风格偏好、非关键路径的实现细节、可后续优化的部分。 -->
119
+
120
+ -
121
+
109
122
  ## 权限规则
110
123
 
111
124
  | 角色 | 可执行操作 | 限制 |
@@ -119,11 +132,6 @@ applies_to: []
119
132
  ## 审计与追踪
120
133
 
121
134
  <!-- 是否需要审计日志、操作人、时间、状态变更原因等。 -->
122
-
123
- ## 禁止行为
124
-
125
- -
126
- -
127
135
  `;
128
136
  const DOMAIN_STATE_MACHINE = `---
129
137
  title: {{domain_title}}状态机
@@ -413,6 +421,109 @@ applies_to: []
413
421
 
414
422
  ## 工具与命令
415
423
  `;
424
+ const CHANGE_PROPOSAL = `# {{change_title}}
425
+
426
+ ## Why
427
+
428
+ <!-- 为什么要做这个变更?解决什么问题? -->
429
+
430
+ ## What Changes
431
+
432
+ <!-- 变更内容概述:新增/修改/移除哪些能力。 -->
433
+
434
+ ## Impact
435
+
436
+ - Affected domains: {{domain}}
437
+ - Affected specs:
438
+ - Affected code:
439
+ `;
440
+ const CHANGE_DESIGN = `# {{change_title}} — Design
441
+
442
+ ## Context
443
+
444
+ <!-- 现状与约束。 -->
445
+
446
+ ## Goals / Non-Goals
447
+
448
+ - Goals:
449
+ - Non-Goals:
450
+
451
+ ## Decisions
452
+
453
+ <!-- 关键技术决策;长期决策请沉淀为 ADR(meta new-adr)。 -->
454
+
455
+ ## Hard Constraints(硬限制核对)
456
+
457
+ <!-- 列出本变更涉及的已声明硬限制与核对结论。 -->
458
+ <!-- 来源:docs/domain/<domain>/rules.md 硬限制章节、docs/engineering/constraints.md。 -->
459
+
460
+ | 硬限制 | 来源 | 核对结论 |
461
+ |---|---|---|
462
+ | | | |
463
+
464
+ ## Risks / Trade-offs
465
+
466
+ <!-- 风险与权衡。 -->
467
+ `;
468
+ const CHANGE_TASKS = `# {{change_title}} — Tasks
469
+
470
+ ## 1. Implementation
471
+
472
+ - [ ] 1.1
473
+ - [ ] 1.2
474
+
475
+ ## 2. Validation
476
+
477
+ - [ ] 2.1 Tests updated
478
+ - [ ] 2.2 \`meta check\` passes
479
+ `;
480
+ const CHANGE_RISK_REVIEW = `# {{change_title}} — Risk Review
481
+
482
+ - Related domain: {{domain}}
483
+ - Date: {{date}}
484
+
485
+ ## Checklist
486
+
487
+ - [ ] Money representation(金额表示与精度)
488
+ - [ ] Idempotency(幂等)
489
+ - [ ] Retry behavior(重试行为)
490
+ - [ ] Callback deduplication(回调去重)
491
+ - [ ] Audit logging(审计日志)
492
+ - [ ] Permission boundaries(权限边界)
493
+ - [ ] Rollback plan(回滚方案)
494
+ - [ ] Declared hard constraints checked(已声明的硬限制全部核对)
495
+
496
+ ## Notes
497
+
498
+ <!-- 每项勾选前写清结论或“不适用”的原因。 -->
499
+ `;
500
+ const ENGINEERING_CONSTRAINTS = `---
501
+ title: 项目级硬限制
502
+ status: draft
503
+ owner: {{owner}}
504
+ last_reviewed: {{date}}
505
+ source_of_truth: true
506
+ applies_to: []
507
+ ---
508
+
509
+ # 项目级硬限制
510
+
511
+ <!-- 跨领域的硬限制放这里;单个领域的硬限制放 docs/domain/<domain>/rules.md。 -->
512
+
513
+ ## 硬限制(不可违反)
514
+
515
+ <!-- 类别参考:安全、数据一致性、API 契约、性能预算、兼容性、合规。 -->
516
+ <!-- 没写在这里的限制,AI 会当成可协商的。 -->
517
+
518
+ -
519
+ -
520
+
521
+ ## 软限制(可权衡)
522
+
523
+ <!-- 代码风格偏好、非关键路径的实现细节、可后续优化的部分。 -->
524
+
525
+ -
526
+ `;
416
527
  const RUNBOOKS_README = `---
417
528
  title: Runbooks
418
529
  status: draft
@@ -441,5 +552,10 @@ export const BUILTIN_TEMPLATES = {
441
552
  "system-overview.md": SYSTEM_OVERVIEW,
442
553
  "api-conventions.md": API_CONVENTIONS,
443
554
  "engineering-testing.md": ENGINEERING_TESTING,
555
+ "engineering-constraints.md": ENGINEERING_CONSTRAINTS,
444
556
  "runbooks-readme.md": RUNBOOKS_README,
557
+ "change-proposal.md": CHANGE_PROPOSAL,
558
+ "change-design.md": CHANGE_DESIGN,
559
+ "change-tasks.md": CHANGE_TASKS,
560
+ "change-risk-review.md": CHANGE_RISK_REVIEW,
445
561
  };
@@ -1,6 +1,6 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
- import { parseDocFile, hasSection } from "../core/frontmatter.js";
3
+ import { parseDocFile, hasSection, sectionHasContent, HARD_CONSTRAINT_HEADINGS, } from "../core/frontmatter.js";
4
4
  import { matchRiskKeywords } from "../core/risk.js";
5
5
  export function listDomainDirs(root, domainDocs) {
6
6
  const abs = path.join(root, domainDocs);
@@ -99,6 +99,20 @@ export function validateDomains(ctx) {
99
99
  }
100
100
  }
101
101
  if (riskHits.length > 0) {
102
+ // Hard constraints must be declared; undeclared limits get treated as
103
+ // negotiable by AI agents.
104
+ if (fs.existsSync(rulesAbs)) {
105
+ const rules = parseDocFile(rulesAbs);
106
+ if (!sectionHasContent(rules.content, HARD_CONSTRAINT_HEADINGS)) {
107
+ issues.push({
108
+ code: "HIGH_RISK_DOMAIN_MISSING_HARD_CONSTRAINTS",
109
+ severity: "warning",
110
+ file: path.join(relDir, "rules.md"),
111
+ message: `High-risk domain '${domain}' declares no hard constraints`,
112
+ suggestion: 'Fill the "## 硬限制(不可违反)" section in rules.md (security, data consistency, API contracts, performance budgets, compatibility, compliance).',
113
+ });
114
+ }
115
+ }
102
116
  if (!fs.existsSync(rulesAbs)) {
103
117
  issues.push({
104
118
  code: "HIGH_RISK_DOMAIN_MISSING_RULES",
@@ -126,6 +140,21 @@ export function validateDomains(ctx) {
126
140
  suggestion: `Run \`meta new-domain ${domain} --force --with-state-machine\`.`,
127
141
  });
128
142
  }
143
+ // High-risk domains should link the ADRs backing their key decisions.
144
+ const docs = [readmeAbs, rulesAbs].filter((abs) => fs.existsSync(abs));
145
+ const referencesAdr = docs.some((abs) => {
146
+ const body = fs.readFileSync(abs, "utf8").replace(/<!--[\s\S]*?-->/g, "");
147
+ return /adr\//i.test(body) || /ADR-\d/.test(body);
148
+ });
149
+ if (docs.length > 0 && !referencesAdr) {
150
+ issues.push({
151
+ code: "DOMAIN_NO_ADR_REFERENCE",
152
+ severity: "warning",
153
+ file: relDir,
154
+ message: `High-risk domain '${domain}' does not reference any ADR`,
155
+ suggestion: `Record key decisions with \`meta new-adr ${domain}-idempotency\` and link them from the domain README.`,
156
+ });
157
+ }
129
158
  }
130
159
  }
131
160
  return { issues, checkedFiles };
@@ -1,5 +1,7 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
+ import { matchRiskKeywords } from "../core/risk.js";
4
+ import { listDomainDirs } from "./domain-validator.js";
3
5
  export function validateOpenSpec(ctx) {
4
6
  const issues = [];
5
7
  const { root, config } = ctx;
@@ -53,24 +55,51 @@ export function validateOpenSpec(ctx) {
53
55
  });
54
56
  }
55
57
  }
56
- // Each change directory should contain at least a proposal or tasks file.
58
+ // Each change directory must contain the core change files.
57
59
  const changesAbs = path.join(openspecAbs, "changes");
58
60
  if (fs.existsSync(changesAbs)) {
59
61
  for (const entry of fs.readdirSync(changesAbs, { withFileTypes: true })) {
60
62
  if (!entry.isDirectory())
61
63
  continue;
64
+ // OpenSpec keeps completed changes under changes/archive/.
65
+ if (entry.name === "archive")
66
+ continue;
62
67
  checkedFiles++;
63
68
  const changeDir = path.join(changesAbs, entry.name);
64
- const hasCore = ["proposal.md", "tasks.md", "design.md"].some((f) => fs.existsSync(path.join(changeDir, f)));
65
- if (!hasCore) {
69
+ const missing = ["proposal.md", "tasks.md"].filter((f) => !fs.existsSync(path.join(changeDir, f)));
70
+ if (missing.length > 0) {
66
71
  issues.push({
67
72
  code: "OPENSPEC_CHANGE_INCOMPLETE",
68
73
  severity: "warning",
69
74
  file: path.join(openspecRel, "changes", entry.name),
70
- message: "Change directory has none of proposal.md / design.md / tasks.md",
75
+ message: `Change directory is missing: ${missing.join(", ")}`,
76
+ suggestion: `Run \`meta new-change ${entry.name}\` to create the missing files.`,
71
77
  });
72
78
  }
73
79
  }
74
80
  }
81
+ // High-risk domain docs should reference OpenSpec specs or changes.
82
+ for (const domain of listDomainDirs(root, config.paths.domain_docs)) {
83
+ const riskHits = matchRiskKeywords(domain, config.risk_keywords);
84
+ if (riskHits.length === 0)
85
+ continue;
86
+ const domainRel = path.join(config.paths.domain_docs, domain);
87
+ const docs = ["README.md", "rules.md"]
88
+ .map((f) => path.join(root, domainRel, f))
89
+ .filter((abs) => fs.existsSync(abs));
90
+ if (docs.length === 0)
91
+ continue;
92
+ checkedFiles += docs.length;
93
+ const referencesOpenspec = docs.some((abs) => /openspec/i.test(fs.readFileSync(abs, "utf8").replace(/<!--[\s\S]*?-->/g, "")));
94
+ if (!referencesOpenspec) {
95
+ issues.push({
96
+ code: "HIGH_RISK_DOMAIN_NO_OPENSPEC_REFERENCE",
97
+ severity: "warning",
98
+ file: domainRel,
99
+ message: `High-risk domain '${domain}' does not reference any OpenSpec specs or changes`,
100
+ suggestion: `Link the relevant openspec/specs/ or openspec/changes/ entries from ${domainRel}/README.md.`,
101
+ });
102
+ }
103
+ }
75
104
  return { issues, checkedFiles };
76
105
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bossmissing/agent-meta",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Agent Meta CLI - manage AI agent collaboration metadata (AGENTS.md, domain docs, ADRs, frontmatter checks)",
5
5
  "keywords": [
6
6
  "cli",
@@ -22,6 +22,7 @@
22
22
  "types": "./dist/index.d.ts",
23
23
  "files": [
24
24
  "dist",
25
+ "assets",
25
26
  "README.md",
26
27
  "LICENSE"
27
28
  ],
@@ -32,14 +33,6 @@
32
33
  "engines": {
33
34
  "node": ">=20"
34
35
  },
35
- "scripts": {
36
- "build": "tsc -p tsconfig.build.json",
37
- "dev": "tsx src/cli.ts",
38
- "test": "vitest run",
39
- "test:watch": "vitest",
40
- "typecheck": "tsc --noEmit",
41
- "prepublishOnly": "pnpm build"
42
- },
43
36
  "dependencies": {
44
37
  "@inquirer/prompts": "^7.0.0",
45
38
  "commander": "^12.1.0",
@@ -55,10 +48,11 @@
55
48
  "typescript": "^5.5.0",
56
49
  "vitest": "^2.1.0"
57
50
  },
58
- "packageManager": "pnpm@10.0.0",
59
- "pnpm": {
60
- "onlyBuiltDependencies": [
61
- "esbuild"
62
- ]
51
+ "scripts": {
52
+ "build": "tsc -p tsconfig.build.json",
53
+ "dev": "tsx src/cli.ts",
54
+ "test": "vitest run",
55
+ "test:watch": "vitest",
56
+ "typecheck": "tsc --noEmit"
63
57
  }
64
- }
58
+ }