aios-core 4.2.14 → 4.3.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 (288) hide show
  1. package/.aios-core/cli/commands/validate/index.js +1 -1
  2. package/.aios-core/core/code-intel/helpers/creation-helper.js +183 -0
  3. package/.aios-core/core/code-intel/helpers/devops-helper.js +166 -0
  4. package/.aios-core/core/code-intel/helpers/planning-helper.js +248 -0
  5. package/.aios-core/core/code-intel/helpers/qa-helper.js +187 -0
  6. package/.aios-core/core/code-intel/helpers/story-helper.js +146 -0
  7. package/.aios-core/core/config/schemas/framework-config.schema.json +155 -7
  8. package/.aios-core/core/config/schemas/project-config.schema.json +329 -15
  9. package/.aios-core/core/config/template-overrides.js +84 -0
  10. package/.aios-core/core/docs/troubleshooting-guide.md +1 -1
  11. package/.aios-core/core/doctor/checks/agent-memory.js +63 -0
  12. package/.aios-core/core/doctor/checks/claude-md.js +56 -0
  13. package/.aios-core/core/doctor/checks/code-intel.js +57 -0
  14. package/.aios-core/core/doctor/checks/commands-count.js +81 -0
  15. package/.aios-core/core/doctor/checks/core-config.js +53 -0
  16. package/.aios-core/core/doctor/checks/entity-registry.js +53 -0
  17. package/.aios-core/core/doctor/checks/git-hooks.js +50 -0
  18. package/.aios-core/core/doctor/checks/graph-dashboard.js +48 -0
  19. package/.aios-core/core/doctor/checks/hooks-claude-count.js +107 -0
  20. package/.aios-core/core/doctor/checks/ide-sync.js +68 -0
  21. package/.aios-core/core/doctor/checks/index.js +46 -0
  22. package/.aios-core/core/doctor/checks/node-version.js +33 -0
  23. package/.aios-core/core/doctor/checks/npm-packages.js +35 -0
  24. package/.aios-core/core/doctor/checks/rules-files.js +61 -0
  25. package/.aios-core/core/doctor/checks/settings-json.js +121 -0
  26. package/.aios-core/core/doctor/checks/skills-count.js +72 -0
  27. package/.aios-core/core/doctor/fix-handler.js +165 -0
  28. package/.aios-core/core/doctor/formatters/json.js +14 -0
  29. package/.aios-core/core/doctor/formatters/text.js +59 -0
  30. package/.aios-core/core/doctor/index.js +94 -0
  31. package/.aios-core/core/graph-dashboard/cli.js +361 -0
  32. package/.aios-core/core/graph-dashboard/data-sources/code-intel-source.js +234 -0
  33. package/.aios-core/core/graph-dashboard/data-sources/metrics-source.js +95 -0
  34. package/.aios-core/core/graph-dashboard/data-sources/registry-source.js +106 -0
  35. package/.aios-core/core/graph-dashboard/formatters/dot-formatter.js +45 -0
  36. package/.aios-core/core/graph-dashboard/formatters/html-formatter.js +1437 -0
  37. package/.aios-core/core/graph-dashboard/formatters/json-formatter.js +13 -0
  38. package/.aios-core/core/graph-dashboard/formatters/mermaid-formatter.js +59 -0
  39. package/.aios-core/core/graph-dashboard/index.js +21 -0
  40. package/.aios-core/core/graph-dashboard/renderers/stats-renderer.js +217 -0
  41. package/.aios-core/core/graph-dashboard/renderers/status-renderer.js +125 -0
  42. package/.aios-core/core/graph-dashboard/renderers/tree-renderer.js +119 -0
  43. package/.aios-core/core/health-check/base-check.js +1 -1
  44. package/.aios-core/core/health-check/check-registry.js +1 -1
  45. package/.aios-core/core/health-check/checks/deployment/build-config.js +1 -1
  46. package/.aios-core/core/health-check/checks/deployment/ci-config.js +1 -1
  47. package/.aios-core/core/health-check/checks/deployment/deployment-readiness.js +1 -1
  48. package/.aios-core/core/health-check/checks/deployment/docker-config.js +1 -1
  49. package/.aios-core/core/health-check/checks/deployment/env-file.js +1 -1
  50. package/.aios-core/core/health-check/checks/deployment/index.js +1 -1
  51. package/.aios-core/core/health-check/checks/index.js +1 -1
  52. package/.aios-core/core/health-check/checks/local/disk-space.js +1 -1
  53. package/.aios-core/core/health-check/checks/local/environment-vars.js +1 -1
  54. package/.aios-core/core/health-check/checks/local/git-install.js +1 -1
  55. package/.aios-core/core/health-check/checks/local/ide-detection.js +1 -1
  56. package/.aios-core/core/health-check/checks/local/index.js +1 -1
  57. package/.aios-core/core/health-check/checks/local/memory.js +1 -1
  58. package/.aios-core/core/health-check/checks/local/network.js +1 -1
  59. package/.aios-core/core/health-check/checks/local/npm-install.js +1 -1
  60. package/.aios-core/core/health-check/checks/local/shell-environment.js +1 -1
  61. package/.aios-core/core/health-check/checks/project/agent-config.js +1 -1
  62. package/.aios-core/core/health-check/checks/project/aios-directory.js +1 -1
  63. package/.aios-core/core/health-check/checks/project/dependencies.js +1 -1
  64. package/.aios-core/core/health-check/checks/project/framework-config.js +1 -1
  65. package/.aios-core/core/health-check/checks/project/index.js +1 -1
  66. package/.aios-core/core/health-check/checks/project/node-version.js +1 -1
  67. package/.aios-core/core/health-check/checks/project/package-json.js +1 -1
  68. package/.aios-core/core/health-check/checks/project/task-definitions.js +1 -1
  69. package/.aios-core/core/health-check/checks/project/workflow-dependencies.js +1 -1
  70. package/.aios-core/core/health-check/checks/repository/branch-protection.js +1 -1
  71. package/.aios-core/core/health-check/checks/repository/commit-history.js +1 -1
  72. package/.aios-core/core/health-check/checks/repository/conflicts.js +1 -1
  73. package/.aios-core/core/health-check/checks/repository/git-repo.js +1 -1
  74. package/.aios-core/core/health-check/checks/repository/git-status.js +1 -1
  75. package/.aios-core/core/health-check/checks/repository/gitignore.js +1 -1
  76. package/.aios-core/core/health-check/checks/repository/index.js +1 -1
  77. package/.aios-core/core/health-check/checks/repository/large-files.js +1 -1
  78. package/.aios-core/core/health-check/checks/repository/lockfile-integrity.js +1 -1
  79. package/.aios-core/core/health-check/checks/services/api-endpoints.js +1 -1
  80. package/.aios-core/core/health-check/checks/services/claude-code.js +1 -1
  81. package/.aios-core/core/health-check/checks/services/gemini-cli.js +1 -1
  82. package/.aios-core/core/health-check/checks/services/github-cli.js +1 -1
  83. package/.aios-core/core/health-check/checks/services/index.js +1 -1
  84. package/.aios-core/core/health-check/checks/services/mcp-integration.js +1 -1
  85. package/.aios-core/core/health-check/engine.js +1 -1
  86. package/.aios-core/core/health-check/healers/backup-manager.js +1 -1
  87. package/.aios-core/core/health-check/healers/index.js +1 -1
  88. package/.aios-core/core/health-check/index.js +9 -2
  89. package/.aios-core/core/health-check/reporters/console.js +1 -1
  90. package/.aios-core/core/health-check/reporters/index.js +1 -1
  91. package/.aios-core/core/health-check/reporters/json.js +1 -1
  92. package/.aios-core/core/health-check/reporters/markdown.js +1 -1
  93. package/.aios-core/core/ids/layer-classifier.js +65 -0
  94. package/.aios-core/core/ids/registry-updater.js +49 -0
  95. package/.aios-core/core/index.esm.js +1 -1
  96. package/.aios-core/core/index.js +1 -1
  97. package/.aios-core/core/session/context-detector.js +2 -7
  98. package/.aios-core/core/synapse/context/context-tracker.js +9 -1
  99. package/.aios-core/core/synapse/engine.js +33 -13
  100. package/.aios-core/core/synapse/runtime/hook-runtime.js +40 -2
  101. package/.aios-core/core/synapse/session/session-manager.js +3 -2
  102. package/.aios-core/core/synapse/utils/atomic-write.js +79 -0
  103. package/.aios-core/core-config.yaml +34 -1
  104. package/.aios-core/data/aios-kb.md +2 -2
  105. package/.aios-core/data/capability-detection.js +290 -0
  106. package/.aios-core/data/entity-registry.yaml +10424 -2127
  107. package/.aios-core/data/mcp-discipline.js +166 -0
  108. package/.aios-core/data/mcp-tool-examples.yaml +215 -0
  109. package/.aios-core/data/tok2-validation.js +168 -0
  110. package/.aios-core/data/tok3-token-comparison.js +123 -0
  111. package/.aios-core/data/tool-registry.yaml +648 -0
  112. package/.aios-core/data/tool-search-validation.js +174 -0
  113. package/.aios-core/development/agents/analyst/MEMORY.md +33 -0
  114. package/.aios-core/development/agents/architect/MEMORY.md +39 -0
  115. package/.aios-core/development/agents/data-engineer/MEMORY.md +32 -0
  116. package/.aios-core/development/agents/dev/MEMORY.md +46 -0
  117. package/.aios-core/development/agents/dev.md +1 -1
  118. package/.aios-core/development/agents/devops/MEMORY.md +39 -0
  119. package/.aios-core/development/agents/devops.md +22 -0
  120. package/.aios-core/development/agents/pm/MEMORY.md +38 -0
  121. package/.aios-core/development/agents/po/MEMORY.md +45 -0
  122. package/.aios-core/development/agents/qa/MEMORY.md +42 -0
  123. package/.aios-core/development/agents/qa.md +1 -1
  124. package/.aios-core/development/agents/sm/MEMORY.md +31 -0
  125. package/.aios-core/development/agents/ux/MEMORY.md +31 -0
  126. package/.aios-core/development/checklists/issue-triage-checklist.md +35 -0
  127. package/.aios-core/development/checklists/memory-audit-checklist.md +53 -0
  128. package/.aios-core/development/scripts/issue-triage.js +171 -0
  129. package/.aios-core/development/scripts/populate-entity-registry.js +412 -19
  130. package/.aios-core/development/scripts/unified-activation-pipeline.js +31 -10
  131. package/.aios-core/development/tasks/analyze-project-structure.md +48 -0
  132. package/.aios-core/development/tasks/brownfield-create-epic.md +41 -0
  133. package/.aios-core/development/tasks/create-doc.md +44 -0
  134. package/.aios-core/development/tasks/create-next-story.md +10 -0
  135. package/.aios-core/development/tasks/dev-develop-story.md +1 -1
  136. package/.aios-core/development/tasks/github-devops-github-pr-automation.md +49 -0
  137. package/.aios-core/development/tasks/github-devops-pre-push-quality-gate.md +63 -0
  138. package/.aios-core/development/tasks/github-issue-triage.md +118 -0
  139. package/.aios-core/development/tasks/health-check.yaml +206 -171
  140. package/.aios-core/development/tasks/kb-mode-interaction.md +3 -3
  141. package/.aios-core/development/tasks/plan-create-context.md +47 -1
  142. package/.aios-core/development/tasks/plan-create-implementation.md +55 -0
  143. package/.aios-core/development/tasks/pr-automation.md +5 -5
  144. package/.aios-core/development/tasks/qa-gate.md +48 -0
  145. package/.aios-core/development/tasks/qa-review-story.md +24 -1
  146. package/.aios-core/development/tasks/resolve-github-issue.md +608 -0
  147. package/.aios-core/development/tasks/review-contributor-pr.md +152 -0
  148. package/.aios-core/development/tasks/setup-llm-routing.md +1 -1
  149. package/.aios-core/development/tasks/spec-research-dependencies.md +4 -0
  150. package/.aios-core/development/tasks/triage-github-issues.md +356 -0
  151. package/.aios-core/development/tasks/validate-agents.md +4 -0
  152. package/.aios-core/development/tasks/validate-next-story.md +10 -0
  153. package/.aios-core/development/templates/agent-handoff-tmpl.yaml +48 -0
  154. package/.aios-core/development/templates/code-intel-integration-pattern.md +199 -0
  155. package/.aios-core/development/templates/ptc-entity-validation.md +113 -0
  156. package/.aios-core/development/templates/ptc-qa-gate.md +100 -0
  157. package/.aios-core/development/templates/ptc-research-aggregation.md +94 -0
  158. package/.aios-core/development/templates/service-template/README.md.hbs +158 -158
  159. package/.aios-core/development/templates/service-template/__tests__/index.test.ts.hbs +237 -237
  160. package/.aios-core/development/templates/service-template/client.ts.hbs +403 -403
  161. package/.aios-core/development/templates/service-template/errors.ts.hbs +182 -182
  162. package/.aios-core/development/templates/service-template/index.ts.hbs +120 -120
  163. package/.aios-core/development/templates/service-template/package.json.hbs +87 -87
  164. package/.aios-core/development/templates/service-template/types.ts.hbs +145 -145
  165. package/.aios-core/development/templates/squad/agent-template.md +11 -0
  166. package/.aios-core/development/templates/squad/task-template.md +21 -0
  167. package/.aios-core/development/templates/squad-template/LICENSE +21 -21
  168. package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.1-COMPLETE.md +1 -1
  169. package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.2-SUMMARY.md +1 -1
  170. package/.aios-core/framework-config.yaml +8 -0
  171. package/.aios-core/index.esm.js +1 -1
  172. package/.aios-core/index.js +1 -1
  173. package/.aios-core/infrastructure/integrations/ai-providers/index.js +1 -1
  174. package/.aios-core/infrastructure/schemas/task-v3-schema.json +6 -0
  175. package/.aios-core/infrastructure/scripts/collect-tool-usage.js +311 -0
  176. package/.aios-core/infrastructure/scripts/generate-optimization-report.js +497 -0
  177. package/.aios-core/infrastructure/scripts/generate-settings-json.js +300 -0
  178. package/.aios-core/infrastructure/scripts/git-config-detector.js +65 -9
  179. package/.aios-core/infrastructure/scripts/ide-sync/index.js +3 -1
  180. package/.aios-core/infrastructure/scripts/ide-sync/transformers/github-copilot.js +184 -0
  181. package/.aios-core/infrastructure/scripts/repository-detector.js +3 -3
  182. package/.aios-core/infrastructure/templates/aios-sync.yaml.template +182 -182
  183. package/.aios-core/infrastructure/templates/coderabbit.yaml.template +279 -279
  184. package/.aios-core/infrastructure/templates/github-workflows/ci.yml.template +169 -169
  185. package/.aios-core/infrastructure/templates/github-workflows/pr-automation.yml.template +330 -330
  186. package/.aios-core/infrastructure/templates/github-workflows/release.yml.template +196 -196
  187. package/.aios-core/infrastructure/templates/gitignore/gitignore-aios-base.tmpl +63 -63
  188. package/.aios-core/infrastructure/templates/gitignore/gitignore-brownfield-merge.tmpl +18 -18
  189. package/.aios-core/infrastructure/templates/gitignore/gitignore-node.tmpl +85 -85
  190. package/.aios-core/infrastructure/templates/gitignore/gitignore-python.tmpl +145 -145
  191. package/.aios-core/install-manifest.yaml +541 -249
  192. package/.aios-core/lib/build.json +1 -0
  193. package/.aios-core/local-config.yaml.template +71 -71
  194. package/.aios-core/monitor/hooks/lib/__init__.py +1 -1
  195. package/.aios-core/monitor/hooks/lib/enrich.py +58 -58
  196. package/.aios-core/monitor/hooks/lib/send_event.py +47 -47
  197. package/.aios-core/monitor/hooks/notification.py +29 -29
  198. package/.aios-core/monitor/hooks/post_tool_use.py +45 -45
  199. package/.aios-core/monitor/hooks/pre_compact.py +29 -29
  200. package/.aios-core/monitor/hooks/pre_tool_use.py +40 -40
  201. package/.aios-core/monitor/hooks/stop.py +29 -29
  202. package/.aios-core/monitor/hooks/subagent_stop.py +29 -29
  203. package/.aios-core/monitor/hooks/user_prompt_submit.py +38 -38
  204. package/.aios-core/product/templates/adr.hbs +125 -125
  205. package/.aios-core/product/templates/dbdr.hbs +241 -241
  206. package/.aios-core/product/templates/epic.hbs +212 -212
  207. package/.aios-core/product/templates/ide-rules/claude-rules.md +77 -0
  208. package/.aios-core/product/templates/pmdr.hbs +186 -186
  209. package/.aios-core/product/templates/prd-v2.0.hbs +216 -216
  210. package/.aios-core/product/templates/prd.hbs +201 -201
  211. package/.aios-core/product/templates/story.hbs +263 -263
  212. package/.aios-core/product/templates/task.hbs +170 -170
  213. package/.aios-core/product/templates/tmpl-comment-on-examples.sql +158 -158
  214. package/.aios-core/product/templates/tmpl-migration-script.sql +91 -91
  215. package/.aios-core/product/templates/tmpl-rls-granular-policies.sql +104 -104
  216. package/.aios-core/product/templates/tmpl-rls-kiss-policy.sql +10 -10
  217. package/.aios-core/product/templates/tmpl-rls-roles.sql +135 -135
  218. package/.aios-core/product/templates/tmpl-rls-simple.sql +77 -77
  219. package/.aios-core/product/templates/tmpl-rls-tenant.sql +152 -152
  220. package/.aios-core/product/templates/tmpl-rollback-script.sql +77 -77
  221. package/.aios-core/product/templates/tmpl-seed-data.sql +140 -140
  222. package/.aios-core/product/templates/tmpl-smoke-test.sql +16 -16
  223. package/.aios-core/product/templates/tmpl-staging-copy-merge.sql +139 -139
  224. package/.aios-core/product/templates/tmpl-stored-proc.sql +140 -140
  225. package/.aios-core/product/templates/tmpl-trigger.sql +152 -152
  226. package/.aios-core/product/templates/tmpl-view-materialized.sql +133 -133
  227. package/.aios-core/product/templates/tmpl-view.sql +177 -177
  228. package/.aios-core/scripts/pm.sh +0 -0
  229. package/.aios-core/user-guide.md +15 -15
  230. package/.aios-core/utils/filters/constants.js +10 -0
  231. package/.aios-core/utils/filters/content-filter.js +223 -0
  232. package/.aios-core/utils/filters/field-filter.js +126 -0
  233. package/.aios-core/utils/filters/index.js +180 -0
  234. package/.aios-core/utils/filters/schema-filter.js +157 -0
  235. package/.claude/CLAUDE.md +62 -0
  236. package/.claude/hooks/enforce-architecture-first.py +196 -196
  237. package/.claude/hooks/enforce-git-push-authority.sh +33 -0
  238. package/.claude/hooks/mind-clone-governance.py +192 -192
  239. package/.claude/hooks/read-protection.py +151 -151
  240. package/.claude/hooks/slug-validation.py +176 -176
  241. package/.claude/hooks/sql-governance.py +182 -182
  242. package/.claude/hooks/synapse-engine.cjs +28 -5
  243. package/.claude/hooks/write-path-validation.py +194 -194
  244. package/.claude/rules/agent-authority.md +105 -0
  245. package/.claude/rules/agent-handoff.md +97 -0
  246. package/.claude/rules/agent-memory-imports.md +15 -0
  247. package/.claude/rules/coderabbit-integration.md +101 -0
  248. package/.claude/rules/ids-principles.md +119 -0
  249. package/.claude/rules/story-lifecycle.md +145 -0
  250. package/.claude/rules/tool-examples.md +64 -0
  251. package/.claude/rules/tool-response-filtering.md +57 -0
  252. package/.claude/rules/workflow-execution.md +150 -0
  253. package/LICENSE +33 -33
  254. package/bin/aios-graph.js +9 -0
  255. package/bin/aios-init.js +2 -2
  256. package/bin/aios-minimal.js +0 -0
  257. package/bin/aios.js +17 -221
  258. package/bin/utils/detect-fsmonitor.js +70 -0
  259. package/bin/utils/framework-guard.js +238 -0
  260. package/bin/utils/validate-publish.js +108 -0
  261. package/package.json +6 -3
  262. package/packages/aios-install/bin/aios-install.js +0 -0
  263. package/packages/aios-install/bin/edmcp.js +0 -0
  264. package/packages/aios-pro-cli/bin/aios-pro.js +2 -0
  265. package/packages/installer/src/installer/brownfield-upgrader.js +68 -5
  266. package/packages/installer/src/merger/index.js +3 -0
  267. package/packages/installer/src/merger/strategies/index.js +6 -0
  268. package/packages/installer/src/merger/strategies/yaml-merger.js +181 -0
  269. package/packages/installer/src/updater/index.js +4 -4
  270. package/packages/installer/src/wizard/i18n.js +321 -3
  271. package/packages/installer/src/wizard/ide-config-generator.js +152 -25
  272. package/packages/installer/src/wizard/index.js +119 -1
  273. package/packages/installer/src/wizard/pro-setup.js +137 -121
  274. package/packages/installer/tests/unit/artifact-copy-pipeline/artifact-copy-pipeline.test.js +261 -0
  275. package/packages/installer/tests/unit/claude-md-template-v5/claude-md-template-v5.test.js +192 -0
  276. package/packages/installer/tests/unit/doctor/doctor-checks.test.js +551 -0
  277. package/packages/installer/tests/unit/doctor/doctor-orchestrator.test.js +134 -0
  278. package/packages/installer/tests/unit/entity-registry-bootstrap.test.js +186 -0
  279. package/packages/installer/tests/unit/generate-settings-json/generate-settings-json.test.js +309 -0
  280. package/packages/installer/tests/unit/ide-sync-integration/ide-sync-integration.test.js +230 -0
  281. package/packages/installer/tests/unit/merger/strategies.test.js +2 -2
  282. package/packages/installer/tests/unit/merger/yaml-merger.test.js +327 -0
  283. package/scripts/check-markdown-links.py +352 -352
  284. package/scripts/dashboard-parallel-dev.sh +0 -0
  285. package/scripts/dashboard-parallel-phase3.sh +0 -0
  286. package/scripts/dashboard-parallel-phase4.sh +0 -0
  287. package/scripts/install-monitor-hooks.sh +0 -0
  288. package/scripts/package-synapse.js +2 -1
