sinapse-ai 9.4.0 → 9.5.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 (266) hide show
  1. package/.claude/CLAUDE.md +10 -4
  2. package/.claude/hooks/enforce-architecture-first.py +197 -197
  3. package/.claude/hooks/enforce-git-push-authority.sh +25 -4
  4. package/.claude/hooks/mind-clone-governance.py +193 -193
  5. package/.claude/hooks/read-protection.py +152 -152
  6. package/.claude/hooks/sql-governance.py +183 -183
  7. package/.claude/hooks/verify-packages.cjs +83 -0
  8. package/.claude/hooks/write-path-validation.py +195 -195
  9. package/.claude/rules/hook-governance.md +1 -0
  10. package/.claude/rules/mandatory-delegation.md +24 -0
  11. package/.claude/rules/project-intelligence.md +63 -0
  12. package/.claude/rules/response-format.md +4 -0
  13. package/.claude/rules/safe-collaboration.md +4 -2
  14. package/.claude/rules/security-data-protection.md +18 -0
  15. package/.claude/rules/squad-awareness.md +93 -67
  16. package/.claude/rules/token-economy.md +148 -0
  17. package/.codex/agents/analyst.md +90 -0
  18. package/.codex/agents/architect.md +78 -0
  19. package/.codex/agents/data-engineer.md +38 -0
  20. package/.codex/agents/developer.md +97 -0
  21. package/.codex/agents/devops.md +121 -0
  22. package/.codex/agents/product-lead.md +27 -0
  23. package/.codex/agents/project-lead.md +28 -0
  24. package/.codex/agents/quality-gate.md +89 -0
  25. package/.codex/agents/sprint-lead.md +28 -0
  26. package/.codex/agents/squad-creator.md +58 -0
  27. package/.codex/agents/ux-design-expert.md +28 -0
  28. package/.sinapse-ai/core/code-intel/registry-syncer.js +56 -3
  29. package/.sinapse-ai/core/doctor/checks/agent-memory.js +5 -1
  30. package/.sinapse-ai/core/doctor/checks/claude-md.js +4 -1
  31. package/.sinapse-ai/core/doctor/checks/code-intel.js +5 -1
  32. package/.sinapse-ai/core/doctor/checks/commands-count.js +4 -1
  33. package/.sinapse-ai/core/doctor/checks/constitution-consistency.js +4 -1
  34. package/.sinapse-ai/core/doctor/checks/core-config.js +4 -1
  35. package/.sinapse-ai/core/doctor/checks/entity-registry.js +6 -1
  36. package/.sinapse-ai/core/doctor/checks/git-hooks.js +5 -1
  37. package/.sinapse-ai/core/doctor/checks/graph-dashboard.js +4 -1
  38. package/.sinapse-ai/core/doctor/checks/hooks-claude-count.js +5 -1
  39. package/.sinapse-ai/core/doctor/checks/ide-sync.js +4 -1
  40. package/.sinapse-ai/core/doctor/checks/node-version.js +4 -1
  41. package/.sinapse-ai/core/doctor/checks/npm-packages.js +4 -1
  42. package/.sinapse-ai/core/doctor/checks/rules-files.js +4 -1
  43. package/.sinapse-ai/core/doctor/checks/settings-json.js +4 -1
  44. package/.sinapse-ai/core/doctor/checks/skills-count.js +4 -1
  45. package/.sinapse-ai/core/doctor/index.js +157 -50
  46. package/.sinapse-ai/core/ids/registry-updater.js +6 -1
  47. package/.sinapse-ai/core/logger/index.js +319 -0
  48. package/.sinapse-ai/core/orchestration/terminal-spawner.js +2 -2
  49. package/.sinapse-ai/core/telemetry/index.js +247 -0
  50. package/.sinapse-ai/data/entity-registry.yaml +1384 -944
  51. package/.sinapse-ai/development/agents/architect.md +5 -0
  52. package/.sinapse-ai/development/agents/data-engineer.md +38 -0
  53. package/.sinapse-ai/development/agents/developer.md +28 -0
  54. package/.sinapse-ai/development/agents/devops.md +4 -0
  55. package/.sinapse-ai/development/agents/product-lead.md +27 -0
  56. package/.sinapse-ai/development/agents/project-lead.md +28 -0
  57. package/.sinapse-ai/development/agents/quality-gate.md +4 -0
  58. package/.sinapse-ai/development/agents/sprint-lead/MEMORY.md +8 -0
  59. package/.sinapse-ai/development/agents/sprint-lead.md +28 -0
  60. package/.sinapse-ai/development/agents/squad-creator.md +58 -0
  61. package/.sinapse-ai/development/agents/ux-design-expert.md +28 -0
  62. package/.sinapse-ai/development/knowledge-base/agent-communication-protocol.md +127 -0
  63. package/.sinapse-ai/development/knowledge-base/database-scaling-patterns.md +374 -0
  64. package/.sinapse-ai/development/knowledge-base/environment-deployment-patterns.md +353 -0
  65. package/.sinapse-ai/development/knowledge-base/gotchas-patterns.md +224 -0
  66. package/.sinapse-ai/development/knowledge-base/infrastructure-decision-framework.md +221 -0
  67. package/.sinapse-ai/development/knowledge-base/security-pre-deploy-checklist.md +410 -0
  68. package/.sinapse-ai/development/knowledge-base/software-architecture-patterns.md +299 -0
  69. package/.sinapse-ai/development/knowledge-base/token-economy-guide.md +198 -0
  70. package/.sinapse-ai/development/scripts/populate-entity-registry.js +5 -1
  71. package/.sinapse-ai/development/skills/captcha-handler.md +82 -0
  72. package/.sinapse-ai/development/skills/chrome-brain.md +81 -0
  73. package/.sinapse-ai/development/skills/deploy-readiness.md +93 -0
  74. package/.sinapse-ai/development/skills/model-router.md +92 -0
  75. package/.sinapse-ai/development/skills/sinapse-methodology.md +175 -0
  76. package/.sinapse-ai/development/skills/story-fast-track.md +71 -0
  77. package/.sinapse-ai/development/tasks/dev-develop-story.md +10 -0
  78. package/.sinapse-ai/development/tasks/environment-promotion-pipeline.md +582 -0
  79. package/.sinapse-ai/development/tasks/generate-agent-handoff.md +223 -0
  80. package/.sinapse-ai/development/tasks/infrastructure-assessment.md +432 -0
  81. package/.sinapse-ai/development/tasks/load-testing-setup.md +611 -0
  82. package/.sinapse-ai/development/tasks/observability-blueprint.md +562 -0
  83. package/.sinapse-ai/development/templates/legal/breach-notification-tmpl.md +113 -0
  84. package/.sinapse-ai/development/templates/legal/privacy-policy-tmpl.md +93 -0
  85. package/.sinapse-ai/development/templates/legal/terms-of-service-tmpl.md +85 -0
  86. package/.sinapse-ai/development/templates/service-template/README.md.hbs +159 -159
  87. package/.sinapse-ai/development/templates/service-template/__tests__/index.test.ts.hbs +238 -238
  88. package/.sinapse-ai/development/templates/service-template/client.ts.hbs +404 -404
  89. package/.sinapse-ai/development/templates/service-template/errors.ts.hbs +183 -183
  90. package/.sinapse-ai/development/templates/service-template/index.ts.hbs +121 -121
  91. package/.sinapse-ai/development/templates/service-template/package.json.hbs +88 -88
  92. package/.sinapse-ai/development/templates/service-template/types.ts.hbs +146 -146
  93. package/.sinapse-ai/development/templates/squad-template/LICENSE +22 -22
  94. package/.sinapse-ai/development/workflows/story-development-cycle.yaml +40 -1
  95. package/.sinapse-ai/hooks/ids-post-commit.js +22 -0
  96. package/.sinapse-ai/infrastructure/contracts/compatibility/README.md +42 -0
  97. package/.sinapse-ai/infrastructure/contracts/compatibility/sinapse-current.yaml +35 -0
  98. package/.sinapse-ai/infrastructure/scripts/llm-routing/templates/claude-free-tracked.cmd +127 -127
  99. package/.sinapse-ai/infrastructure/scripts/llm-routing/templates/deepseek-proxy.cmd +71 -71
  100. package/.sinapse-ai/infrastructure/scripts/llm-routing/templates/deepseek-usage.cmd +51 -51
  101. package/.sinapse-ai/infrastructure/scripts/pr-review-ai.js +16 -13
  102. package/.sinapse-ai/infrastructure/scripts/setup-project-infra.js +128 -0
  103. package/.sinapse-ai/infrastructure/scripts/test-discovery.js +8 -3
  104. package/.sinapse-ai/infrastructure/scripts/validate-manifest-parity.js +380 -0
  105. package/.sinapse-ai/infrastructure/scripts/validate-parity.js +76 -25
  106. package/.sinapse-ai/infrastructure/templates/coderabbit.yaml.template +280 -280
  107. package/.sinapse-ai/infrastructure/templates/config/env.example +16 -0
  108. package/.sinapse-ai/infrastructure/templates/config/gitignore-additions.tmpl +59 -0
  109. package/.sinapse-ai/infrastructure/templates/github/CODEOWNERS.template +12 -0
  110. package/.sinapse-ai/infrastructure/templates/github/PULL_REQUEST_TEMPLATE.md +29 -0
  111. package/.sinapse-ai/infrastructure/templates/github/ci-template.yml +77 -0
  112. package/.sinapse-ai/infrastructure/templates/github/issue-templates/bug_report.md +34 -0
  113. package/.sinapse-ai/infrastructure/templates/github/issue-templates/feature_request.md +19 -0
  114. package/.sinapse-ai/infrastructure/templates/github-workflows/ci.yml.template +170 -170
  115. package/.sinapse-ai/infrastructure/templates/github-workflows/pr-automation.yml.template +331 -331
  116. package/.sinapse-ai/infrastructure/templates/github-workflows/release.yml.template +197 -197
  117. package/.sinapse-ai/infrastructure/templates/gitignore/gitignore-brownfield-merge.tmpl +19 -19
  118. package/.sinapse-ai/infrastructure/templates/gitignore/gitignore-node.tmpl +86 -86
  119. package/.sinapse-ai/infrastructure/templates/gitignore/gitignore-python.tmpl +146 -146
  120. package/.sinapse-ai/infrastructure/templates/gitignore/gitignore-sinapse-base.tmpl +64 -64
  121. package/.sinapse-ai/infrastructure/templates/sinapse-sync.yaml.template +183 -183
  122. package/.sinapse-ai/install-manifest.yaml +275 -140
  123. package/.sinapse-ai/local-config.yaml.template +65 -65
  124. package/.sinapse-ai/monitor/hooks/lib/__init__.py +2 -2
  125. package/.sinapse-ai/monitor/hooks/lib/enrich.py +59 -59
  126. package/.sinapse-ai/monitor/hooks/lib/send_event.py +48 -48
  127. package/.sinapse-ai/monitor/hooks/notification.py +30 -30
  128. package/.sinapse-ai/monitor/hooks/post_tool_use.py +46 -46
  129. package/.sinapse-ai/monitor/hooks/pre_compact.py +30 -30
  130. package/.sinapse-ai/monitor/hooks/pre_tool_use.py +41 -41
  131. package/.sinapse-ai/monitor/hooks/stop.py +30 -30
  132. package/.sinapse-ai/monitor/hooks/subagent_stop.py +30 -30
  133. package/.sinapse-ai/monitor/hooks/user_prompt_submit.py +39 -39
  134. package/.sinapse-ai/product/templates/adr.hbs +126 -126
  135. package/.sinapse-ai/product/templates/dbdr.hbs +242 -242
  136. package/.sinapse-ai/product/templates/epic.hbs +213 -213
  137. package/.sinapse-ai/product/templates/pmdr.hbs +187 -187
  138. package/.sinapse-ai/product/templates/prd-v2.0.hbs +217 -217
  139. package/.sinapse-ai/product/templates/prd.hbs +202 -202
  140. package/.sinapse-ai/product/templates/story-tmpl.yaml +59 -0
  141. package/.sinapse-ai/product/templates/story.hbs +264 -264
  142. package/.sinapse-ai/product/templates/task.hbs +171 -171
  143. package/.sinapse-ai/product/templates/tmpl-comment-on-examples.sql +159 -159
  144. package/.sinapse-ai/product/templates/tmpl-migration-script.sql +92 -92
  145. package/.sinapse-ai/product/templates/tmpl-rls-granular-policies.sql +105 -105
  146. package/.sinapse-ai/product/templates/tmpl-rls-kiss-policy.sql +11 -11
  147. package/.sinapse-ai/product/templates/tmpl-rls-roles.sql +136 -136
  148. package/.sinapse-ai/product/templates/tmpl-rls-simple.sql +78 -78
  149. package/.sinapse-ai/product/templates/tmpl-rls-tenant.sql +153 -153
  150. package/.sinapse-ai/product/templates/tmpl-rollback-script.sql +78 -78
  151. package/.sinapse-ai/product/templates/tmpl-seed-data.sql +141 -141
  152. package/.sinapse-ai/product/templates/tmpl-smoke-test.sql +17 -17
  153. package/.sinapse-ai/product/templates/tmpl-staging-copy-merge.sql +140 -140
  154. package/.sinapse-ai/product/templates/tmpl-stored-proc.sql +141 -141
  155. package/.sinapse-ai/product/templates/tmpl-trigger.sql +153 -153
  156. package/.sinapse-ai/product/templates/tmpl-view-materialized.sql +134 -134
  157. package/.sinapse-ai/product/templates/tmpl-view.sql +178 -178
  158. package/.sinapse-ai/scripts/diagnostics/health-dashboard/package-lock.json +427 -355
  159. package/LICENSE +34 -34
  160. package/README.en.md +167 -20
  161. package/README.md +190 -22
  162. package/bin/cli.js +510 -196
  163. package/bin/postinstall.js +564 -0
  164. package/bin/sinapse-cli +283 -283
  165. package/bin/sinapse-graph.js +9 -0
  166. package/bin/sinapse-init.js +36 -4
  167. package/bin/sinapse-minimal.js +20 -9
  168. package/bin/sinapse.js +202 -122
  169. package/bin/utils/deprecation-warning.js +46 -0
  170. package/bin/utils/pre-push-safety.js +14 -0
  171. package/docs/TELEMETRY.md +131 -0
  172. package/docs/chrome-brain-upgrade-plan.md +624 -0
  173. package/docs/framework/orqx-plan.md +1 -1
  174. package/docs/installation/chrome-brain.md +17 -7
  175. package/docs/mega-upgrade-orchestration-plan.md +71 -0
  176. package/docs/pt/contributing.md +20 -0
  177. package/docs/research-synthesis-for-upgrade.md +511 -0
  178. package/docs/security-audit-report.md +306 -0
  179. package/package.json +20 -8
  180. package/packages/installer/src/config/configure-environment.js +19 -44
  181. package/packages/installer/src/detection/detect-project-type.js +181 -63
  182. package/packages/installer/src/installer/manifest-signature.js +32 -17
  183. package/packages/installer/src/wizard/i18n.js +12 -0
  184. package/packages/installer/src/wizard/ide-config-generator.js +8 -39
  185. package/packages/installer/src/wizard/index.js +119 -14
  186. package/packages/installer/src/wizard/questions.js +2 -3
  187. package/packages/installer/tests/integration/environment-configuration.test.js +7 -5
  188. package/packages/installer/tests/unit/detection/detect-project-type.test.js +138 -1
  189. package/packages/installer/tests/unit/doctor/doctor-orchestrator.test.js +3 -3
  190. package/packages/sinapse-install/bin/edmcp.js +0 -0
  191. package/packages/sinapse-install/bin/sinapse-install.js +0 -0
  192. package/packages/sinapse-pro-cli/bin/sinapse-pro.js +0 -0
  193. package/scripts/check-markdown-links.py +353 -353
  194. package/scripts/coverage-report-summary.js +169 -0
  195. package/scripts/generate-install-manifest.js +6 -2
  196. package/scripts/release-readiness.js +169 -0
  197. package/scripts/test-install-matrix-local.sh +153 -0
  198. package/scripts/validate-install-docs.js +394 -0
  199. package/scripts/validate-no-external-refs.js +376 -0
  200. package/scripts/validate-squad-orqx.js +302 -0
  201. package/scripts/validate-story-meta.js +263 -0
  202. package/squads/claude-code-mastery/CHANGELOG.md +1 -1
  203. package/squads/claude-code-mastery/README.md +2 -2
  204. package/squads/claude-code-mastery/squad.yaml +1 -1
  205. package/squads/squad-artdir/README.md +90 -0
  206. package/squads/squad-artdir/agents/accessibility-guardian.md +184 -0
  207. package/squads/squad-artdir/agents/artdir-orqx.md +145 -0
  208. package/squads/squad-artdir/agents/color-psychologist.md +166 -0
  209. package/squads/squad-artdir/agents/cro-persuasion.md +161 -0
  210. package/squads/squad-artdir/agents/design-system-architect.md +100 -0
  211. package/squads/squad-artdir/agents/ia-architect.md +169 -0
  212. package/squads/squad-artdir/agents/interaction-designer.md +162 -0
  213. package/squads/squad-artdir/agents/layout-engineer.md +163 -0
  214. package/squads/squad-artdir/agents/motion-architect.md +185 -0
  215. package/squads/squad-artdir/agents/platform-aesthetic-director.md +84 -0
  216. package/squads/squad-artdir/agents/premium-packaging-strategist.md +107 -0
  217. package/squads/squad-artdir/agents/product-surface-director.md +86 -0
  218. package/squads/squad-artdir/agents/type-systemist.md +138 -0
  219. package/squads/squad-artdir/agents/visual-strategist.md +127 -0
  220. package/squads/squad-artdir/checklists/seven-pillars-validation-checklist.md +172 -0
  221. package/squads/squad-artdir/knowledge-base/case-nyo-ia-reference.md +289 -0
  222. package/squads/squad-artdir/knowledge-base/deliverables-templates.md +457 -0
  223. package/squads/squad-artdir/knowledge-base/motion-technique-catalog.md +247 -0
  224. package/squads/squad-artdir/knowledge-base/premium-packaging-principles.md +133 -0
  225. package/squads/squad-artdir/knowledge-base/psychological-toolkit.md +229 -0
  226. package/squads/squad-artdir/knowledge-base/saas-art-direction-canon.md +242 -0
  227. package/squads/squad-artdir/knowledge-base/seven-pillars-framework.md +289 -0
  228. package/squads/squad-artdir/knowledge-base/ten-pillars-framework.md +221 -0
  229. package/squads/squad-artdir/package.json +20 -0
  230. package/squads/squad-artdir/squad.yaml +271 -0
  231. package/squads/squad-artdir/tasks/audit-conversion.md +97 -0
  232. package/squads/squad-artdir/tasks/audit-drift-multi-surface.md +55 -0
  233. package/squads/squad-artdir/tasks/consult-saas-canon.md +54 -0
  234. package/squads/squad-artdir/tasks/create-art-direction-brief.md +110 -0
  235. package/squads/squad-artdir/tasks/create-premium-packaging-brief.md +61 -0
  236. package/squads/squad-artdir/tasks/create-wireflow.md +84 -0
  237. package/squads/squad-artdir/tasks/design-color-system.md +81 -0
  238. package/squads/squad-artdir/tasks/design-product-surface.md +60 -0
  239. package/squads/squad-artdir/tasks/design-token-system.md +58 -0
  240. package/squads/squad-artdir/tasks/diagnose-visual-language.md +92 -0
  241. package/squads/squad-artdir/tasks/first-5-minutes-choreography.md +65 -0
  242. package/squads/squad-artdir/tasks/specify-motion-system.md +84 -0
  243. package/squads/squad-artdir/tasks/validate-against-pillars.md +143 -0
  244. package/squads/squad-artdir/templates/art-direction-brief-template.md +215 -0
  245. package/squads/squad-artdir/workflows/conversion-audit-cycle.yaml +78 -0
  246. package/squads/squad-artdir/workflows/full-art-direction-cycle.yaml +98 -0
  247. package/squads/squad-artdir/workflows/saas-platform-art-direction-cycle.yaml +174 -0
  248. package/squads/squad-brand/knowledge-base/ai-visual-generation-canon.md +234 -0
  249. package/squads/squad-brand/squad.yaml +20 -6
  250. package/squads/squad-claude/knowledge-base/context-window-optimization.md +1 -1
  251. package/squads/squad-claude/knowledge-base/swarm-orchestration-patterns.md +2 -2
  252. package/squads/squad-content/knowledge-base/ai-native-content-loop.md +220 -0
  253. package/squads/squad-content/knowledge-base/signal-intelligence-v2.md +234 -0
  254. package/squads/squad-content/knowledge-base/task-ownership-map.md +235 -0
  255. package/squads/squad-content/squad.yaml +187 -27
  256. package/squads/squad-copy/knowledge-base/ai-copy-human-loop-canon.md +235 -0
  257. package/squads/squad-copy/squad.yaml +19 -4
  258. package/squads/squad-design/knowledge-base/cross-surface-token-canon.md +209 -0
  259. package/squads/squad-design/squad.yaml +19 -4
  260. package/.sinapse-ai/core/registry/service-registry.json +0 -6346
  261. package/.sinapse-ai/data/registry-update-log.jsonl +0 -1323
  262. package/.sinapse-ai/manifests/agents.csv +0 -29
  263. package/.sinapse-ai/manifests/tasks.csv +0 -204
  264. package/.sinapse-ai/manifests/workers.csv +0 -196
  265. package/squads/squad-growth/tasks/calculate-sample-size.md +0 -121
  266. package/squads/squad-paidmedia/tasks/calculate-sample-size.md +0 -57
