aios-core 4.2.15 → 4.4.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 (329) hide show
  1. package/.aios-core/cli/commands/validate/index.js +1 -1
  2. package/.aios-core/core/code-intel/code-intel-client.js +19 -5
  3. package/.aios-core/core/code-intel/helpers/creation-helper.js +183 -0
  4. package/.aios-core/core/code-intel/helpers/devops-helper.js +166 -0
  5. package/.aios-core/core/code-intel/helpers/planning-helper.js +248 -0
  6. package/.aios-core/core/code-intel/helpers/qa-helper.js +187 -0
  7. package/.aios-core/core/code-intel/helpers/story-helper.js +146 -0
  8. package/.aios-core/core/code-intel/hook-runtime.js +186 -0
  9. package/.aios-core/core/code-intel/index.js +2 -0
  10. package/.aios-core/core/code-intel/providers/code-graph-provider.js +8 -0
  11. package/.aios-core/core/code-intel/providers/provider-interface.js +9 -0
  12. package/.aios-core/core/code-intel/providers/registry-provider.js +515 -0
  13. package/.aios-core/core/config/schemas/framework-config.schema.json +155 -7
  14. package/.aios-core/core/config/schemas/project-config.schema.json +329 -15
  15. package/.aios-core/core/config/template-overrides.js +84 -0
  16. package/.aios-core/core/docs/troubleshooting-guide.md +1 -1
  17. package/.aios-core/core/doctor/checks/agent-memory.js +63 -0
  18. package/.aios-core/core/doctor/checks/claude-md.js +56 -0
  19. package/.aios-core/core/doctor/checks/code-intel.js +131 -0
  20. package/.aios-core/core/doctor/checks/commands-count.js +81 -0
  21. package/.aios-core/core/doctor/checks/core-config.js +53 -0
  22. package/.aios-core/core/doctor/checks/entity-registry.js +53 -0
  23. package/.aios-core/core/doctor/checks/git-hooks.js +50 -0
  24. package/.aios-core/core/doctor/checks/graph-dashboard.js +48 -0
  25. package/.aios-core/core/doctor/checks/hooks-claude-count.js +118 -0
  26. package/.aios-core/core/doctor/checks/ide-sync.js +85 -0
  27. package/.aios-core/core/doctor/checks/index.js +46 -0
  28. package/.aios-core/core/doctor/checks/node-version.js +33 -0
  29. package/.aios-core/core/doctor/checks/npm-packages.js +35 -0
  30. package/.aios-core/core/doctor/checks/rules-files.js +61 -0
  31. package/.aios-core/core/doctor/checks/settings-json.js +121 -0
  32. package/.aios-core/core/doctor/checks/skills-count.js +72 -0
  33. package/.aios-core/core/doctor/fix-handler.js +165 -0
  34. package/.aios-core/core/doctor/formatters/json.js +14 -0
  35. package/.aios-core/core/doctor/formatters/text.js +59 -0
  36. package/.aios-core/core/doctor/index.js +94 -0
  37. package/.aios-core/core/graph-dashboard/cli.js +361 -0
  38. package/.aios-core/core/graph-dashboard/data-sources/code-intel-source.js +234 -0
  39. package/.aios-core/core/graph-dashboard/data-sources/metrics-source.js +95 -0
  40. package/.aios-core/core/graph-dashboard/data-sources/registry-source.js +106 -0
  41. package/.aios-core/core/graph-dashboard/formatters/dot-formatter.js +45 -0
  42. package/.aios-core/core/graph-dashboard/formatters/html-formatter.js +1437 -0
  43. package/.aios-core/core/graph-dashboard/formatters/json-formatter.js +13 -0
  44. package/.aios-core/core/graph-dashboard/formatters/mermaid-formatter.js +59 -0
  45. package/.aios-core/core/graph-dashboard/index.js +21 -0
  46. package/.aios-core/core/graph-dashboard/renderers/stats-renderer.js +217 -0
  47. package/.aios-core/core/graph-dashboard/renderers/status-renderer.js +125 -0
  48. package/.aios-core/core/graph-dashboard/renderers/tree-renderer.js +119 -0
  49. package/.aios-core/core/health-check/base-check.js +1 -1
  50. package/.aios-core/core/health-check/check-registry.js +1 -1
  51. package/.aios-core/core/health-check/checks/deployment/build-config.js +1 -1
  52. package/.aios-core/core/health-check/checks/deployment/ci-config.js +1 -1
  53. package/.aios-core/core/health-check/checks/deployment/deployment-readiness.js +1 -1
  54. package/.aios-core/core/health-check/checks/deployment/docker-config.js +1 -1
  55. package/.aios-core/core/health-check/checks/deployment/env-file.js +1 -1
  56. package/.aios-core/core/health-check/checks/deployment/index.js +1 -1
  57. package/.aios-core/core/health-check/checks/index.js +1 -1
  58. package/.aios-core/core/health-check/checks/local/disk-space.js +1 -1
  59. package/.aios-core/core/health-check/checks/local/environment-vars.js +1 -1
  60. package/.aios-core/core/health-check/checks/local/git-install.js +1 -1
  61. package/.aios-core/core/health-check/checks/local/ide-detection.js +1 -1
  62. package/.aios-core/core/health-check/checks/local/index.js +1 -1
  63. package/.aios-core/core/health-check/checks/local/memory.js +1 -1
  64. package/.aios-core/core/health-check/checks/local/network.js +1 -1
  65. package/.aios-core/core/health-check/checks/local/npm-install.js +1 -1
  66. package/.aios-core/core/health-check/checks/local/shell-environment.js +1 -1
  67. package/.aios-core/core/health-check/checks/project/agent-config.js +1 -1
  68. package/.aios-core/core/health-check/checks/project/aios-directory.js +1 -1
  69. package/.aios-core/core/health-check/checks/project/dependencies.js +1 -1
  70. package/.aios-core/core/health-check/checks/project/framework-config.js +1 -1
  71. package/.aios-core/core/health-check/checks/project/index.js +1 -1
  72. package/.aios-core/core/health-check/checks/project/node-version.js +1 -1
  73. package/.aios-core/core/health-check/checks/project/package-json.js +1 -1
  74. package/.aios-core/core/health-check/checks/project/task-definitions.js +1 -1
  75. package/.aios-core/core/health-check/checks/project/workflow-dependencies.js +1 -1
  76. package/.aios-core/core/health-check/checks/repository/branch-protection.js +1 -1
  77. package/.aios-core/core/health-check/checks/repository/commit-history.js +1 -1
  78. package/.aios-core/core/health-check/checks/repository/conflicts.js +1 -1
  79. package/.aios-core/core/health-check/checks/repository/git-repo.js +1 -1
  80. package/.aios-core/core/health-check/checks/repository/git-status.js +1 -1
  81. package/.aios-core/core/health-check/checks/repository/gitignore.js +1 -1
  82. package/.aios-core/core/health-check/checks/repository/index.js +1 -1
  83. package/.aios-core/core/health-check/checks/repository/large-files.js +1 -1
  84. package/.aios-core/core/health-check/checks/repository/lockfile-integrity.js +1 -1
  85. package/.aios-core/core/health-check/checks/services/api-endpoints.js +1 -1
  86. package/.aios-core/core/health-check/checks/services/claude-code.js +1 -1
  87. package/.aios-core/core/health-check/checks/services/gemini-cli.js +1 -1
  88. package/.aios-core/core/health-check/checks/services/github-cli.js +1 -1
  89. package/.aios-core/core/health-check/checks/services/index.js +1 -1
  90. package/.aios-core/core/health-check/checks/services/mcp-integration.js +1 -1
  91. package/.aios-core/core/health-check/engine.js +1 -1
  92. package/.aios-core/core/health-check/healers/backup-manager.js +1 -1
  93. package/.aios-core/core/health-check/healers/index.js +1 -1
  94. package/.aios-core/core/health-check/index.js +9 -2
  95. package/.aios-core/core/health-check/reporters/console.js +1 -1
  96. package/.aios-core/core/health-check/reporters/index.js +1 -1
  97. package/.aios-core/core/health-check/reporters/json.js +1 -1
  98. package/.aios-core/core/health-check/reporters/markdown.js +1 -1
  99. package/.aios-core/core/ids/layer-classifier.js +65 -0
  100. package/.aios-core/core/ids/registry-updater.js +49 -0
  101. package/.aios-core/core/index.esm.js +1 -1
  102. package/.aios-core/core/index.js +1 -1
  103. package/.aios-core/core/session/context-detector.js +2 -7
  104. package/.aios-core/core/synapse/context/context-tracker.js +9 -1
  105. package/.aios-core/core/synapse/engine.js +33 -13
  106. package/.aios-core/core/synapse/memory/memory-bridge.js +17 -43
  107. package/.aios-core/core/synapse/memory/synapse-memory-provider.js +201 -0
  108. package/.aios-core/core/synapse/runtime/hook-runtime.js +40 -2
  109. package/.aios-core/core/synapse/session/session-manager.js +3 -2
  110. package/.aios-core/core/synapse/utils/atomic-write.js +79 -0
  111. package/.aios-core/core-config.yaml +34 -1
  112. package/.aios-core/data/aios-kb.md +2 -2
  113. package/.aios-core/data/capability-detection.js +290 -0
  114. package/.aios-core/data/entity-registry.yaml +10450 -2129
  115. package/.aios-core/data/mcp-discipline.js +166 -0
  116. package/.aios-core/data/mcp-tool-examples.yaml +215 -0
  117. package/.aios-core/data/tok2-validation.js +168 -0
  118. package/.aios-core/data/tok3-token-comparison.js +123 -0
  119. package/.aios-core/data/tool-registry.yaml +648 -0
  120. package/.aios-core/data/tool-search-validation.js +174 -0
  121. package/.aios-core/data/workflow-chains.yaml +156 -0
  122. package/.aios-core/development/agents/aios-master.md +17 -10
  123. package/.aios-core/development/agents/analyst/MEMORY.md +33 -0
  124. package/.aios-core/development/agents/analyst.md +17 -10
  125. package/.aios-core/development/agents/architect/MEMORY.md +39 -0
  126. package/.aios-core/development/agents/architect.md +17 -10
  127. package/.aios-core/development/agents/data-engineer/MEMORY.md +32 -0
  128. package/.aios-core/development/agents/data-engineer.md +17 -10
  129. package/.aios-core/development/agents/dev/MEMORY.md +46 -0
  130. package/.aios-core/development/agents/dev.md +18 -11
  131. package/.aios-core/development/agents/devops/MEMORY.md +39 -0
  132. package/.aios-core/development/agents/devops.md +44 -10
  133. package/.aios-core/development/agents/pm/MEMORY.md +38 -0
  134. package/.aios-core/development/agents/pm.md +17 -10
  135. package/.aios-core/development/agents/po/MEMORY.md +45 -0
  136. package/.aios-core/development/agents/po.md +17 -10
  137. package/.aios-core/development/agents/qa/MEMORY.md +42 -0
  138. package/.aios-core/development/agents/qa.md +18 -11
  139. package/.aios-core/development/agents/sm/MEMORY.md +31 -0
  140. package/.aios-core/development/agents/sm.md +17 -10
  141. package/.aios-core/development/agents/squad-creator.md +18 -9
  142. package/.aios-core/development/agents/ux/MEMORY.md +31 -0
  143. package/.aios-core/development/agents/ux-design-expert.md +16 -9
  144. package/.aios-core/development/checklists/issue-triage-checklist.md +35 -0
  145. package/.aios-core/development/checklists/memory-audit-checklist.md +53 -0
  146. package/.aios-core/development/scripts/issue-triage.js +171 -0
  147. package/.aios-core/development/scripts/populate-entity-registry.js +412 -19
  148. package/.aios-core/development/scripts/unified-activation-pipeline.js +31 -10
  149. package/.aios-core/development/tasks/analyze-project-structure.md +48 -0
  150. package/.aios-core/development/tasks/apply-qa-fixes.md +7 -0
  151. package/.aios-core/development/tasks/architect-analyze-impact.md +8 -1
  152. package/.aios-core/development/tasks/brownfield-create-epic.md +41 -0
  153. package/.aios-core/development/tasks/brownfield-create-story.md +7 -0
  154. package/.aios-core/development/tasks/build-autonomous.md +7 -0
  155. package/.aios-core/development/tasks/create-deep-research-prompt.md +7 -0
  156. package/.aios-core/development/tasks/create-doc.md +44 -0
  157. package/.aios-core/development/tasks/create-next-story.md +17 -0
  158. package/.aios-core/development/tasks/create-suite.md +7 -0
  159. package/.aios-core/development/tasks/dev-develop-story.md +9 -1
  160. package/.aios-core/development/tasks/execute-checklist.md +7 -0
  161. package/.aios-core/development/tasks/github-devops-github-pr-automation.md +56 -0
  162. package/.aios-core/development/tasks/github-devops-pre-push-quality-gate.md +70 -0
  163. package/.aios-core/development/tasks/github-issue-triage.md +118 -0
  164. package/.aios-core/development/tasks/health-check.yaml +206 -171
  165. package/.aios-core/development/tasks/kb-mode-interaction.md +3 -3
  166. package/.aios-core/development/tasks/plan-create-context.md +47 -1
  167. package/.aios-core/development/tasks/plan-create-implementation.md +55 -0
  168. package/.aios-core/development/tasks/po-close-story.md +7 -0
  169. package/.aios-core/development/tasks/pr-automation.md +5 -5
  170. package/.aios-core/development/tasks/qa-create-fix-request.md +7 -0
  171. package/.aios-core/development/tasks/qa-fix-issues.md +7 -0
  172. package/.aios-core/development/tasks/qa-gate.md +56 -0
  173. package/.aios-core/development/tasks/qa-review-story.md +32 -1
  174. package/.aios-core/development/tasks/release-management.md +7 -0
  175. package/.aios-core/development/tasks/resolve-github-issue.md +608 -0
  176. package/.aios-core/development/tasks/review-contributor-pr.md +152 -0
  177. package/.aios-core/development/tasks/setup-llm-routing.md +1 -1
  178. package/.aios-core/development/tasks/spec-critique.md +8 -0
  179. package/.aios-core/development/tasks/spec-gather-requirements.md +7 -0
  180. package/.aios-core/development/tasks/spec-research-dependencies.md +4 -0
  181. package/.aios-core/development/tasks/spec-write-spec.md +5 -0
  182. package/.aios-core/development/tasks/triage-github-issues.md +356 -0
  183. package/.aios-core/development/tasks/validate-agents.md +4 -0
  184. package/.aios-core/development/tasks/validate-next-story.md +17 -0
  185. package/.aios-core/development/templates/agent-handoff-tmpl.yaml +48 -0
  186. package/.aios-core/development/templates/code-intel-integration-pattern.md +199 -0
  187. package/.aios-core/development/templates/ptc-entity-validation.md +113 -0
  188. package/.aios-core/development/templates/ptc-qa-gate.md +100 -0
  189. package/.aios-core/development/templates/ptc-research-aggregation.md +94 -0
  190. package/.aios-core/development/templates/service-template/README.md.hbs +158 -158
  191. package/.aios-core/development/templates/service-template/__tests__/index.test.ts.hbs +237 -237
  192. package/.aios-core/development/templates/service-template/client.ts.hbs +403 -403
  193. package/.aios-core/development/templates/service-template/errors.ts.hbs +182 -182
  194. package/.aios-core/development/templates/service-template/index.ts.hbs +120 -120
  195. package/.aios-core/development/templates/service-template/package.json.hbs +87 -87
  196. package/.aios-core/development/templates/service-template/types.ts.hbs +145 -145
  197. package/.aios-core/development/templates/squad/agent-template.md +11 -0
  198. package/.aios-core/development/templates/squad/task-template.md +21 -0
  199. package/.aios-core/development/templates/squad-template/LICENSE +21 -21
  200. package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.1-COMPLETE.md +1 -1
  201. package/.aios-core/docs/standards/AIOS-LIVRO-DE-OURO-V2.2-SUMMARY.md +1 -1
  202. package/.aios-core/framework-config.yaml +8 -0
  203. package/.aios-core/index.esm.js +1 -1
  204. package/.aios-core/index.js +1 -1
  205. package/.aios-core/infrastructure/integrations/ai-providers/index.js +1 -1
  206. package/.aios-core/infrastructure/schemas/task-v3-schema.json +6 -0
  207. package/.aios-core/infrastructure/scripts/collect-tool-usage.js +311 -0
  208. package/.aios-core/infrastructure/scripts/generate-optimization-report.js +497 -0
  209. package/.aios-core/infrastructure/scripts/generate-settings-json.js +300 -0
  210. package/.aios-core/infrastructure/scripts/git-config-detector.js +65 -9
  211. package/.aios-core/infrastructure/scripts/ide-sync/index.js +3 -1
  212. package/.aios-core/infrastructure/scripts/ide-sync/transformers/github-copilot.js +184 -0
  213. package/.aios-core/infrastructure/scripts/repository-detector.js +3 -3
  214. package/.aios-core/infrastructure/templates/aios-sync.yaml.template +182 -182
  215. package/.aios-core/infrastructure/templates/coderabbit.yaml.template +279 -279
  216. package/.aios-core/infrastructure/templates/github-workflows/ci.yml.template +169 -169
  217. package/.aios-core/infrastructure/templates/github-workflows/pr-automation.yml.template +330 -330
  218. package/.aios-core/infrastructure/templates/github-workflows/release.yml.template +196 -196
  219. package/.aios-core/infrastructure/templates/gitignore/gitignore-aios-base.tmpl +63 -63
  220. package/.aios-core/infrastructure/templates/gitignore/gitignore-brownfield-merge.tmpl +18 -18
  221. package/.aios-core/infrastructure/templates/gitignore/gitignore-node.tmpl +85 -85
  222. package/.aios-core/infrastructure/templates/gitignore/gitignore-python.tmpl +145 -145
  223. package/.aios-core/install-manifest.yaml +613 -305
  224. package/.aios-core/lib/build.json +1 -0
  225. package/.aios-core/local-config.yaml.template +71 -71
  226. package/.aios-core/monitor/hooks/lib/__init__.py +1 -1
  227. package/.aios-core/monitor/hooks/lib/enrich.py +58 -58
  228. package/.aios-core/monitor/hooks/lib/send_event.py +47 -47
  229. package/.aios-core/monitor/hooks/notification.py +29 -29
  230. package/.aios-core/monitor/hooks/post_tool_use.py +45 -45
  231. package/.aios-core/monitor/hooks/pre_compact.py +29 -29
  232. package/.aios-core/monitor/hooks/pre_tool_use.py +40 -40
  233. package/.aios-core/monitor/hooks/stop.py +29 -29
  234. package/.aios-core/monitor/hooks/subagent_stop.py +29 -29
  235. package/.aios-core/monitor/hooks/user_prompt_submit.py +38 -38
  236. package/.aios-core/product/templates/adr.hbs +125 -125
  237. package/.aios-core/product/templates/dbdr.hbs +241 -241
  238. package/.aios-core/product/templates/epic.hbs +212 -212
  239. package/.aios-core/product/templates/ide-rules/claude-rules.md +125 -0
  240. package/.aios-core/product/templates/pmdr.hbs +186 -186
  241. package/.aios-core/product/templates/prd-v2.0.hbs +216 -216
  242. package/.aios-core/product/templates/prd.hbs +201 -201
  243. package/.aios-core/product/templates/story.hbs +263 -263
  244. package/.aios-core/product/templates/task.hbs +170 -170
  245. package/.aios-core/product/templates/tmpl-comment-on-examples.sql +158 -158
  246. package/.aios-core/product/templates/tmpl-migration-script.sql +91 -91
  247. package/.aios-core/product/templates/tmpl-rls-granular-policies.sql +104 -104
  248. package/.aios-core/product/templates/tmpl-rls-kiss-policy.sql +10 -10
  249. package/.aios-core/product/templates/tmpl-rls-roles.sql +135 -135
  250. package/.aios-core/product/templates/tmpl-rls-simple.sql +77 -77
  251. package/.aios-core/product/templates/tmpl-rls-tenant.sql +152 -152
  252. package/.aios-core/product/templates/tmpl-rollback-script.sql +77 -77
  253. package/.aios-core/product/templates/tmpl-seed-data.sql +140 -140
  254. package/.aios-core/product/templates/tmpl-smoke-test.sql +16 -16
  255. package/.aios-core/product/templates/tmpl-staging-copy-merge.sql +139 -139
  256. package/.aios-core/product/templates/tmpl-stored-proc.sql +140 -140
  257. package/.aios-core/product/templates/tmpl-trigger.sql +152 -152
  258. package/.aios-core/product/templates/tmpl-view-materialized.sql +133 -133
  259. package/.aios-core/product/templates/tmpl-view.sql +177 -177
  260. package/.aios-core/scripts/pm.sh +0 -0
  261. package/.aios-core/user-guide.md +15 -15
  262. package/.aios-core/utils/filters/constants.js +10 -0
  263. package/.aios-core/utils/filters/content-filter.js +223 -0
  264. package/.aios-core/utils/filters/field-filter.js +126 -0
  265. package/.aios-core/utils/filters/index.js +180 -0
  266. package/.aios-core/utils/filters/schema-filter.js +157 -0
  267. package/.claude/CLAUDE.md +62 -0
  268. package/.claude/hooks/enforce-architecture-first.py +196 -196
  269. package/.claude/hooks/enforce-git-push-authority.sh +33 -0
  270. package/.claude/hooks/mind-clone-governance.py +192 -192
  271. package/.claude/hooks/read-protection.py +151 -151
  272. package/.claude/hooks/slug-validation.py +176 -176
  273. package/.claude/hooks/sql-governance.py +182 -182
  274. package/.claude/hooks/synapse-engine.cjs +28 -5
  275. package/.claude/hooks/write-path-validation.py +194 -194
  276. package/.claude/rules/agent-authority.md +105 -0
  277. package/.claude/rules/agent-handoff.md +97 -0
  278. package/.claude/rules/agent-memory-imports.md +15 -0
  279. package/.claude/rules/coderabbit-integration.md +101 -0
  280. package/.claude/rules/ids-principles.md +119 -0
  281. package/.claude/rules/story-lifecycle.md +145 -0
  282. package/.claude/rules/tool-examples.md +64 -0
  283. package/.claude/rules/tool-response-filtering.md +57 -0
  284. package/.claude/rules/workflow-execution.md +150 -0
  285. package/LICENSE +33 -33
  286. package/bin/aios-graph.js +9 -0
  287. package/bin/aios-init.js +2 -2
  288. package/bin/aios-minimal.js +0 -0
  289. package/bin/aios.js +17 -221
  290. package/bin/utils/detect-fsmonitor.js +70 -0
  291. package/bin/utils/framework-guard.js +238 -0
  292. package/bin/utils/validate-publish.js +108 -0
  293. package/package.json +6 -3
  294. package/packages/aios-install/bin/aios-install.js +0 -0
  295. package/packages/aios-install/bin/edmcp.js +0 -0
  296. package/packages/aios-pro-cli/bin/aios-pro.js +2 -0
  297. package/packages/installer/src/config/templates/core-config-template.js +25 -0
  298. package/packages/installer/src/installer/brownfield-upgrader.js +68 -5
  299. package/packages/installer/src/merger/index.js +3 -0
  300. package/packages/installer/src/merger/strategies/index.js +6 -0
  301. package/packages/installer/src/merger/strategies/yaml-merger.js +181 -0
  302. package/packages/installer/src/updater/index.js +4 -4
  303. package/packages/installer/src/wizard/i18n.js +321 -3
  304. package/packages/installer/src/wizard/ide-config-generator.js +173 -25
  305. package/packages/installer/src/wizard/index.js +119 -1
  306. package/packages/installer/src/wizard/pro-setup.js +137 -121
  307. package/packages/installer/tests/unit/artifact-copy-pipeline/artifact-copy-pipeline.test.js +271 -0
  308. package/packages/installer/tests/unit/claude-md-template-v5/claude-md-template-v5.test.js +192 -0
  309. package/packages/installer/tests/unit/doctor/doctor-checks.test.js +610 -0
  310. package/packages/installer/tests/unit/doctor/doctor-orchestrator.test.js +134 -0
  311. package/packages/installer/tests/unit/entity-registry-bootstrap.test.js +186 -0
  312. package/packages/installer/tests/unit/generate-settings-json/generate-settings-json.test.js +309 -0
  313. package/packages/installer/tests/unit/ide-sync-integration/ide-sync-integration.test.js +230 -0
  314. package/packages/installer/tests/unit/merger/strategies.test.js +2 -2
  315. package/packages/installer/tests/unit/merger/yaml-merger.test.js +327 -0
  316. package/scripts/check-markdown-links.py +352 -352
  317. package/scripts/dashboard-parallel-dev.sh +0 -0
  318. package/scripts/dashboard-parallel-phase3.sh +0 -0
  319. package/scripts/dashboard-parallel-phase4.sh +0 -0
  320. package/scripts/install-monitor-hooks.sh +0 -0
  321. package/scripts/package-synapse.js +2 -1
  322. package/pro/README.md +0 -66
  323. package/pro/license/degradation.js +0 -220
  324. package/pro/license/errors.js +0 -450
  325. package/pro/license/feature-gate.js +0 -354
  326. package/pro/license/index.js +0 -181
  327. package/pro/license/license-api.js +0 -651
  328. package/pro/license/license-cache.js +0 -523
  329. package/pro/license/license-crypto.js +0 -303
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Unit Tests: Doctor Orchestrator
3
+ * Story INS-4.1: aios doctor rewrite
4
+ *
5
+ * Tests for options forwarding, output format, and fix/dry-run behavior.
6
+ */
7
+
8
+ const path = require('path');
9
+
10
+ // Use real modules for orchestrator testing (checks will hit real filesystem)
11
+ const { runDoctorChecks, DOCTOR_VERSION } = require('../../../../../.aios-core/core/doctor');
12
+
13
+ const projectRoot = path.resolve(__dirname, '..', '..', '..', '..', '..');
14
+
15
+ describe('Doctor Orchestrator', () => {
16
+ describe('version', () => {
17
+ it('should export DOCTOR_VERSION as 2.0.0', () => {
18
+ expect(DOCTOR_VERSION).toBe('2.0.0');
19
+ });
20
+ });
21
+
22
+ describe('options forwarding (AC1)', () => {
23
+ it('should accept and use options object', async () => {
24
+ const result = await runDoctorChecks({ projectRoot });
25
+ expect(result).toHaveProperty('formatted');
26
+ expect(result).toHaveProperty('data');
27
+ expect(result.data).toHaveProperty('version', '2.0.0');
28
+ expect(result.data).toHaveProperty('summary');
29
+ expect(result.data).toHaveProperty('checks');
30
+ });
31
+
32
+ it('should produce JSON when json option is true', async () => {
33
+ const result = await runDoctorChecks({ json: true, projectRoot });
34
+ expect(result.formatted).toBeTruthy();
35
+
36
+ // Should be valid JSON
37
+ const parsed = JSON.parse(result.formatted);
38
+ expect(parsed).toHaveProperty('version');
39
+ expect(parsed).toHaveProperty('summary');
40
+ expect(parsed).toHaveProperty('checks');
41
+ });
42
+
43
+ it('should produce text when json option is false', async () => {
44
+ const result = await runDoctorChecks({ json: false, projectRoot });
45
+ expect(result.formatted).toContain('AIOS Doctor');
46
+ expect(result.formatted).toContain('Summary:');
47
+ });
48
+ });
49
+
50
+ describe('15 checks (AC2 + INS-4.8)', () => {
51
+ it('should run exactly 15 checks', async () => {
52
+ const result = await runDoctorChecks({ projectRoot });
53
+ expect(result.data.checks).toHaveLength(15);
54
+ });
55
+
56
+ it('should return valid status for each check', async () => {
57
+ const result = await runDoctorChecks({ projectRoot });
58
+ const validStatuses = ['PASS', 'WARN', 'FAIL', 'INFO'];
59
+
60
+ for (const check of result.data.checks) {
61
+ expect(validStatuses).toContain(check.status);
62
+ expect(check).toHaveProperty('check');
63
+ expect(check).toHaveProperty('message');
64
+ }
65
+ });
66
+
67
+ it('should include all expected check names', async () => {
68
+ const result = await runDoctorChecks({ projectRoot });
69
+ const checkNames = result.data.checks.map((c) => c.check);
70
+
71
+ expect(checkNames).toContain('settings-json');
72
+ expect(checkNames).toContain('rules-files');
73
+ expect(checkNames).toContain('agent-memory');
74
+ expect(checkNames).toContain('entity-registry');
75
+ expect(checkNames).toContain('git-hooks');
76
+ expect(checkNames).toContain('core-config');
77
+ expect(checkNames).toContain('claude-md');
78
+ expect(checkNames).toContain('ide-sync');
79
+ expect(checkNames).toContain('graph-dashboard');
80
+ expect(checkNames).toContain('code-intel');
81
+ expect(checkNames).toContain('node-version');
82
+ expect(checkNames).toContain('npm-packages');
83
+ expect(checkNames).toContain('skills-count');
84
+ expect(checkNames).toContain('commands-count');
85
+ expect(checkNames).toContain('hooks-claude-count');
86
+ });
87
+ });
88
+
89
+ describe('summary (AC3)', () => {
90
+ it('should have pass/warn/fail/info counts that sum to 15', async () => {
91
+ const result = await runDoctorChecks({ projectRoot });
92
+ const { pass, warn, fail, info } = result.data.summary;
93
+ expect(pass + warn + fail + info).toBe(15);
94
+ });
95
+
96
+ it('should include Summary line in text output', async () => {
97
+ const result = await runDoctorChecks({ projectRoot });
98
+ expect(result.formatted).toMatch(/Summary: \d+ PASS \| \d+ WARN \| \d+ FAIL \| \d+ INFO/);
99
+ });
100
+ });
101
+
102
+ describe('--dry-run (AC4)', () => {
103
+ it('should include fixResults when dryRun is true', async () => {
104
+ const result = await runDoctorChecks({ dryRun: true, projectRoot });
105
+ expect(result.data).toHaveProperty('fixResults');
106
+ });
107
+
108
+ it('should not produce file changes with dryRun', async () => {
109
+ const result = await runDoctorChecks({ dryRun: true, projectRoot });
110
+ if (result.data.fixResults) {
111
+ for (const fr of result.data.fixResults) {
112
+ expect(fr.applied).toBe(false);
113
+ }
114
+ }
115
+ });
116
+ });
117
+
118
+ describe('JSON output schema (AC3)', () => {
119
+ it('should match expected JSON schema', async () => {
120
+ const result = await runDoctorChecks({ json: true, projectRoot });
121
+ const parsed = JSON.parse(result.formatted);
122
+
123
+ expect(parsed).toHaveProperty('version');
124
+ expect(parsed).toHaveProperty('timestamp');
125
+ expect(parsed).toHaveProperty('summary');
126
+ expect(parsed.summary).toHaveProperty('pass');
127
+ expect(parsed.summary).toHaveProperty('warn');
128
+ expect(parsed.summary).toHaveProperty('fail');
129
+ expect(parsed.summary).toHaveProperty('info');
130
+ expect(parsed).toHaveProperty('checks');
131
+ expect(Array.isArray(parsed.checks)).toBe(true);
132
+ });
133
+ });
134
+ });
@@ -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
+ });