mindforge-cc 1.0.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 (324) hide show
  1. package/.agent/CLAUDE.md +462 -0
  2. package/.agent/forge/help.md +7 -0
  3. package/.agent/forge/init-project.md +32 -0
  4. package/.agent/forge/plan-phase.md +30 -0
  5. package/.agent/mindforge/approve.md +18 -0
  6. package/.agent/mindforge/audit.md +30 -0
  7. package/.agent/mindforge/benchmark.md +33 -0
  8. package/.agent/mindforge/complete-milestone.md +18 -0
  9. package/.agent/mindforge/debug.md +126 -0
  10. package/.agent/mindforge/discuss-phase.md +138 -0
  11. package/.agent/mindforge/execute-phase.md +165 -0
  12. package/.agent/mindforge/health.md +21 -0
  13. package/.agent/mindforge/help.md +23 -0
  14. package/.agent/mindforge/init-org.md +131 -0
  15. package/.agent/mindforge/init-project.md +155 -0
  16. package/.agent/mindforge/install-skill.md +15 -0
  17. package/.agent/mindforge/map-codebase.md +298 -0
  18. package/.agent/mindforge/metrics.md +22 -0
  19. package/.agent/mindforge/migrate.md +40 -0
  20. package/.agent/mindforge/milestone.md +12 -0
  21. package/.agent/mindforge/next.md +105 -0
  22. package/.agent/mindforge/plan-phase.md +125 -0
  23. package/.agent/mindforge/plugins.md +40 -0
  24. package/.agent/mindforge/pr-review.md +41 -0
  25. package/.agent/mindforge/profile-team.md +23 -0
  26. package/.agent/mindforge/publish-skill.md +19 -0
  27. package/.agent/mindforge/quick.md +135 -0
  28. package/.agent/mindforge/release.md +10 -0
  29. package/.agent/mindforge/retrospective.md +26 -0
  30. package/.agent/mindforge/review.md +157 -0
  31. package/.agent/mindforge/security-scan.md +233 -0
  32. package/.agent/mindforge/ship.md +100 -0
  33. package/.agent/mindforge/skills.md +141 -0
  34. package/.agent/mindforge/status.md +104 -0
  35. package/.agent/mindforge/sync-confluence.md +11 -0
  36. package/.agent/mindforge/sync-jira.md +12 -0
  37. package/.agent/mindforge/tokens.md +8 -0
  38. package/.agent/mindforge/update.md +42 -0
  39. package/.agent/mindforge/verify-phase.md +62 -0
  40. package/.agent/mindforge/workspace.md +29 -0
  41. package/.claude/CLAUDE.md +462 -0
  42. package/.claude/commands/forge/help.md +7 -0
  43. package/.claude/commands/forge/init-project.md +32 -0
  44. package/.claude/commands/forge/plan-phase.md +30 -0
  45. package/.claude/commands/mindforge/approve.md +18 -0
  46. package/.claude/commands/mindforge/audit.md +30 -0
  47. package/.claude/commands/mindforge/benchmark.md +33 -0
  48. package/.claude/commands/mindforge/complete-milestone.md +18 -0
  49. package/.claude/commands/mindforge/debug.md +126 -0
  50. package/.claude/commands/mindforge/discuss-phase.md +138 -0
  51. package/.claude/commands/mindforge/execute-phase.md +165 -0
  52. package/.claude/commands/mindforge/health.md +21 -0
  53. package/.claude/commands/mindforge/help.md +23 -0
  54. package/.claude/commands/mindforge/init-org.md +131 -0
  55. package/.claude/commands/mindforge/init-project.md +155 -0
  56. package/.claude/commands/mindforge/install-skill.md +15 -0
  57. package/.claude/commands/mindforge/map-codebase.md +298 -0
  58. package/.claude/commands/mindforge/metrics.md +22 -0
  59. package/.claude/commands/mindforge/migrate.md +40 -0
  60. package/.claude/commands/mindforge/milestone.md +12 -0
  61. package/.claude/commands/mindforge/next.md +105 -0
  62. package/.claude/commands/mindforge/plan-phase.md +125 -0
  63. package/.claude/commands/mindforge/plugins.md +40 -0
  64. package/.claude/commands/mindforge/pr-review.md +41 -0
  65. package/.claude/commands/mindforge/profile-team.md +23 -0
  66. package/.claude/commands/mindforge/publish-skill.md +19 -0
  67. package/.claude/commands/mindforge/quick.md +135 -0
  68. package/.claude/commands/mindforge/release.md +10 -0
  69. package/.claude/commands/mindforge/retrospective.md +26 -0
  70. package/.claude/commands/mindforge/review.md +157 -0
  71. package/.claude/commands/mindforge/security-scan.md +233 -0
  72. package/.claude/commands/mindforge/ship.md +100 -0
  73. package/.claude/commands/mindforge/skills.md +141 -0
  74. package/.claude/commands/mindforge/status.md +104 -0
  75. package/.claude/commands/mindforge/sync-confluence.md +11 -0
  76. package/.claude/commands/mindforge/sync-jira.md +12 -0
  77. package/.claude/commands/mindforge/tokens.md +8 -0
  78. package/.claude/commands/mindforge/update.md +42 -0
  79. package/.claude/commands/mindforge/verify-phase.md +62 -0
  80. package/.claude/commands/mindforge/workspace.md +29 -0
  81. package/.forge/org/CONVENTIONS.md +0 -0
  82. package/.forge/org/ORG.md +0 -0
  83. package/.forge/org/SECURITY.md +0 -0
  84. package/.forge/org/TOOLS.md +0 -0
  85. package/.forge/personas/analyst.md +0 -0
  86. package/.forge/personas/architect.md +0 -0
  87. package/.forge/personas/debug-specialist.md +0 -0
  88. package/.forge/personas/developer.md +26 -0
  89. package/.forge/personas/qa-engineer.md +0 -0
  90. package/.forge/personas/release-manager.md +0 -0
  91. package/.forge/personas/security-reviewer.md +33 -0
  92. package/.forge/personas/tech-writer.md +0 -0
  93. package/.forge/skills/api-design/SKILL.md +0 -0
  94. package/.forge/skills/code-quality/SKILL.md +0 -0
  95. package/.forge/skills/documentation/SKILL.md +0 -0
  96. package/.forge/skills/security-review/SKILL.md +23 -0
  97. package/.forge/skills/testing-standards/SKILL.md +27 -0
  98. package/.github/workflows/mindforge-ci.yml +224 -0
  99. package/.gitlab-ci-mindforge.yml +18 -0
  100. package/.mindforge/MINDFORGE-SCHEMA.json +165 -0
  101. package/.mindforge/audit/AUDIT-SCHEMA.md +451 -0
  102. package/.mindforge/ci/ci-config-schema.md +21 -0
  103. package/.mindforge/ci/ci-mode.md +179 -0
  104. package/.mindforge/ci/github-actions-adapter.md +224 -0
  105. package/.mindforge/ci/gitlab-ci-adapter.md +31 -0
  106. package/.mindforge/ci/jenkins-adapter.md +44 -0
  107. package/.mindforge/distribution/registry-client.md +166 -0
  108. package/.mindforge/distribution/registry-schema.md +96 -0
  109. package/.mindforge/distribution/skill-publisher.md +44 -0
  110. package/.mindforge/distribution/skill-validator.md +74 -0
  111. package/.mindforge/engine/compaction-protocol.md +182 -0
  112. package/.mindforge/engine/context-injector.md +128 -0
  113. package/.mindforge/engine/dependency-parser.md +113 -0
  114. package/.mindforge/engine/skills/conflict-resolver.md +69 -0
  115. package/.mindforge/engine/skills/loader.md +184 -0
  116. package/.mindforge/engine/skills/registry.md +98 -0
  117. package/.mindforge/engine/skills/versioning.md +75 -0
  118. package/.mindforge/engine/verification-pipeline.md +111 -0
  119. package/.mindforge/engine/wave-executor.md +235 -0
  120. package/.mindforge/governance/GOVERNANCE-CONFIG.md +17 -0
  121. package/.mindforge/governance/approval-workflow.md +37 -0
  122. package/.mindforge/governance/change-classifier.md +63 -0
  123. package/.mindforge/governance/compliance-gates.md +31 -0
  124. package/.mindforge/integrations/confluence.md +27 -0
  125. package/.mindforge/integrations/connection-manager.md +163 -0
  126. package/.mindforge/integrations/github.md +25 -0
  127. package/.mindforge/integrations/gitlab.md +13 -0
  128. package/.mindforge/integrations/jira.md +102 -0
  129. package/.mindforge/integrations/slack.md +41 -0
  130. package/.mindforge/intelligence/antipattern-detector.md +75 -0
  131. package/.mindforge/intelligence/difficulty-scorer.md +55 -0
  132. package/.mindforge/intelligence/health-engine.md +208 -0
  133. package/.mindforge/intelligence/skill-gap-analyser.md +40 -0
  134. package/.mindforge/intelligence/smart-compaction.md +71 -0
  135. package/.mindforge/metrics/METRICS-SCHEMA.md +42 -0
  136. package/.mindforge/metrics/quality-tracker.md +32 -0
  137. package/.mindforge/monorepo/cross-package-planner.md +114 -0
  138. package/.mindforge/monorepo/dependency-graph-builder.md +32 -0
  139. package/.mindforge/monorepo/workspace-detector.md +129 -0
  140. package/.mindforge/org/CONVENTIONS.md +62 -0
  141. package/.mindforge/org/ORG.md +51 -0
  142. package/.mindforge/org/SECURITY.md +50 -0
  143. package/.mindforge/org/TOOLS.md +53 -0
  144. package/.mindforge/org/integrations/INTEGRATIONS-CONFIG.md +58 -0
  145. package/.mindforge/org/skills/MANIFEST.md +38 -0
  146. package/.mindforge/personas/analyst.md +52 -0
  147. package/.mindforge/personas/architect.md +75 -0
  148. package/.mindforge/personas/debug-specialist.md +52 -0
  149. package/.mindforge/personas/developer.md +85 -0
  150. package/.mindforge/personas/overrides/README.md +85 -0
  151. package/.mindforge/personas/qa-engineer.md +61 -0
  152. package/.mindforge/personas/release-manager.md +76 -0
  153. package/.mindforge/personas/security-reviewer.md +91 -0
  154. package/.mindforge/personas/tech-writer.md +51 -0
  155. package/.mindforge/plugins/PLUGINS-MANIFEST.md +23 -0
  156. package/.mindforge/plugins/plugin-loader.md +93 -0
  157. package/.mindforge/plugins/plugin-registry.md +44 -0
  158. package/.mindforge/plugins/plugin-schema.md +68 -0
  159. package/.mindforge/pr-review/ai-reviewer.md +266 -0
  160. package/.mindforge/pr-review/finding-formatter.md +46 -0
  161. package/.mindforge/pr-review/review-prompt-templates.md +44 -0
  162. package/.mindforge/production/compatibility-layer.md +39 -0
  163. package/.mindforge/production/migration-engine.md +52 -0
  164. package/.mindforge/production/production-checklist.md +165 -0
  165. package/.mindforge/production/token-optimiser.md +68 -0
  166. package/.mindforge/skills/accessibility/SKILL.md +106 -0
  167. package/.mindforge/skills/api-design/SKILL.md +98 -0
  168. package/.mindforge/skills/code-quality/SKILL.md +88 -0
  169. package/.mindforge/skills/data-privacy/SKILL.md +126 -0
  170. package/.mindforge/skills/database-patterns/SKILL.md +192 -0
  171. package/.mindforge/skills/documentation/SKILL.md +91 -0
  172. package/.mindforge/skills/incident-response/SKILL.md +180 -0
  173. package/.mindforge/skills/performance/SKILL.md +120 -0
  174. package/.mindforge/skills/security-review/SKILL.md +83 -0
  175. package/.mindforge/skills/testing-standards/SKILL.md +97 -0
  176. package/.mindforge/team/TEAM-PROFILE.md +42 -0
  177. package/.mindforge/team/multi-handoff.md +23 -0
  178. package/.mindforge/team/profiles/README.md +13 -0
  179. package/.mindforge/team/session-merger.md +18 -0
  180. package/.planning/ARCHITECTURE.md +0 -0
  181. package/.planning/AUDIT.jsonl +0 -0
  182. package/.planning/HANDOFF.json +28 -0
  183. package/.planning/PROJECT.md +33 -0
  184. package/.planning/RELEASE-CHECKLIST.md +68 -0
  185. package/.planning/REQUIREMENTS.md +0 -0
  186. package/.planning/ROADMAP.md +0 -0
  187. package/.planning/STATE.md +31 -0
  188. package/.planning/approvals/.gitkeep +1 -0
  189. package/.planning/archive/.gitkeep +1 -0
  190. package/.planning/audit-archive/.gitkeep +1 -0
  191. package/.planning/decisions/.gitkeep +0 -0
  192. package/.planning/decisions/ADR-001-handoff-tracking.md +41 -0
  193. package/.planning/decisions/ADR-002-markdown-commands.md +46 -0
  194. package/.planning/decisions/ADR-003-skills-trigger-model.md +37 -0
  195. package/.planning/decisions/ADR-004-wave-parallelism-model.md +45 -0
  196. package/.planning/decisions/ADR-005-append-only-audit-log.md +51 -0
  197. package/.planning/decisions/ADR-006-tiered-skills-system.md +22 -0
  198. package/.planning/decisions/ADR-007-trigger-keyword-model.md +22 -0
  199. package/.planning/decisions/ADR-008-just-in-time-skill-loading.md +29 -0
  200. package/.planning/decisions/ADR-009-enterprise-integration-retry-policy.md +8 -0
  201. package/.planning/decisions/ADR-010-governance-tier-escalation.md +8 -0
  202. package/.planning/decisions/ADR-011-multi-developer-handoff-contract.md +8 -0
  203. package/.planning/decisions/ADR-012-intelligence-feedback-loops.md +19 -0
  204. package/.planning/decisions/ADR-013-mindforge-md-constitution.md +16 -0
  205. package/.planning/decisions/ADR-014-metrics-as-signals-not-evaluation.md +15 -0
  206. package/.planning/decisions/ADR-015-npm-based-skill-registry.md +26 -0
  207. package/.planning/decisions/ADR-016-ci-exit-code-0-on-timeout.md +27 -0
  208. package/.planning/decisions/ADR-017-sdk-localhost-only.md +28 -0
  209. package/.planning/decisions/ADR-018-installer-self-install-detection.md +15 -0
  210. package/.planning/decisions/ADR-019-self-update-scope-preservation.md +14 -0
  211. package/.planning/decisions/ADR-020-v1.0.0-stable-interface-contract.md +23 -0
  212. package/.planning/jira-sync.json +9 -0
  213. package/.planning/milestones/.gitkeep +1 -0
  214. package/.planning/phases/day1/REVIEW-DAY1.md +50 -0
  215. package/.planning/phases/day1/SECURITY-REVIEW-DAY1.md +15 -0
  216. package/.planning/phases/day2/REVIEW-DAY2.md +521 -0
  217. package/.planning/phases/day3/REVIEW-DAY3.md +234 -0
  218. package/.planning/slack-threads.json +6 -0
  219. package/CHANGELOG.md +175 -0
  220. package/LICENSE +21 -0
  221. package/MINDFORGE.md +76 -0
  222. package/README.md +182 -0
  223. package/RELEASENOTES.md +41 -0
  224. package/SECURITY.md +4 -0
  225. package/bin/install.js +120 -0
  226. package/bin/installer-core.js +292 -0
  227. package/bin/migrations/0.1.0-to-0.5.0.js +37 -0
  228. package/bin/migrations/0.5.0-to-0.6.0.js +17 -0
  229. package/bin/migrations/0.6.0-to-1.0.0.js +100 -0
  230. package/bin/migrations/migrate.js +151 -0
  231. package/bin/migrations/schema-versions.js +64 -0
  232. package/bin/updater/changelog-fetcher.js +62 -0
  233. package/bin/updater/self-update.js +169 -0
  234. package/bin/updater/version-comparator.js +68 -0
  235. package/bin/validate-config.js +92 -0
  236. package/bin/wizard/config-generator.js +112 -0
  237. package/bin/wizard/environment-detector.js +76 -0
  238. package/bin/wizard/setup-wizard.js +237 -0
  239. package/docs/Context/Master-Context.md +701 -0
  240. package/docs/architecture/README.md +35 -0
  241. package/docs/architecture/decision-records-index.md +26 -0
  242. package/docs/ci-cd-integration.md +30 -0
  243. package/docs/ci-quickstart.md +78 -0
  244. package/docs/commands-reference.md +11 -0
  245. package/docs/contributing/CONTRIBUTING.md +38 -0
  246. package/docs/contributing/plugin-authoring.md +50 -0
  247. package/docs/contributing/skill-authoring.md +41 -0
  248. package/docs/enterprise-setup.md +25 -0
  249. package/docs/faq.md +38 -0
  250. package/docs/getting-started.md +36 -0
  251. package/docs/governance-guide.md +23 -0
  252. package/docs/mindforge-md-reference.md +53 -0
  253. package/docs/monorepo-guide.md +26 -0
  254. package/docs/persona-customisation.md +56 -0
  255. package/docs/quick-verify.md +33 -0
  256. package/docs/reference/audit-events.md +53 -0
  257. package/docs/reference/commands.md +82 -0
  258. package/docs/reference/config-reference.md +64 -0
  259. package/docs/reference/sdk-api.md +48 -0
  260. package/docs/reference/skills-api.md +57 -0
  261. package/docs/release-checklist-guide.md +37 -0
  262. package/docs/requirements.md +29 -0
  263. package/docs/sdk-reference.md +27 -0
  264. package/docs/security/SECURITY.md +42 -0
  265. package/docs/security/penetration-test-results.md +31 -0
  266. package/docs/security/threat-model.md +142 -0
  267. package/docs/skills-authoring-guide.md +119 -0
  268. package/docs/skills-publishing-guide.md +21 -0
  269. package/docs/team-setup-guide.md +21 -0
  270. package/docs/troubleshooting.md +119 -0
  271. package/docs/tutorial.md +195 -0
  272. package/docs/upgrade.md +44 -0
  273. package/docs/user-guide.md +131 -0
  274. package/docs/usp-features.md +214 -0
  275. package/eslint.config.mjs +31 -0
  276. package/examples/starter-project/.planning/AUDIT.jsonl +1 -0
  277. package/examples/starter-project/.planning/HANDOFF.json +23 -0
  278. package/examples/starter-project/.planning/PROJECT.md +27 -0
  279. package/examples/starter-project/.planning/STATE.md +10 -0
  280. package/examples/starter-project/MINDFORGE.md +40 -0
  281. package/examples/starter-project/README.md +14 -0
  282. package/implementation-roadmap/day-1-imp/DAY1-HARDEN.md +823 -0
  283. package/implementation-roadmap/day-1-imp/DAY1-IMPLEMENT.md +2459 -0
  284. package/implementation-roadmap/day-1-imp/DAY1-REVIEW.md +288 -0
  285. package/implementation-roadmap/day-2-imp/DAY2-HARDEN.md +954 -0
  286. package/implementation-roadmap/day-2-imp/DAY2-IMPLEMENT.md +2347 -0
  287. package/implementation-roadmap/day-2-imp/DAY2-REVIEW.md +422 -0
  288. package/implementation-roadmap/day-3-imp/DAY3-HARDEN.md +870 -0
  289. package/implementation-roadmap/day-3-imp/DAY3-IMPLEMENT.md +2798 -0
  290. package/implementation-roadmap/day-3-imp/DAY3-REVIEW.md +484 -0
  291. package/implementation-roadmap/day-4-imp/DAY4-HARDEN.md +1087 -0
  292. package/implementation-roadmap/day-4-imp/DAY4-IMPLEMENT.md +2874 -0
  293. package/implementation-roadmap/day-4-imp/DAY4-REVIEW.md +386 -0
  294. package/implementation-roadmap/day-5-imp/DAY5-HARDEN.md +1078 -0
  295. package/implementation-roadmap/day-5-imp/DAY5-IMPLEMENT.md +3151 -0
  296. package/implementation-roadmap/day-5-imp/DAY5-REVIEW.md +345 -0
  297. package/implementation-roadmap/day-6-imp/DAY6-COMPLETE.md +3919 -0
  298. package/implementation-roadmap/day-7-imp-prod/DAY7-PRODUCTION-FINAL.md +4513 -0
  299. package/package.json +31 -0
  300. package/sdk/README.md +69 -0
  301. package/sdk/eslint.config.mjs +34 -0
  302. package/sdk/package-lock.json +1507 -0
  303. package/sdk/package.json +30 -0
  304. package/sdk/src/client.ts +133 -0
  305. package/sdk/src/commands.ts +63 -0
  306. package/sdk/src/events.ts +166 -0
  307. package/sdk/src/index.ts +22 -0
  308. package/sdk/src/types.ts +87 -0
  309. package/sdk/tsconfig.json +13 -0
  310. package/tests/audit.test.js +206 -0
  311. package/tests/ci-mode.test.js +162 -0
  312. package/tests/compaction.test.js +161 -0
  313. package/tests/distribution.test.js +205 -0
  314. package/tests/e2e.test.js +618 -0
  315. package/tests/governance.test.js +130 -0
  316. package/tests/install.test.js +209 -0
  317. package/tests/integrations.test.js +128 -0
  318. package/tests/intelligence.test.js +117 -0
  319. package/tests/metrics.test.js +96 -0
  320. package/tests/migration.test.js +309 -0
  321. package/tests/production.test.js +416 -0
  322. package/tests/sdk.test.js +200 -0
  323. package/tests/skills-platform.test.js +403 -0
  324. package/tests/wave-engine.test.js +338 -0