@@ -0,0 +1,169 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * coverage-report-summary — Story 10.25
4
+ *
5
+ * Reads coverage/coverage-summary.json (Jest `json-summary` reporter)
6
+ * and prints a Current vs Floor comparison table to stdout. When run
7
+ * inside GitHub Actions (GITHUB_STEP_SUMMARY env var set), also writes
8
+ * a Markdown table to the job summary file so reviewers see coverage
9
+ * in the PR Checks tab.
10
+ *
11
+ * Always exits 0 — coverage gating is enforced by Jest's
12
+ * coverageThreshold in jest.config.js, not by this script.
13
+ *
14
+ * Usage:
15
+ * node scripts/coverage-report-summary.js
16
+ * node scripts/coverage-report-summary.js --json (JSON output)
17
+ *
18
+ * Reads ratchet floors from jest.config.js coverageThreshold.global.
19
+ */
20
+
21
+ 'use strict';
22
+
23
+ const fs = require('fs');
24
+ const path = require('path');
25
+
26
+ const PROJECT_ROOT = path.resolve(__dirname, '..');
27
+ const SUMMARY_PATH = path.join(PROJECT_ROOT, 'coverage', 'coverage-summary.json');
28
+ const JEST_CONFIG_PATH = path.join(PROJECT_ROOT, 'jest.config.js');
29
+
30
+ function readCoverageSummary(summaryPath = SUMMARY_PATH) {
31
+ if (!fs.existsSync(summaryPath)) {
32
+ return null;
33
+ }
34
+ try {
35
+ const raw = fs.readFileSync(summaryPath, 'utf8');
36
+ return JSON.parse(raw);
37
+ } catch {
38
+ return null;
39
+ }
40
+ }
41
+
42
+ function readRatchetFloors(jestConfigPath = JEST_CONFIG_PATH) {
43
+ // We don't require() jest.config.js because Jest itself loads it with
44
+ // its own resolver. Instead we parse it as text and extract the global
45
+ // floors. This avoids running jest at script load time.
46
+ if (!fs.existsSync(jestConfigPath)) {
47
+ return null;
48
+ }
49
+ const raw = fs.readFileSync(jestConfigPath, 'utf8');
50
+ const globalBlockMatch = raw.match(/global:\s*\{([^}]+)\}/);
51
+ if (!globalBlockMatch) return null;
52
+ const block = globalBlockMatch[1];
53
+ const floors = {};
54
+ for (const key of ['statements', 'branches', 'lines', 'functions']) {
55
+ const re = new RegExp(`${key}\\s*:\\s*(\\d+)`);
56
+ const m = block.match(re);
57
+ if (m) floors[key] = Number(m[1]);
58
+ }
59
+ return floors;
60
+ }
61
+
62
+ function buildRows(summary, floors) {
63
+ if (!summary || !summary.total || !floors) return [];
64
+ const total = summary.total;
65
+ const metrics = ['statements', 'branches', 'lines', 'functions'];
66
+ return metrics.map((m) => {
67
+ const actual = total[m] && typeof total[m].pct === 'number' ? total[m].pct : null;
68
+ const floor = typeof floors[m] === 'number' ? floors[m] : null;
69
+ let status = '?';
70
+ if (actual !== null && floor !== null) {
71
+ status = actual >= floor ? 'PASS' : 'FAIL';
72
+ }
73
+ return { metric: m, floor, actual, status };
74
+ });
75
+ }
76
+
77
+ function formatAsciiTable(rows) {
78
+ const header = ['Metric', 'Floor', 'Actual', 'Status'];
79
+ const widths = header.map((h) => h.length);
80
+ for (const r of rows) {
81
+ widths[0] = Math.max(widths[0], r.metric.length);
82
+ widths[1] = Math.max(widths[1], String(r.floor).length + 1); // +1 for %
83
+ widths[2] = Math.max(widths[2], String(r.actual).length + 1);
84
+ widths[3] = Math.max(widths[3], r.status.length);
85
+ }
86
+ const sep = '+' + widths.map((w) => '-'.repeat(w + 2)).join('+') + '+';
87
+ const fmt = (cells) =>
88
+ '| '
89
+ + cells.map((c, i) => String(c).padEnd(widths[i])).join(' | ')
90
+ + ' |';
91
+ const lines = [sep, fmt(header), sep];
92
+ for (const r of rows) {
93
+ lines.push(
94
+ fmt([
95
+ r.metric,
96
+ r.floor === null ? '?' : `${r.floor}%`,
97
+ r.actual === null ? '?' : `${r.actual}%`,
98
+ r.status,
99
+ ]),
100
+ );
101
+ }
102
+ lines.push(sep);
103
+ return lines.join('\n');
104
+ }
105
+
106
+ function formatMarkdownTable(rows) {
107
+ const lines = [];
108
+ lines.push('### Coverage Report (Story 10.19 ratchet)');
109
+ lines.push('');
110
+ lines.push('| Metric | Floor | Actual | Status |');
111
+ lines.push('|--------|-------|--------|--------|');
112
+ for (const r of rows) {
113
+ const floorStr = r.floor === null ? '?' : `${r.floor}%`;
114
+ const actualStr = r.actual === null ? '?' : `${r.actual}%`;
115
+ const statusEmoji = r.status === 'PASS' ? '✅' : r.status === 'FAIL' ? '❌' : '❓';
116
+ lines.push(`| ${r.metric} | ${floorStr} | ${actualStr} | ${statusEmoji} |`);
117
+ }
118
+ return lines.join('\n');
119
+ }
120
+
121
+ function appendToGithubSummary(markdown) {
122
+ const target = process.env.GITHUB_STEP_SUMMARY;
123
+ if (!target) return false;
124
+ try {
125
+ fs.appendFileSync(target, markdown + '\n\n', 'utf8');
126
+ return true;
127
+ } catch {
128
+ return false;
129
+ }
130
+ }
131
+
132
+ function main(argv = process.argv.slice(2)) {
133
+ const args = new Set(argv);
134
+ const summary = readCoverageSummary();
135
+ if (!summary) {
136
+ console.log('=== coverage-report-summary ===');
137
+ console.log('No coverage/coverage-summary.json found — run `npm run test:coverage` first.');
138
+ return 0;
139
+ }
140
+ const floors = readRatchetFloors();
141
+ if (!floors) {
142
+ console.log('=== coverage-report-summary ===');
143
+ console.log('Could not parse jest.config.js coverageThreshold.global — skipping comparison.');
144
+ return 0;
145
+ }
146
+ const rows = buildRows(summary, floors);
147
+ if (args.has('--json')) {
148
+ console.log(JSON.stringify({ rows, floors }, null, 2));
149
+ return 0;
150
+ }
151
+ console.log('=== Coverage Report (Story 10.19 ratchet) ===');
152
+ console.log(formatAsciiTable(rows));
153
+ appendToGithubSummary(formatMarkdownTable(rows));
154
+ return 0;
155
+ }
156
+
157
+ if (require.main === module) {
158
+ process.exitCode = main();
159
+ }
160
+
161
+ module.exports = {
162
+ readCoverageSummary,
163
+ readRatchetFloors,
164
+ buildRows,
165
+ formatAsciiTable,
166
+ formatMarkdownTable,
167
+ appendToGithubSummary,
168
+ main,
169
+ };
@@ -274,9 +274,13 @@ async function generateManifest() {
274
274
  fileEntries.sort((a, b) => a.path.localeCompare(b.path));
275
275
 
276
276
  // Build manifest object
277
+ // Story 10.27 — `generated_at` removed from the manifest body to keep
278
+ // the file deterministic across regenerations. Without removal, every
279
+ // post-commit hook regen produced a new timestamp -> new file content
280
+ // -> recurring "M install-manifest.yaml" churn in git status. Consumers
281
+ // (post-install-validator) treat the field as optional metadata.
277
282
  const manifest = {
278
283
  version: version,
279
- generated_at: new Date().toISOString(),
280
284
  generator: 'scripts/generate-install-manifest.js',
281
285
  file_count: fileEntries.length,
282
286
  files: fileEntries,
@@ -318,7 +322,7 @@ async function writeManifest(manifest) {
318
322
  console.log(`\nManifest written to: ${manifestPath}`);
319
323
  console.log(` Version: ${manifest.version}`);
320
324
  console.log(` Files: ${manifest.file_count}`);
321
- console.log(` Generated: ${manifest.generated_at}`);
325
+ console.log(` Generated: ${new Date().toISOString()}`);
322
326
 
323
327
  // Also compute and display manifest hash for integrity verification
324
328
  const manifestHash = hashString(yamlContent);
@@ -0,0 +1,169 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * release-readiness — Story 10.29
4
+ *
5
+ * Aggregates every validator and quality gate built throughout Epic 10.0
6
+ * into one release-readiness report. Run before opening a release PR or
7
+ * tagging v10.0.0 to confirm the framework is shippable.
8
+ *
9
+ * Validators executed (in order):
10
+ * 1. lint — npm run lint
11
+ * 2. typecheck — npm run typecheck
12
+ * 3. agents — npm run validate:agents
13
+ * 4. squad-orqx — npm run validate:squad-orqx (Story 10.28)
14
+ * 5. story-meta — npm run validate:story-meta (Story 10.19)
15
+ * 6. no-external-refs — npm run validate:no-external-refs (Story 10.17)
16
+ * 7. parity — npm run validate:parity (Story 10.18)
17
+ * 8. manifest — npm run validate:manifest
18
+ * 9. install-docs — npm run validate:docs
19
+ *
20
+ * Each gate runs in its own subprocess. Failures are reported but do NOT
21
+ * short-circuit — the script always runs every gate so the operator sees
22
+ * the full picture in one pass.
23
+ *
24
+ * Exit codes:
25
+ * 0 every gate passed
26
+ * 1 one or more gates failed (per-gate detail in the summary table)
27
+ *
28
+ * Usage:
29
+ * node scripts/release-readiness.js
30
+ * node scripts/release-readiness.js --json
31
+ * node scripts/release-readiness.js --quiet
32
+ */
33
+
34
+ 'use strict';
35
+
36
+ const path = require('path');
37
+ const { spawnSync } = require('child_process');
38
+
39
+ const PROJECT_ROOT = path.resolve(__dirname, '..');
40
+
41
+ const GATES = [
42
+ { id: 'lint', name: 'ESLint', cmd: ['npm', 'run', 'lint', '--silent'] },
43
+ { id: 'typecheck', name: 'TypeScript', cmd: ['npm', 'run', 'typecheck', '--silent'] },
44
+ { id: 'agents', name: 'Core agents', cmd: ['npm', 'run', 'validate:agents', '--silent'] },
45
+ { id: 'squad-orqx', name: 'Squad orqx (10.28)', cmd: ['npm', 'run', 'validate:squad-orqx', '--silent'] },
46
+ { id: 'story-meta', name: 'Story meta (10.19)', cmd: ['npm', 'run', 'validate:story-meta', '--silent'] },
47
+ { id: 'no-external-refs', name: 'External refs (10.17)', cmd: ['npm', 'run', 'validate:no-external-refs', '--silent'] },
48
+ { id: 'parity', name: 'Cross-IDE parity (10.18)', cmd: ['npm', 'run', 'validate:parity', '--silent'] },
49
+ { id: 'manifest', name: 'Install manifest', cmd: ['npm', 'run', 'validate:manifest', '--silent'] },
50
+ { id: 'install-docs', name: 'Install docs', cmd: ['npm', 'run', 'validate:docs', '--silent'] },
51
+ ];
52
+
53
+ function parseArgs(argv = process.argv.slice(2)) {
54
+ const args = new Set(argv);
55
+ return {
56
+ json: args.has('--json'),
57
+ quiet: args.has('--quiet') || args.has('-q'),
58
+ };
59
+ }
60
+
61
+ function runGate(gate) {
62
+ const start = Date.now();
63
+ const result = spawnSync(gate.cmd[0], gate.cmd.slice(1), {
64
+ cwd: PROJECT_ROOT,
65
+ encoding: 'utf8',
66
+ shell: process.platform === 'win32',
67
+ });
68
+ const elapsed = Date.now() - start;
69
+ return {
70
+ id: gate.id,
71
+ name: gate.name,
72
+ status: result.status === 0 ? 'PASS' : 'FAIL',
73
+ exitCode: result.status,
74
+ elapsedMs: elapsed,
75
+ stderr: result.stderr ? result.stderr.split('\n').slice(-5).join('\n') : '',
76
+ };
77
+ }
78
+
79
+ function runAllGates(gates = GATES) {
80
+ return gates.map((g) => runGate(g));
81
+ }
82
+
83
+ function summarize(results) {
84
+ return {
85
+ total: results.length,
86
+ pass: results.filter((r) => r.status === 'PASS').length,
87
+ fail: results.filter((r) => r.status === 'FAIL').length,
88
+ elapsedMs: results.reduce((sum, r) => sum + r.elapsedMs, 0),
89
+ };
90
+ }
91
+
92
+ function formatTable(results) {
93
+ const lines = [];
94
+ const widths = [22, 8, 8, 6];
95
+ const sep = '+' + widths.map((w) => '-'.repeat(w + 2)).join('+') + '+';
96
+ lines.push(sep);
97
+ lines.push(
98
+ '| '
99
+ + 'Gate'.padEnd(widths[0])
100
+ + ' | '
101
+ + 'Status'.padEnd(widths[1])
102
+ + ' | '
103
+ + 'Time'.padEnd(widths[2])
104
+ + ' | '
105
+ + 'Exit'.padEnd(widths[3])
106
+ + ' |',
107
+ );
108
+ lines.push(sep);
109
+ for (const r of results) {
110
+ lines.push(
111
+ '| '
112
+ + r.name.padEnd(widths[0])
113
+ + ' | '
114
+ + r.status.padEnd(widths[1])
115
+ + ' | '
116
+ + `${r.elapsedMs}ms`.padEnd(widths[2])
117
+ + ' | '
118
+ + String(r.exitCode).padEnd(widths[3])
119
+ + ' |',
120
+ );
121
+ }
122
+ lines.push(sep);
123
+ return lines.join('\n');
124
+ }
125
+
126
+ function main(argv = process.argv.slice(2)) {
127
+ const args = parseArgs(argv);
128
+ if (!args.quiet && !args.json) {
129
+ console.log('=== release-readiness ===');
130
+ console.log('Running all release gates (this can take a few minutes)...');
131
+ console.log('');
132
+ }
133
+ const results = runAllGates();
134
+ const summary = summarize(results);
135
+
136
+ if (args.json) {
137
+ console.log(JSON.stringify({ results, summary }, null, 2));
138
+ } else if (!args.quiet) {
139
+ console.log(formatTable(results));
140
+ console.log('');
141
+ console.log(
142
+ `Summary: ${summary.total} gates — ${summary.pass} pass, ${summary.fail} fail (${summary.elapsedMs}ms total)`,
143
+ );
144
+ if (summary.fail > 0) {
145
+ console.log('');
146
+ console.log('Failed gates (last 5 lines of stderr):');
147
+ for (const r of results.filter((x) => x.status === 'FAIL')) {
148
+ console.log(`\n--- ${r.name} ---`);
149
+ console.log(r.stderr || '(no stderr)');
150
+ }
151
+ }
152
+ }
153
+
154
+ return summary.fail > 0 ? 1 : 0;
155
+ }
156
+
157
+ if (require.main === module) {
158
+ process.exitCode = main();
159
+ }
160
+
161
+ module.exports = {
162
+ parseArgs,
163
+ GATES,
164
+ runGate,
165
+ runAllGates,
166
+ summarize,
167
+ formatTable,
168
+ main,
169
+ };
@@ -0,0 +1,153 @@
1
+ #!/usr/bin/env bash
2
+ # Story A.5 - Local install matrix helper
3
+ #
4
+ # Best-effort local validation of the install matrix. You can only fully
5
+ # validate the OS you are currently running on — the other 2 OSes are
6
+ # covered by the GitHub Actions workflow `.github/workflows/install-matrix.yml`
7
+ # on release PRs.
8
+ #
9
+ # Usage:
10
+ # bash scripts/test-install-matrix-local.sh # runs all PMs x methods available locally
11
+ # bash scripts/test-install-matrix-local.sh --pm npm # limit to one PM
12
+ # bash scripts/test-install-matrix-local.sh --method global
13
+ # bash scripts/test-install-matrix-local.sh --only npm:global,pnpm:local
14
+ #
15
+ # What it does:
16
+ # 1. Packs the current repo with `npm pack` into a tarball
17
+ # 2. For each selected (pm, method) combo, creates a scratch dir and runs
18
+ # the SAME combo runner used by CI: .github/workflows/install-matrix/run-combo.sh
19
+ # 3. Prints a summary table of local results
20
+ #
21
+ # What it does NOT do:
22
+ # - Run on OSes other than the current one
23
+ # - Replace the CI workflow (the gate for rc -> latest promotion)
24
+
25
+ set -u
26
+
27
+ REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
28
+ cd "$REPO_ROOT"
29
+
30
+ # Defaults
31
+ FILTER_PM=""
32
+ FILTER_METHOD=""
33
+ ONLY=""
34
+
35
+ while [ $# -gt 0 ]; do
36
+ case "$1" in
37
+ --pm) FILTER_PM="$2"; shift 2 ;;
38
+ --method) FILTER_METHOD="$2"; shift 2 ;;
39
+ --only) ONLY="$2"; shift 2 ;;
40
+ -h|--help)
41
+ sed -n '2,30p' "$0"
42
+ exit 0
43
+ ;;
44
+ *)
45
+ echo "Unknown arg: $1" >&2
46
+ exit 2
47
+ ;;
48
+ esac
49
+ done
50
+
51
+ # Detect OS (for informational purposes only)
52
+ OS_KIND="unknown"
53
+ case "$(uname -s 2>/dev/null || echo Windows)" in
54
+ Linux*) OS_KIND="linux" ;;
55
+ Darwin*) OS_KIND="macos" ;;
56
+ MINGW*|CYGWIN*|MSYS*|Windows*) OS_KIND="windows" ;;
57
+ esac
58
+
59
+ echo "=== Local install matrix helper ==="
60
+ echo "OS: $OS_KIND"
61
+ echo "Repo: $REPO_ROOT"
62
+ echo "Node: $(node --version 2>/dev/null || echo 'NOT FOUND')"
63
+ echo "npm: $(npm --version 2>/dev/null || echo 'NOT FOUND')"
64
+ echo "pnpm: $(pnpm --version 2>/dev/null || echo 'NOT INSTALLED (skipped)')"
65
+ echo "yarn: $(yarn --version 2>/dev/null || echo 'NOT INSTALLED (skipped)')"
66
+ echo
67
+
68
+ # Build tarball once
69
+ echo "[1/3] Packing candidate tarball..."
70
+ TARBALL_REL=$(npm pack --silent 2>/dev/null | tail -n1)
71
+ if [ -z "$TARBALL_REL" ] || [ ! -f "$TARBALL_REL" ]; then
72
+ echo "ERROR: failed to pack candidate" >&2
73
+ exit 1
74
+ fi
75
+ TARBALL="$REPO_ROOT/$TARBALL_REL"
76
+ echo " tarball: $TARBALL"
77
+ echo
78
+
79
+ # Enumerate combos
80
+ ALL_PMS="npm pnpm yarn"
81
+ ALL_METHODS="global npx local"
82
+ RESULTS=()
83
+
84
+ should_run() {
85
+ local pm="$1" method="$2"
86
+ if [ -n "$FILTER_PM" ] && [ "$pm" != "$FILTER_PM" ]; then return 1; fi
87
+ if [ -n "$FILTER_METHOD" ] && [ "$method" != "$FILTER_METHOD" ]; then return 1; fi
88
+ if [ -n "$ONLY" ]; then
89
+ case ",$ONLY," in
90
+ *,"$pm:$method",*) return 0 ;;
91
+ *) return 1 ;;
92
+ esac
93
+ fi
94
+ return 0
95
+ }
96
+
97
+ has_pm() {
98
+ command -v "$1" >/dev/null 2>&1
99
+ }
100
+
101
+ echo "[2/3] Running combos..."
102
+ TMP_BASE="$(mktemp -d 2>/dev/null || mktemp -d -t install-matrix)"
103
+ trap 'rm -rf "$TMP_BASE"' EXIT
104
+
105
+ for pm in $ALL_PMS; do
106
+ if ! has_pm "$pm"; then
107
+ echo " skip $pm/* — $pm not installed locally"
108
+ continue
109
+ fi
110
+ for method in $ALL_METHODS; do
111
+ if ! should_run "$pm" "$method"; then continue; fi
112
+ echo " -> $pm / $method"
113
+ SM_PM="$pm" \
114
+ SM_METHOD="$method" \
115
+ SM_TARBALL="$TARBALL" \
116
+ SM_TEST_DIR="$TMP_BASE/$pm-$method" \
117
+ bash "$REPO_ROOT/.github/workflows/install-matrix/run-combo.sh"
118
+ code=$?
119
+ if [ $code -eq 0 ]; then
120
+ RESULTS+=("PASS|$pm|$method")
121
+ else
122
+ RESULTS+=("FAIL|$pm|$method")
123
+ fi
124
+ echo
125
+ done
126
+ done
127
+
128
+ echo "[3/3] Local matrix summary ($OS_KIND):"
129
+ printf " %-6s %-6s %-8s %s\n" "STATUS" "PM" "METHOD" ""
130
+ printf " %-6s %-6s %-8s %s\n" "------" "----" "------" ""
131
+ PASS_COUNT=0
132
+ FAIL_COUNT=0
133
+ for row in "${RESULTS[@]:-}"; do
134
+ IFS='|' read -r status pm method <<<"$row"
135
+ printf " %-6s %-6s %-8s\n" "$status" "$pm" "$method"
136
+ case "$status" in
137
+ PASS) PASS_COUNT=$((PASS_COUNT+1)) ;;
138
+ FAIL) FAIL_COUNT=$((FAIL_COUNT+1)) ;;
139
+ esac
140
+ done
141
+ echo
142
+ echo " PASS: $PASS_COUNT FAIL: $FAIL_COUNT"
143
+ echo
144
+ echo "NOTE: Local runs validate only $OS_KIND. The full 27-combo gate runs in CI"
145
+ echo " via .github/workflows/install-matrix.yml on release PRs."
146
+
147
+ # Cleanup tarball
148
+ rm -f "$TARBALL" 2>/dev/null || true
149
+
150
+ if [ $FAIL_COUNT -gt 0 ]; then
151
+ exit 1
152
+ fi
153
+ exit 0