@@ -0,0 +1,186 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Entity Registry Bootstrap Tests (Story INS-4.6)
5
+ *
6
+ * Validates that the installer calls populate-entity-registry.js during install,
7
+ * handles failures gracefully, and that aios doctor can verify the registry.
8
+ */
9
+
10
+ const fs = require('fs');
11
+ const path = require('path');
12
+
13
+ const WIZARD_PATH = path.join(__dirname, '..', '..', 'src', 'wizard', 'index.js');
14
+ const POPULATE_SCRIPT = path.join(
15
+ __dirname, '..', '..', '..', '..', '.aios-core', 'development', 'scripts', 'populate-entity-registry.js'
16
+ );
17
+ const DOCTOR_CHECK = path.join(
18
+ __dirname, '..', '..', '..', '..', '.aios-core', 'core', 'doctor', 'checks', 'entity-registry.js'
19
+ );
20
+ const REGISTRY_PATH = path.join(
21
+ __dirname, '..', '..', '..', '..', '.aios-core', 'data', 'entity-registry.yaml'
22
+ );
23
+ const PRE_PUSH_HOOK = path.join(__dirname, '..', '..', '..', '..', '.husky', 'pre-push');
24
+ const IDS_PRE_PUSH = path.join(
25
+ __dirname, '..', '..', '..', '..', '.aios-core', 'hooks', 'ids-pre-push.js'
26
+ );
27
+
28
+ describe('Entity Registry Bootstrap (Story INS-4.6)', () => {
29
+ let wizardSource;
30
+
31
+ beforeAll(() => {
32
+ wizardSource = fs.readFileSync(WIZARD_PATH, 'utf8');
33
+ });
34
+
35
+ describe('AC1: Bootstrap called during install', () => {
36
+ test('wizard calls populate-entity-registry.js', () => {
37
+ expect(wizardSource).toContain('populate-entity-registry.js');
38
+ expect(wizardSource).toContain('Bootstrapping entity registry');
39
+ });
40
+
41
+ test('bootstrap runs after .aios-core/ copy (injection order)', () => {
42
+ const aiosCoreIdx = wizardSource.indexOf('AIOS core installed');
43
+ const bootstrapIdx = wizardSource.indexOf('Bootstrapping entity registry');
44
+ const envConfigIdx = wizardSource.indexOf('Configuring environment');
45
+
46
+ // Bootstrap must come after aios-core install
47
+ expect(bootstrapIdx).toBeGreaterThan(aiosCoreIdx);
48
+ // Bootstrap must come before environment configuration
49
+ expect(bootstrapIdx).toBeLessThan(envConfigIdx);
50
+ });
51
+
52
+ test('bootstrap has try/catch — failure does not abort install', () => {
53
+ // Verify the bootstrap block is wrapped in try/catch
54
+ expect(wizardSource).toContain("answers.entityRegistryStatus = 'failed'");
55
+ expect(wizardSource).toContain('Entity registry bootstrap failed');
56
+ // Should warn, not throw
57
+ expect(wizardSource).toContain("run 'aios doctor' post-install");
58
+ });
59
+
60
+ test('bootstrap uses 30s timeout guard', () => {
61
+ expect(wizardSource).toContain('timeout: 30000');
62
+ });
63
+
64
+ test('bootstrap reports entity count on success', () => {
65
+ expect(wizardSource).toContain("answers.entityRegistryStatus = 'populated'");
66
+ expect(wizardSource).toContain('answers.entityRegistryCount');
67
+ expect(wizardSource).toContain('answers.entityRegistryMs');
68
+ });
69
+
70
+ test('bootstrap handles missing script gracefully', () => {
71
+ expect(wizardSource).toContain("answers.entityRegistryStatus = 'skipped'");
72
+ expect(wizardSource).toContain('Entity registry script not found');
73
+ });
74
+ });
75
+
76
+ describe('AC2: Sanity check (relative threshold)', () => {
77
+ test('aios doctor entity-registry check exists', () => {
78
+ expect(fs.existsSync(DOCTOR_CHECK)).toBe(true);
79
+ });
80
+
81
+ test('doctor check uses relative validation (file exists + non-empty), not fixed threshold', () => {
82
+ const checkSource = fs.readFileSync(DOCTOR_CHECK, 'utf8');
83
+
84
+ // Should check file existence
85
+ expect(checkSource).toContain('existsSync');
86
+ // Should NOT have hardcoded threshold like >= 500
87
+ expect(checkSource).not.toMatch(/>= ?\d{3}/);
88
+ // Should report line count (relative measure)
89
+ expect(checkSource).toContain('lineCount');
90
+ });
91
+
92
+ test('doctor check validates recency (mtime)', () => {
93
+ const checkSource = fs.readFileSync(DOCTOR_CHECK, 'utf8');
94
+ expect(checkSource).toContain('mtimeMs');
95
+ expect(checkSource).toContain('MAX_AGE_MS');
96
+ });
97
+ });
98
+
99
+ describe('AC3: No duplication with pre-push hook', () => {
100
+ test('pre-push hook calls ids-pre-push.js (incremental), not populate script', () => {
101
+ const hookContent = fs.readFileSync(PRE_PUSH_HOOK, 'utf8');
102
+ expect(hookContent).toContain('ids-pre-push.js');
103
+ expect(hookContent).not.toContain('populate-entity-registry.js');
104
+ });
105
+
106
+ test('ids-pre-push.js uses RegistryUpdater.processChanges (incremental)', () => {
107
+ const idsSource = fs.readFileSync(IDS_PRE_PUSH, 'utf8');
108
+ expect(idsSource).toContain('RegistryUpdater');
109
+ expect(idsSource).toContain('processChanges');
110
+ });
111
+
112
+ test('bootstrap uses populate-entity-registry.js (full scan), distinct from incremental', () => {
113
+ // Wizard calls populate-entity-registry.js
114
+ expect(wizardSource).toContain('populate-entity-registry.js');
115
+ // Wizard does NOT call ids-pre-push.js
116
+ expect(wizardSource).not.toContain('ids-pre-push.js');
117
+ });
118
+ });
119
+
120
+ describe('AC4: Performance guard', () => {
121
+ test('populate-entity-registry.js exists and is executable', () => {
122
+ expect(fs.existsSync(POPULATE_SCRIPT)).toBe(true);
123
+ });
124
+
125
+ test('populate script has programmatic API (module.exports)', () => {
126
+ const scriptSource = fs.readFileSync(POPULATE_SCRIPT, 'utf8');
127
+ expect(scriptSource).toContain('module.exports');
128
+ expect(scriptSource).toContain('populate');
129
+ });
130
+
131
+ test('measured runtime is well under 15s threshold', () => {
132
+ // Run the actual script and measure time
133
+ const { execSync } = require('child_process');
134
+ const projectRoot = path.join(__dirname, '..', '..', '..', '..');
135
+ const start = Date.now();
136
+
137
+ try {
138
+ execSync(`node "${POPULATE_SCRIPT}"`, {
139
+ cwd: projectRoot,
140
+ encoding: 'utf8',
141
+ timeout: 30000,
142
+ stdio: 'pipe',
143
+ });
144
+ } catch {
145
+ // Script may fail in some environments — that's ok for timing test
146
+ console.log('SKIP: populate script execution failed — timing not measured');
147
+ return;
148
+ }
149
+
150
+ const elapsed = Date.now() - start;
151
+ // Must be under 15s (AC4 threshold)
152
+ expect(elapsed).toBeLessThan(15000);
153
+ console.log(`Measured runtime: ${(elapsed / 1000).toFixed(2)}s`);
154
+ });
155
+ });
156
+
157
+ describe('AC5: Post-bootstrap verification', () => {
158
+ test('entity-registry.yaml exists after bootstrap', () => {
159
+ expect(fs.existsSync(REGISTRY_PATH)).toBe(true);
160
+ });
161
+
162
+ test('entity-registry.yaml has at least 1 entity (non-empty)', () => {
163
+ const content = fs.readFileSync(REGISTRY_PATH, 'utf8');
164
+ const match = content.match(/entityCount:\s*(\d+)/);
165
+ expect(match).not.toBeNull();
166
+ const count = parseInt(match[1], 10);
167
+ expect(count).toBeGreaterThan(0);
168
+ });
169
+
170
+ // NOTE: This test depends on AC4 "measured runtime" test running first,
171
+ // which executes populate-entity-registry.js and refreshes the file mtime.
172
+ test('entity-registry.yaml updatedAt is recent (within 5 minutes)', () => {
173
+ const stat = fs.statSync(REGISTRY_PATH);
174
+ const ageMs = Date.now() - stat.mtimeMs;
175
+ const FIVE_MINUTES = 5 * 60 * 1000;
176
+ expect(ageMs).toBeLessThan(FIVE_MINUTES);
177
+ });
178
+
179
+ test('aios doctor entity-registry check passes on current registry', async () => {
180
+ const { run } = require(DOCTOR_CHECK);
181
+ const projectRoot = path.join(__dirname, '..', '..', '..', '..');
182
+ const result = await run({ projectRoot });
183
+ expect(result.status).toBe('PASS');
184
+ });
185
+ });
186
+ });
@@ -0,0 +1,309 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const os = require('os');
6
+
7
+ const {
8
+ generate,
9
+ validateBoundaryPath,
10
+ readBoundaryConfig,
11
+ expandProtectedPaths,
12
+ expandExceptionPaths,
13
+ generatePermissions,
14
+ writeSettingsJson,
15
+ } = require('../../../../../.aios-core/infrastructure/scripts/generate-settings-json');
16
+
17
+ function createTempProject(boundary, existingSettings) {
18
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gen-settings-'));
19
+
20
+ // Create core-config.yaml with boundary section
21
+ const aiosCoreDir = path.join(tmpDir, '.aios-core');
22
+ fs.mkdirSync(aiosCoreDir, { recursive: true });
23
+
24
+ const yamlContent = [
25
+ 'boundary:',
26
+ ` frameworkProtection: ${boundary.frameworkProtection}`,
27
+ ' protected:',
28
+ ...boundary.protected.map(p => ` - ${p}`),
29
+ ' exceptions:',
30
+ ...boundary.exceptions.map(p => ` - ${p}`),
31
+ ].join('\n') + '\n';
32
+
33
+ fs.writeFileSync(path.join(tmpDir, '.aios-core', 'core-config.yaml'), yamlContent, 'utf8');
34
+
35
+ // Create directory structure for expansion tests
36
+ if (boundary.protected.includes('.aios-core/core/**')) {
37
+ const coreDir = path.join(tmpDir, '.aios-core', 'core');
38
+ fs.mkdirSync(coreDir, { recursive: true });
39
+ fs.mkdirSync(path.join(coreDir, 'utils'), { recursive: true });
40
+ fs.mkdirSync(path.join(coreDir, 'events'), { recursive: true });
41
+ fs.writeFileSync(path.join(coreDir, 'index.js'), '', 'utf8');
42
+ }
43
+
44
+ // Create .claude directory and optionally existing settings
45
+ const claudeDir = path.join(tmpDir, '.claude');
46
+ fs.mkdirSync(claudeDir, { recursive: true });
47
+
48
+ if (existingSettings) {
49
+ fs.writeFileSync(
50
+ path.join(claudeDir, 'settings.json'),
51
+ JSON.stringify(existingSettings, null, 2) + '\n',
52
+ 'utf8'
53
+ );
54
+ }
55
+
56
+ return tmpDir;
57
+ }
58
+
59
+ function cleanupTempProject(tmpDir) {
60
+ fs.rmSync(tmpDir, { recursive: true, force: true });
61
+ }
62
+
63
+ describe('generate-settings-json', () => {
64
+ describe('readBoundaryConfig', () => {
65
+ test('reads boundary config from core-config.yaml', () => {
66
+ const tmpDir = createTempProject({
67
+ frameworkProtection: true,
68
+ protected: ['.aios-core/core/**', 'bin/aios.js'],
69
+ exceptions: ['.aios-core/data/**'],
70
+ });
71
+
72
+ try {
73
+ const config = readBoundaryConfig(tmpDir);
74
+
75
+ expect(config.frameworkProtection).toBe(true);
76
+ expect(config.protected).toContain('.aios-core/core/**');
77
+ expect(config.protected).toContain('bin/aios.js');
78
+ expect(config.exceptions).toContain('.aios-core/data/**');
79
+ } finally {
80
+ cleanupTempProject(tmpDir);
81
+ }
82
+ });
83
+
84
+ test('throws when core-config.yaml not found', () => {
85
+ expect(() => readBoundaryConfig('/nonexistent/path')).toThrow('core-config.yaml not found');
86
+ });
87
+
88
+ test('rejects path traversal in protected paths', () => {
89
+ const tmpDir = createTempProject({
90
+ frameworkProtection: true,
91
+ protected: ['../../etc/passwd'],
92
+ exceptions: [],
93
+ });
94
+
95
+ try {
96
+ expect(() => readBoundaryConfig(tmpDir)).toThrow('Path traversal detected');
97
+ } finally {
98
+ cleanupTempProject(tmpDir);
99
+ }
100
+ });
101
+
102
+ test('rejects absolute paths in boundary config', () => {
103
+ const tmpDir = createTempProject({
104
+ frameworkProtection: true,
105
+ protected: ['/etc/passwd'],
106
+ exceptions: [],
107
+ });
108
+
109
+ try {
110
+ expect(() => readBoundaryConfig(tmpDir)).toThrow('Absolute path not allowed');
111
+ } finally {
112
+ cleanupTempProject(tmpDir);
113
+ }
114
+ });
115
+ });
116
+
117
+ describe('generatePermissions — frameworkProtection: true', () => {
118
+ test('generates deny rules covering all protected paths', () => {
119
+ const tmpDir = createTempProject({
120
+ frameworkProtection: true,
121
+ protected: ['.aios-core/core/**', '.aios-core/infrastructure/**', 'bin/aios.js'],
122
+ exceptions: ['.aios-core/data/**'],
123
+ });
124
+
125
+ // Create infrastructure dir (no expansion for non-core paths)
126
+ fs.mkdirSync(path.join(tmpDir, '.aios-core', 'infrastructure'), { recursive: true });
127
+
128
+ try {
129
+ const boundary = readBoundaryConfig(tmpDir);
130
+ const permissions = generatePermissions(boundary, tmpDir);
131
+
132
+ // Should have deny rules for core subdirs (events/**, utils/**, index.js) + infrastructure/** + bin/aios.js
133
+ expect(permissions.deny.length).toBeGreaterThan(0);
134
+
135
+ // Core expansion: events/**, utils/**, index.js → 6 deny rules (3 paths x 2 tools)
136
+ expect(permissions.deny).toContain('Edit(.aios-core/core/events/**)');
137
+ expect(permissions.deny).toContain('Write(.aios-core/core/events/**)');
138
+ expect(permissions.deny).toContain('Edit(.aios-core/core/utils/**)');
139
+ expect(permissions.deny).toContain('Write(.aios-core/core/utils/**)');
140
+ expect(permissions.deny).toContain('Edit(.aios-core/core/index.js)');
141
+ expect(permissions.deny).toContain('Write(.aios-core/core/index.js)');
142
+
143
+ // Non-core paths stay as globs
144
+ expect(permissions.deny).toContain('Edit(.aios-core/infrastructure/**)');
145
+ expect(permissions.deny).toContain('Write(.aios-core/infrastructure/**)');
146
+ expect(permissions.deny).toContain('Edit(bin/aios.js)');
147
+ expect(permissions.deny).toContain('Write(bin/aios.js)');
148
+
149
+ // Allow rules from exceptions
150
+ expect(permissions.allow).toContain('Edit(.aios-core/data/**)');
151
+ expect(permissions.allow).toContain('Write(.aios-core/data/**)');
152
+ expect(permissions.allow).toContain('Read(.aios-core/**)');
153
+ } finally {
154
+ cleanupTempProject(tmpDir);
155
+ }
156
+ });
157
+
158
+ test('all 9 protected paths from core-config produce deny rules', () => {
159
+ const projectRoot = path.resolve(__dirname, '../../../../..');
160
+ const boundary = readBoundaryConfig(projectRoot);
161
+ // Force frameworkProtection: true for this test (core-config may have it disabled for contributor mode)
162
+ boundary.frameworkProtection = true;
163
+ const permissions = generatePermissions(boundary, projectRoot);
164
+
165
+ // Verify all 9 config paths are covered
166
+ const protectedRoots = [
167
+ '.aios-core/core/',
168
+ '.aios-core/development/tasks/',
169
+ '.aios-core/development/templates/',
170
+ '.aios-core/development/checklists/',
171
+ '.aios-core/development/workflows/',
172
+ '.aios-core/infrastructure/',
173
+ '.aios-core/constitution.md',
174
+ 'bin/aios.js',
175
+ 'bin/aios-init.js',
176
+ ];
177
+
178
+ for (const root of protectedRoots) {
179
+ const hasDenyRule = permissions.deny.some(r => r.includes(root));
180
+ expect(hasDenyRule).toBe(true);
181
+ }
182
+
183
+ // Verify deny rules use only Edit and Write (no MultiEdit)
184
+ for (const rule of permissions.deny) {
185
+ expect(rule).toMatch(/^(Edit|Write)\(/);
186
+ }
187
+ });
188
+ });
189
+
190
+ describe('generatePermissions — frameworkProtection: false', () => {
191
+ test('produces no boundary deny rules', () => {
192
+ const boundary = {
193
+ frameworkProtection: false,
194
+ protected: ['.aios-core/core/**', '.aios-core/infrastructure/**'],
195
+ exceptions: ['.aios-core/data/**'],
196
+ };
197
+
198
+ const permissions = generatePermissions(boundary, '/tmp');
199
+
200
+ expect(permissions.deny).toEqual([]);
201
+ expect(permissions.allow).toEqual([]);
202
+ });
203
+ });
204
+
205
+ describe('idempotency', () => {
206
+ test('running generator twice produces identical output', () => {
207
+ const tmpDir = createTempProject({
208
+ frameworkProtection: true,
209
+ protected: ['.aios-core/core/**', 'bin/aios.js'],
210
+ exceptions: ['.aios-core/data/**'],
211
+ });
212
+
213
+ try {
214
+ // First run
215
+ generate(tmpDir);
216
+ const firstRun = fs.readFileSync(path.join(tmpDir, '.claude', 'settings.json'), 'utf8');
217
+
218
+ // Second run
219
+ generate(tmpDir);
220
+ const secondRun = fs.readFileSync(path.join(tmpDir, '.claude', 'settings.json'), 'utf8');
221
+
222
+ expect(firstRun).toBe(secondRun);
223
+ } finally {
224
+ cleanupTempProject(tmpDir);
225
+ }
226
+ });
227
+
228
+ test('JSON output is valid and parseable', () => {
229
+ const tmpDir = createTempProject({
230
+ frameworkProtection: true,
231
+ protected: ['.aios-core/core/**'],
232
+ exceptions: ['.aios-core/data/**'],
233
+ });
234
+
235
+ try {
236
+ generate(tmpDir);
237
+ const content = fs.readFileSync(path.join(tmpDir, '.claude', 'settings.json'), 'utf8');
238
+ const parsed = JSON.parse(content);
239
+
240
+ expect(parsed).toHaveProperty('permissions');
241
+ expect(parsed.permissions).toHaveProperty('deny');
242
+ expect(parsed.permissions).toHaveProperty('allow');
243
+ expect(Array.isArray(parsed.permissions.deny)).toBe(true);
244
+ expect(Array.isArray(parsed.permissions.allow)).toBe(true);
245
+ } finally {
246
+ cleanupTempProject(tmpDir);
247
+ }
248
+ });
249
+ });
250
+
251
+ describe('section preservation', () => {
252
+ test('preserves user-set language key after generator run', () => {
253
+ const tmpDir = createTempProject(
254
+ {
255
+ frameworkProtection: true,
256
+ protected: ['bin/aios.js'],
257
+ exceptions: [],
258
+ },
259
+ { language: 'pt', customSetting: true }
260
+ );
261
+
262
+ try {
263
+ generate(tmpDir);
264
+ const content = fs.readFileSync(path.join(tmpDir, '.claude', 'settings.json'), 'utf8');
265
+ const parsed = JSON.parse(content);
266
+
267
+ expect(parsed.language).toBe('pt');
268
+ expect(parsed.customSetting).toBe(true);
269
+ expect(parsed.permissions).toBeDefined();
270
+ expect(parsed.permissions.deny.length).toBeGreaterThan(0);
271
+ } finally {
272
+ cleanupTempProject(tmpDir);
273
+ }
274
+ });
275
+
276
+ test('frameworkProtection false preserves user settings and removes permissions', () => {
277
+ const tmpDir = createTempProject(
278
+ {
279
+ frameworkProtection: false,
280
+ protected: ['bin/aios.js'],
281
+ exceptions: [],
282
+ },
283
+ { language: 'pt', permissions: { deny: ['old-rule'], allow: [] } }
284
+ );
285
+
286
+ try {
287
+ generate(tmpDir);
288
+ const content = fs.readFileSync(path.join(tmpDir, '.claude', 'settings.json'), 'utf8');
289
+ const parsed = JSON.parse(content);
290
+
291
+ expect(parsed.language).toBe('pt');
292
+ expect(parsed.permissions).toBeUndefined();
293
+ } finally {
294
+ cleanupTempProject(tmpDir);
295
+ }
296
+ });
297
+ });
298
+
299
+ describe('CLI entry point', () => {
300
+ test('module exports required functions', () => {
301
+ expect(typeof generate).toBe('function');
302
+ expect(typeof readBoundaryConfig).toBe('function');
303
+ expect(typeof expandProtectedPaths).toBe('function');
304
+ expect(typeof expandExceptionPaths).toBe('function');
305
+ expect(typeof generatePermissions).toBe('function');
306
+ expect(typeof writeSettingsJson).toBe('function');
307
+ });
308
+ });
309
+ });