@@ -0,0 +1,130 @@
1
+ /**
2
+ * MindForge Day 4 — Governance Tests
3
+ * Run: node tests/governance.test.js
4
+ */
5
+
6
+ const fs = require('fs');
7
+ const assert = require('assert');
8
+
9
+ let passed = 0;
10
+ let failed = 0;
11
+
12
+ function test(name, fn) {
13
+ try {
14
+ fn();
15
+ console.log(` ✅ ${name}`);
16
+ passed++;
17
+ } catch (err) {
18
+ console.error(` ❌ ${name}`);
19
+ console.error(` ${err.message}`);
20
+ failed++;
21
+ }
22
+ }
23
+
24
+ function read(file) {
25
+ return fs.readFileSync(file, 'utf8');
26
+ }
27
+
28
+ function classifyChange({ files, diff, recentHighSeverityFinding = false }) {
29
+ const fileSignals = /(auth\/|security\/|payment\/|billing\/|privacy\/|crypto\/|secrets\/|login\.ts|logout\.ts|token\.ts|password\.ts|credentials\.ts|session\.ts|oauth\.ts|jwt\.ts|hash\.ts|encrypt\.ts|stripe\.ts|payment\.ts|billing\.ts|pii\.ts|consent\.ts)/;
30
+ const codeSignals = /(bcrypt|argon2|jwt\.sign|jwt\.verify|jose\.sign|jose\.verify|stripe\.|paypal\.|createCipheriv|createDecipheriv|crypto\.subtle|hashPassword|verifyPassword|encrypt\(|decrypt\(|role.*permission|hasPermission|SET ROLE|GRANT)/;
31
+
32
+ if (files.some(file => fileSignals.test(file))) return 3;
33
+ if (codeSignals.test(diff)) return 3;
34
+ if (recentHighSeverityFinding) return 3;
35
+ if (files.length > 10) return 2;
36
+ return 1;
37
+ }
38
+
39
+ console.log('\nMindForge Day 4 — Governance Tests\n');
40
+
41
+ console.log('Governance files:');
42
+
43
+ [
44
+ '.mindforge/governance/change-classifier.md',
45
+ '.mindforge/governance/approval-workflow.md',
46
+ '.mindforge/governance/compliance-gates.md',
47
+ '.mindforge/governance/GOVERNANCE-CONFIG.md',
48
+ '.mindforge/team/multi-handoff.md',
49
+ '.mindforge/team/session-merger.md',
50
+ 'docs/governance-guide.md',
51
+ ].forEach(file => {
52
+ test(`${file} exists`, () => assert.ok(fs.existsSync(file), `Missing ${file}`));
53
+ });
54
+
55
+ console.log('\nClassifier hardening:');
56
+
57
+ test('tier 3 triggers on code pattern even in helper.ts', () => {
58
+ const tier = classifyChange({
59
+ files: ['src/utils/helper.ts'],
60
+ diff: '+ const token = jwt.sign(payload, secret);',
61
+ });
62
+ assert.strictEqual(tier, 3);
63
+ });
64
+
65
+ test('tier 3 triggers on audit-history escalation', () => {
66
+ const tier = classifyChange({
67
+ files: ['src/utils/helpers.ts'],
68
+ diff: '+ export const noop = true;',
69
+ recentHighSeverityFinding: true,
70
+ });
71
+ assert.strictEqual(tier, 3);
72
+ });
73
+
74
+ test('change classifier documents trigger points and code-content scanning', () => {
75
+ const content = read('.mindforge/governance/change-classifier.md');
76
+ assert.ok(content.includes('Before each plan executes'), 'Missing plan execution trigger');
77
+ assert.ok(content.includes('Code content patterns'), 'Missing code-content scanning section');
78
+ assert.ok(content.includes('jwt.sign'), 'Missing concrete Tier 3 code pattern');
79
+ });
80
+
81
+ console.log('\nApproval workflow and emergency handling:');
82
+
83
+ test('approval workflow documents pending-only listing and rejection context carry-forward', () => {
84
+ const approve = read('.claude/commands/mindforge/approve.md');
85
+ const workflow = read('.mindforge/governance/approval-workflow.md');
86
+ assert.ok(approve.includes('status: pending'), 'Missing pending-only listing rule');
87
+ assert.ok(workflow.includes('rejection reason'), 'Missing rejection-reason carry-forward');
88
+ });
89
+
90
+ test('approve command requires explicit emergency flag and EMERGENCY_APPROVERS config', () => {
91
+ const approve = read('.claude/commands/mindforge/approve.md');
92
+ const config = read('.mindforge/org/integrations/INTEGRATIONS-CONFIG.md');
93
+ assert.ok(approve.includes('--emergency'), 'Missing emergency flag requirement');
94
+ assert.ok(config.includes('EMERGENCY_APPROVERS='), 'Missing EMERGENCY_APPROVERS');
95
+ });
96
+
97
+ test('approval workflow documents identity assurance limitation', () => {
98
+ const content = read('.mindforge/governance/approval-workflow.md');
99
+ assert.ok(content.includes('spoofable'), 'Missing identity limitation acknowledgement');
100
+ assert.ok(content.includes('IdP'), 'Missing stronger identity recommendation');
101
+ });
102
+
103
+ console.log('\nCompliance and team coordination:');
104
+
105
+ test('gdpr gate runs independently of skill loading and checks retention policy', () => {
106
+ const content = read('.mindforge/governance/compliance-gates.md');
107
+ assert.ok(content.includes('independently of skill loading'), 'Missing skill-independent gate');
108
+ assert.ok(content.includes('retention'), 'Missing retention requirement');
109
+ });
110
+
111
+ test('multi-developer handoff documents stale detection after 4 hours', () => {
112
+ const content = read('.mindforge/team/multi-handoff.md');
113
+ assert.ok(content.includes('older than 4 hours'), 'Missing stale detection threshold');
114
+ });
115
+
116
+ test('session merger requires AUDIT entries to be committed with task commits', () => {
117
+ const content = read('.mindforge/team/session-merger.md');
118
+ assert.ok(content.includes('AUDIT'), 'Missing AUDIT merge guidance');
119
+ assert.ok(content.includes('committed'), 'Missing committed AUDIT guidance');
120
+ });
121
+
122
+ console.log(`\n${'─'.repeat(50)}`);
123
+ console.log(`Results: ${passed} passed, ${failed} failed`);
124
+
125
+ if (failed > 0) {
126
+ console.error(`\n❌ ${failed} test(s) failed.\n`);
127
+ process.exit(1);
128
+ } else {
129
+ console.log('\n✅ All governance tests passed.\n');
130
+ }
@@ -0,0 +1,209 @@
1
+ /**
2
+ * MindForge installer smoke tests
3
+ * Run: node tests/install.test.js
4
+ */
5
+
6
+ const fs = require('fs');
7
+ const path = require('path');
8
+ const assert = require('assert');
9
+
10
+ let passed = 0;
11
+ let failed = 0;
12
+
13
+ function test(name, fn) {
14
+ try {
15
+ fn();
16
+ console.log(` ✅ ${name}`);
17
+ passed++;
18
+ } catch (err) {
19
+ console.error(` ❌ ${name}`);
20
+ console.error(` ${err.message}`);
21
+ failed++;
22
+ }
23
+ }
24
+
25
+ console.log('\nMindForge Day 1 — Structural Integrity Tests\n');
26
+
27
+ // ── Directory structure tests ─────────────────────────────────────────────────
28
+ console.log('Directories:');
29
+ const dirs = [
30
+ '.claude/commands/mindforge',
31
+ '.agent/mindforge',
32
+ '.mindforge/personas',
33
+ '.mindforge/integrations',
34
+ '.mindforge/governance',
35
+ '.mindforge/team',
36
+ '.mindforge/org/integrations',
37
+ '.mindforge/skills/security-review',
38
+ '.mindforge/skills/code-quality',
39
+ '.mindforge/skills/api-design',
40
+ '.mindforge/skills/testing-standards',
41
+ '.mindforge/skills/documentation',
42
+ '.mindforge/org',
43
+ '.planning/decisions',
44
+ 'bin',
45
+ 'docs',
46
+ 'tests',
47
+ '.planning/audit-archive',
48
+ '.planning/approvals',
49
+ '.planning/milestones',
50
+ ];
51
+ dirs.forEach(d => test(d, () => assert.ok(fs.existsSync(d), `Missing: ${d}`)));
52
+
53
+ // ── Required files tests ──────────────────────────────────────────────────────
54
+ console.log('\nRequired files:');
55
+ const files = [
56
+ '.claude/CLAUDE.md',
57
+ '.agent/CLAUDE.md',
58
+ '.claude/commands/mindforge/help.md',
59
+ '.claude/commands/mindforge/init-project.md',
60
+ '.claude/commands/mindforge/plan-phase.md',
61
+ '.claude/commands/mindforge/execute-phase.md',
62
+ '.claude/commands/mindforge/verify-phase.md',
63
+ '.claude/commands/mindforge/ship.md',
64
+ '.claude/commands/mindforge/audit.md',
65
+ '.claude/commands/mindforge/milestone.md',
66
+ '.claude/commands/mindforge/complete-milestone.md',
67
+ '.claude/commands/mindforge/approve.md',
68
+ '.claude/commands/mindforge/sync-jira.md',
69
+ '.claude/commands/mindforge/sync-confluence.md',
70
+ '.mindforge/personas/analyst.md',
71
+ '.mindforge/personas/architect.md',
72
+ '.mindforge/personas/developer.md',
73
+ '.mindforge/personas/qa-engineer.md',
74
+ '.mindforge/personas/security-reviewer.md',
75
+ '.mindforge/personas/tech-writer.md',
76
+ '.mindforge/personas/debug-specialist.md',
77
+ '.mindforge/personas/release-manager.md',
78
+ '.mindforge/skills/security-review/SKILL.md',
79
+ '.mindforge/skills/code-quality/SKILL.md',
80
+ '.mindforge/skills/api-design/SKILL.md',
81
+ '.mindforge/skills/testing-standards/SKILL.md',
82
+ '.mindforge/skills/documentation/SKILL.md',
83
+ '.mindforge/org/ORG.md',
84
+ '.mindforge/org/CONVENTIONS.md',
85
+ '.mindforge/org/SECURITY.md',
86
+ '.mindforge/org/TOOLS.md',
87
+ '.mindforge/integrations/connection-manager.md',
88
+ '.mindforge/integrations/jira.md',
89
+ '.mindforge/integrations/confluence.md',
90
+ '.mindforge/integrations/slack.md',
91
+ '.mindforge/integrations/github.md',
92
+ '.mindforge/integrations/gitlab.md',
93
+ '.mindforge/governance/change-classifier.md',
94
+ '.mindforge/governance/approval-workflow.md',
95
+ '.mindforge/governance/compliance-gates.md',
96
+ '.mindforge/governance/GOVERNANCE-CONFIG.md',
97
+ '.mindforge/team/multi-handoff.md',
98
+ '.mindforge/team/session-merger.md',
99
+ '.mindforge/org/integrations/INTEGRATIONS-CONFIG.md',
100
+ '.planning/STATE.md',
101
+ '.planning/HANDOFF.json',
102
+ '.planning/jira-sync.json',
103
+ '.planning/slack-threads.json',
104
+ 'bin/install.js',
105
+ 'package.json',
106
+ 'README.md',
107
+ 'docs/enterprise-setup.md',
108
+ 'docs/governance-guide.md',
109
+ ];
110
+ files.forEach(f => test(f, () => assert.ok(fs.existsSync(f), `Missing: ${f}`)));
111
+
112
+ // ── Content tests ─────────────────────────────────────────────────────────────
113
+ console.log('\nContent validation:');
114
+
115
+ test('CLAUDE.md has session start protocol', () => {
116
+ const content = fs.readFileSync('.claude/CLAUDE.md', 'utf8');
117
+ assert.ok(content.includes('SESSION START PROTOCOL'), 'Missing session start protocol');
118
+ assert.ok(content.includes('PLAN-FIRST RULE'), 'Missing plan-first rule');
119
+ assert.ok(content.includes('Quality gates'), 'Missing quality gates');
120
+ assert.ok(content.includes('SECURITY AUTO-TRIGGER'), 'Missing security auto-trigger');
121
+ assert.ok(content.includes('/mindforge:audit'), 'Missing Day 4 command awareness');
122
+ assert.ok(content.includes('Tier 3'), 'Missing governance tier awareness');
123
+ });
124
+
125
+ test('CLAUDE.md and .agent/CLAUDE.md are identical', () => {
126
+ const claude = fs.readFileSync('.claude/CLAUDE.md', 'utf8');
127
+ const agent = fs.readFileSync('.agent/CLAUDE.md', 'utf8');
128
+ assert.strictEqual(claude, agent, '.claude/CLAUDE.md and .agent/CLAUDE.md differ');
129
+ });
130
+
131
+ test('All 6 commands mirrored to .agent/mindforge/', () => {
132
+ const claudeCommands = fs.readdirSync('.claude/commands/mindforge/').sort();
133
+ const agentCommands = fs.readdirSync('.agent/mindforge/').sort();
134
+ assert.deepStrictEqual(claudeCommands, agentCommands, 'Command files differ between runtimes');
135
+ });
136
+
137
+ test('HANDOFF.json is valid JSON', () => {
138
+ const content = fs.readFileSync('.planning/HANDOFF.json', 'utf8');
139
+ const parsed = JSON.parse(content);
140
+ assert.ok(parsed.schema_version, 'Missing schema_version field');
141
+ assert.ok(parsed._warning, 'Missing _warning anti-secret field');
142
+ });
143
+
144
+ test('package.json has bin field', () => {
145
+ const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));
146
+ assert.ok(pkg.bin, 'Missing bin field');
147
+ assert.ok(pkg.bin.mindforge, 'Missing bin.mindforge');
148
+ assert.ok(pkg.engines, 'Missing engines field');
149
+ assert.ok(pkg.engines.node, 'Missing engines.node');
150
+ });
151
+
152
+ test('All skill packs have frontmatter triggers', () => {
153
+ const skillDirs = fs.readdirSync('.mindforge/skills/');
154
+ skillDirs.forEach(dir => {
155
+ const skillPath = `.mindforge/skills/${dir}/SKILL.md`;
156
+ if (fs.existsSync(skillPath)) {
157
+ const content = fs.readFileSync(skillPath, 'utf8');
158
+ assert.ok(content.includes('triggers:'), `${skillPath} missing triggers frontmatter`);
159
+ assert.ok(content.includes('name:'), `${skillPath} missing name frontmatter`);
160
+ }
161
+ });
162
+ });
163
+
164
+ test('bin/install.js is executable and has no obvious syntax errors', () => {
165
+ const stat = fs.statSync('bin/install.js');
166
+ assert.ok(stat.size > 1000, 'bin/install.js is suspiciously small');
167
+ const content = fs.readFileSync('bin/install.js', 'utf8');
168
+ assert.ok(content.includes('#!/usr/bin/env node'), 'Missing shebang line');
169
+ assert.ok(content.includes('verifyInstall'), 'Missing install verification function');
170
+ });
171
+
172
+ test('No secrets in any committed file', () => {
173
+ const secretPatterns = [
174
+ /password\s*=\s*['"][^'"]{6,}/i,
175
+ /api[_-]?key\s*=\s*['"][^'"]{10,}/i,
176
+ /secret\s*=\s*['"][^'"]{8,}/i,
177
+ /-----BEGIN (RSA |EC |PRIVATE )?KEY-----/,
178
+ /sk-[a-zA-Z0-9]{20,}/,
179
+ ];
180
+
181
+ function scanDir(dir) {
182
+ if (dir.includes('node_modules') || dir.includes('.git')) return;
183
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
184
+ entries.forEach(entry => {
185
+ const full = path.join(dir, entry.name);
186
+ if (entry.isDirectory()) {
187
+ scanDir(full);
188
+ } else if (entry.name.endsWith('.md') || entry.name.endsWith('.js') || entry.name.endsWith('.json')) {
189
+ const content = fs.readFileSync(full, 'utf8');
190
+ secretPatterns.forEach(pattern => {
191
+ assert.ok(!pattern.test(content), `Potential secret in ${full}`);
192
+ });
193
+ }
194
+ });
195
+ }
196
+
197
+ scanDir('.');
198
+ });
199
+
200
+ // ── Results ───────────────────────────────────────────────────────────────────
201
+ console.log(`\n${'─'.repeat(50)}`);
202
+ console.log(`Results: ${passed} passed, ${failed} failed`);
203
+
204
+ if (failed > 0) {
205
+ console.error(`\n❌ ${failed} test(s) failed. Fix before pushing.\n`);
206
+ process.exit(1);
207
+ } else {
208
+ console.log(`\n✅ All tests passed. Day 1 foundation is solid.\n`);
209
+ }
@@ -0,0 +1,128 @@
1
+ /**
2
+ * MindForge Day 4 — Enterprise Integration Tests
3
+ * Run: node tests/integrations.test.js
4
+ */
5
+
6
+ const fs = require('fs');
7
+ const assert = require('assert');
8
+
9
+ let passed = 0;
10
+ let failed = 0;
11
+
12
+ function test(name, fn) {
13
+ try {
14
+ fn();
15
+ console.log(` ✅ ${name}`);
16
+ passed++;
17
+ } catch (err) {
18
+ console.error(` ❌ ${name}`);
19
+ console.error(` ${err.message}`);
20
+ failed++;
21
+ }
22
+ }
23
+
24
+ function read(file) {
25
+ return fs.readFileSync(file, 'utf8');
26
+ }
27
+
28
+ console.log('\nMindForge Day 4 — Integration Tests\n');
29
+
30
+ console.log('Scaffold and config:');
31
+
32
+ [
33
+ '.mindforge/integrations/connection-manager.md',
34
+ '.mindforge/integrations/jira.md',
35
+ '.mindforge/integrations/confluence.md',
36
+ '.mindforge/integrations/slack.md',
37
+ '.mindforge/integrations/github.md',
38
+ '.mindforge/integrations/gitlab.md',
39
+ '.mindforge/org/integrations/INTEGRATIONS-CONFIG.md',
40
+ '.planning/jira-sync.json',
41
+ '.planning/slack-threads.json',
42
+ ].forEach(file => {
43
+ test(`${file} exists`, () => assert.ok(fs.existsSync(file), `Missing ${file}`));
44
+ });
45
+
46
+ console.log('\nSecurity hardening:');
47
+
48
+ test('integration config contains no token values', () => {
49
+ const content = read('.mindforge/org/integrations/INTEGRATIONS-CONFIG.md');
50
+ const forbidden = [/ghp_[a-zA-Z0-9]+/, /xoxb-[a-zA-Z0-9-]+/, /sk-[a-zA-Z0-9]+/, /API_TOKEN=\S+/];
51
+ forbidden.forEach(pattern => {
52
+ assert.ok(!pattern.test(content), `Potential token leaked in config: ${pattern}`);
53
+ });
54
+ });
55
+
56
+ test('connection manager documents shell debug prohibition and curl verbose prohibition', () => {
57
+ const content = read('.mindforge/integrations/connection-manager.md');
58
+ assert.ok(content.includes('Debug mode prohibition'), 'Missing debug mode guidance');
59
+ assert.ok(content.includes('curl verbose mode prohibition'), 'Missing curl verbose guidance');
60
+ assert.ok(content.includes('set +x'), 'Missing explicit set +x guidance');
61
+ });
62
+
63
+ test('audit schema and audit command document archive rotation after 10000 lines', () => {
64
+ const schema = read('.mindforge/audit/AUDIT-SCHEMA.md');
65
+ const command = read('.claude/commands/mindforge/audit.md');
66
+ assert.ok(schema.includes('10,000 lines'), 'Missing audit rotation threshold in schema');
67
+ assert.ok(command.includes('10,000 lines'), 'Missing audit rotation threshold in command');
68
+ });
69
+
70
+ console.log('\nJira behaviour:');
71
+
72
+ test('jira integration uses dynamic transition lookup instead of hardcoded IDs', () => {
73
+ const content = read('.mindforge/integrations/jira.md');
74
+ assert.ok(content.includes('Never hardcode transition IDs'), 'Missing dynamic lookup guidance');
75
+ assert.ok(content.includes('GET /rest/api/3/issue/{issueKey}/transitions'), 'Missing transitions lookup endpoint');
76
+ assert.ok(content.includes('transition_cache'), 'Missing transition cache guidance');
77
+ });
78
+
79
+ test('jira-sync.json includes anti-secret warning', () => {
80
+ const parsed = JSON.parse(read('.planning/jira-sync.json'));
81
+ assert.ok(parsed._warning, 'Missing _warning');
82
+ assert.ok(parsed._warning.toLowerCase().includes('credentials'), 'Warning should mention credentials');
83
+ });
84
+
85
+ test('jira integration documents backoff and second-429 stop behaviour', () => {
86
+ const content = read('.mindforge/integrations/jira.md');
87
+ assert.ok(content.includes('429'), 'Missing rate limit handling');
88
+ assert.ok(content.includes('retry once'), 'Missing retry-once guidance');
89
+ });
90
+
91
+ console.log('\nConfluence and Slack resilience:');
92
+
93
+ test('confluence integration requires idempotent updates', () => {
94
+ const content = read('.mindforge/integrations/confluence.md');
95
+ assert.ok(content.includes('idempotent'), 'Missing idempotency guidance');
96
+ assert.ok(content.includes('Do not create duplicate pages'), 'Missing duplicate-page guidance');
97
+ });
98
+
99
+ test('slack thread schema is valid and guarded against token storage', () => {
100
+ const parsed = JSON.parse(read('.planning/slack-threads.json'));
101
+ assert.strictEqual(parsed.schema_version, '1.0.0');
102
+ assert.ok(parsed.threads && typeof parsed.threads === 'object', 'Missing threads object');
103
+ assert.ok(parsed._warning.toLowerCase().includes('tokens'), 'Warning should mention tokens');
104
+ });
105
+
106
+ test('slack integration handles invalid thread timestamps and undelivered critical alerts', () => {
107
+ const content = read('.mindforge/integrations/slack.md');
108
+ assert.ok(content.includes('clear that entry'), 'Missing invalid thread handling');
109
+ assert.ok(content.includes('Undelivered alerts'), 'Missing undelivered critical alert handling');
110
+ });
111
+
112
+ console.log('\nGitHub correctness:');
113
+
114
+ test('github integration treats branch-protection 404 as non-fatal and checks branch diff before PR', () => {
115
+ const content = read('.mindforge/integrations/github.md');
116
+ assert.ok(content.includes('404'), 'Missing branch protection 404 handling');
117
+ assert.ok(content.includes('git log origin/${GITHUB_DEFAULT_BRANCH}..HEAD --oneline | wc -l'), 'Missing ahead-of-base check');
118
+ });
119
+
120
+ console.log(`\n${'─'.repeat(50)}`);
121
+ console.log(`Results: ${passed} passed, ${failed} failed`);
122
+
123
+ if (failed > 0) {
124
+ console.error(`\n❌ ${failed} test(s) failed.\n`);
125
+ process.exit(1);
126
+ } else {
127
+ console.log('\n✅ All integration tests passed.\n');
128
+ }
@@ -0,0 +1,117 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const assert = require('assert');
5
+
6
+ let passed = 0;
7
+ let failed = 0;
8
+
9
+ function test(name, fn) {
10
+ try {
11
+ fn();
12
+ console.log(` ✅ ${name}`);
13
+ passed += 1;
14
+ } catch (err) {
15
+ console.error(` ❌ ${name}`);
16
+ console.error(` ${err.message}`);
17
+ failed += 1;
18
+ }
19
+ }
20
+
21
+ function read(p) {
22
+ return fs.existsSync(p) ? fs.readFileSync(p, 'utf8') : '';
23
+ }
24
+
25
+ console.log('\nMindForge Day 5 — Intelligence Tests\n');
26
+
27
+ console.log('Files:');
28
+ [
29
+ '.mindforge/intelligence/health-engine.md',
30
+ '.mindforge/intelligence/difficulty-scorer.md',
31
+ '.mindforge/intelligence/antipattern-detector.md',
32
+ '.mindforge/intelligence/skill-gap-analyser.md',
33
+ '.mindforge/intelligence/smart-compaction.md',
34
+ '.mindforge/team/TEAM-PROFILE.md',
35
+ '.mindforge/team/profiles/README.md',
36
+ 'MINDFORGE.md',
37
+ 'bin/wizard/setup-wizard.js',
38
+ 'bin/wizard/environment-detector.js',
39
+ 'bin/wizard/config-generator.js',
40
+ '.claude/commands/mindforge/health.md',
41
+ '.claude/commands/mindforge/retrospective.md',
42
+ '.claude/commands/mindforge/profile-team.md',
43
+ '.claude/commands/mindforge/metrics.md',
44
+ ].forEach((p) => test(`${p} exists`, () => assert.ok(fs.existsSync(p), `Missing: ${p}`)));
45
+
46
+ console.log('\nReview/hardening checks:');
47
+
48
+ test('health engine required list includes Day 5 command files', () => {
49
+ const c = read('.mindforge/intelligence/health-engine.md');
50
+ assert.ok(c.includes('health.md'));
51
+ assert.ok(c.includes('retrospective.md'));
52
+ assert.ok(c.includes('profile-team.md'));
53
+ assert.ok(c.includes('metrics.md'));
54
+ });
55
+
56
+ test('health engine includes audit quarantine approach', () => {
57
+ const c = read('.mindforge/intelligence/health-engine.md');
58
+ assert.ok(c.includes('AUDIT.jsonl.quarantine'));
59
+ assert.ok(c.toLowerCase().includes('never delete lines'));
60
+ });
61
+
62
+ test('antipattern detector excludes test files for C01', () => {
63
+ const c = read('.mindforge/intelligence/antipattern-detector.md');
64
+ assert.ok(c.includes('*.test.ts'));
65
+ assert.ok(c.includes('*.spec.ts'));
66
+ assert.ok(c.includes('type-guard'));
67
+ });
68
+
69
+ test('antipattern detector includes cursor pagination exception', () => {
70
+ const c = read('.mindforge/intelligence/antipattern-detector.md');
71
+ assert.ok(c.includes('cursor:'));
72
+ assert.ok(c.includes('B03'));
73
+ });
74
+
75
+ test('smart compaction includes Level 1/2/3 and inconsistency file display', () => {
76
+ const c = read('.mindforge/intelligence/smart-compaction.md');
77
+ assert.ok(c.includes('Level 1'));
78
+ assert.ok(c.includes('Level 2'));
79
+ assert.ok(c.includes('Level 3'));
80
+ assert.ok(c.includes('first 50 lines'));
81
+ });
82
+
83
+ test('difficulty scorer includes migration context handling and split recommendation', () => {
84
+ const c = read('.mindforge/intelligence/difficulty-scorer.md');
85
+ assert.ok(c.includes('migration'));
86
+ assert.ok(c.includes('/mindforge:discuss-phase [N] --split'));
87
+ });
88
+
89
+ test('MINDFORGE has non-overridable section', () => {
90
+ const c = read('MINDFORGE.md');
91
+ assert.ok(c.includes('NON-OVERRIDABLE'));
92
+ });
93
+
94
+ test('retrospective command includes MINDFORGE feedback step', () => {
95
+ const c = read('.claude/commands/mindforge/retrospective.md');
96
+ assert.ok(c.includes('MINDFORGE.md'));
97
+ assert.ok(c.toLowerCase().includes('apply learnings'));
98
+ });
99
+
100
+ test('wizard checks stdin tty for interactivity', () => {
101
+ const c = read('bin/wizard/setup-wizard.js');
102
+ assert.ok(c.includes('process.stdin.isTTY'));
103
+ });
104
+
105
+ test('environment detector checks devDependencies', () => {
106
+ const c = read('bin/wizard/environment-detector.js');
107
+ assert.ok(c.includes('devDependencies'));
108
+ });
109
+
110
+ test('config generator uses idempotent already configured behavior', () => {
111
+ const c = read('bin/wizard/config-generator.js');
112
+ assert.ok(c.includes('already configured'));
113
+ });
114
+
115
+ console.log(`\n${'─'.repeat(50)}`);
116
+ console.log(`Results: ${passed} passed, ${failed} failed`);
117
+ if (failed > 0) process.exit(1);
@@ -0,0 +1,96 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const assert = require('assert');
5
+
6
+ let passed = 0;
7
+ let failed = 0;
8
+
9
+ function test(name, fn) {
10
+ try {
11
+ fn();
12
+ console.log(` ✅ ${name}`);
13
+ passed += 1;
14
+ } catch (err) {
15
+ console.error(` ❌ ${name}`);
16
+ console.error(` ${err.message}`);
17
+ failed += 1;
18
+ }
19
+ }
20
+
21
+ function read(p) {
22
+ return fs.existsSync(p) ? fs.readFileSync(p, 'utf8') : '';
23
+ }
24
+
25
+ function calcScore(opts = {}) {
26
+ const {
27
+ tasksFailed = 0,
28
+ qualityGatesFailed = 0,
29
+ critical = 0,
30
+ high = 0,
31
+ medium = 0,
32
+ } = opts;
33
+ let s = 100;
34
+ s -= tasksFailed * 15;
35
+ s -= qualityGatesFailed * 10;
36
+ s -= critical * 30;
37
+ s -= high * 15;
38
+ s -= medium * 5;
39
+ if (!qualityGatesFailed) s += 5;
40
+ if (!critical && !high) s += 5;
41
+ return Math.max(0, Math.min(100, s));
42
+ }
43
+
44
+ console.log('\nMindForge Day 5 — Metrics Tests\n');
45
+
46
+ console.log('Files:');
47
+ [
48
+ '.mindforge/metrics/METRICS-SCHEMA.md',
49
+ '.mindforge/metrics/quality-tracker.md',
50
+ '.mindforge/team/TEAM-PROFILE.md',
51
+ ].forEach((p) => test(`${p} exists`, () => assert.ok(fs.existsSync(p), `Missing: ${p}`)));
52
+
53
+ console.log('\nSchema checks:');
54
+
55
+ test('metrics schema defines compaction-quality.jsonl', () => {
56
+ const c = read('.mindforge/metrics/METRICS-SCHEMA.md');
57
+ assert.ok(c.includes('compaction-quality.jsonl'));
58
+ });
59
+
60
+ test('metrics schema defines trigger_type in skill usage', () => {
61
+ const c = read('.mindforge/metrics/METRICS-SCHEMA.md');
62
+ assert.ok(c.includes('trigger_type'));
63
+ });
64
+
65
+ test('metrics schema defines session_quality_score', () => {
66
+ const c = read('.mindforge/metrics/METRICS-SCHEMA.md');
67
+ assert.ok(c.includes('session_quality_score'));
68
+ });
69
+
70
+ test('quality tracker includes automatic adjustments', () => {
71
+ const c = read('.mindforge/metrics/quality-tracker.md').toLowerCase();
72
+ assert.ok(c.includes('automatic adjustments'));
73
+ });
74
+
75
+ test('team profile includes non-evaluative metrics policy', () => {
76
+ const c = read('.mindforge/team/TEAM-PROFILE.md').toLowerCase();
77
+ assert.ok(c.includes('not developer performance'));
78
+ });
79
+
80
+ console.log('\nScore behavior:');
81
+
82
+ test('perfect score clamps to 100', () => {
83
+ assert.strictEqual(calcScore({}), 100);
84
+ });
85
+
86
+ test('heavy failure scenario clamps to 0', () => {
87
+ assert.strictEqual(calcScore({ tasksFailed: 10, qualityGatesFailed: 5, critical: 3 }), 0);
88
+ });
89
+
90
+ test('one task failure lowers score below 100', () => {
91
+ assert.ok(calcScore({ tasksFailed: 1 }) < 100);
92
+ });
93
+
94
+ console.log(`\n${'─'.repeat(50)}`);
95
+ console.log(`Results: ${passed} passed, ${failed} failed`);
96
+ if (failed > 0) process.exit(1);