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
@@ -6,6 +6,7 @@ const path = require('path');
6
6
  const yaml = require('js-yaml');
7
7
  const fg = require('fast-glob');
8
8
  const crypto = require('crypto');
9
+ const { classifyLayer } = require('../../core/ids/layer-classifier');
9
10
 
10
11
  const REPO_ROOT = path.resolve(__dirname, '../../..');
11
12
  const REGISTRY_PATH = path.resolve(__dirname, '../../data/entity-registry.yaml');
@@ -17,7 +18,14 @@ const SCAN_CONFIG = [
17
18
  { category: 'modules', basePath: '.aios-core/core', glob: '**/*.{js,mjs}', type: 'module' },
18
19
  { category: 'agents', basePath: '.aios-core/development/agents', glob: '**/*.{md,yaml,yml}', type: 'agent' },
19
20
  { category: 'checklists', basePath: '.aios-core/development/checklists', glob: '**/*.md', type: 'checklist' },
20
- { category: 'data', basePath: '.aios-core/data', glob: '**/*.{yaml,yml,md}', type: 'data' }
21
+ { category: 'data', basePath: '.aios-core/data', glob: '**/*.{yaml,yml,md}', type: 'data' },
22
+ { category: 'workflows', basePath: '.aios-core/development/workflows', glob: '**/*.{yaml,yml}', type: 'workflow' },
23
+ { category: 'utils', basePath: '.aios-core/core/utils', glob: '**/*.js', type: 'util' },
24
+ { category: 'tools', basePath: '.aios-core/development/tools', glob: '**/*.{md,js,sh}', type: 'tool' },
25
+ { category: 'infra-scripts', basePath: '.aios-core/infrastructure/scripts', glob: '**/*.js', type: 'script' },
26
+ { category: 'infra-tools', basePath: '.aios-core/infrastructure/tools', glob: '**/*.{yaml,yml,md}', type: 'tool' },
27
+ { category: 'product-checklists', basePath: '.aios-core/product/checklists', glob: '**/*.md', type: 'checklist' },
28
+ { category: 'product-data', basePath: '.aios-core/product/data', glob: '**/*.{yaml,yml,md}', type: 'data' }
21
29
  ];
22
30
 
23
31
  const ADAPTABILITY_DEFAULTS = {
@@ -27,9 +35,38 @@ const ADAPTABILITY_DEFAULTS = {
27
35
  checklist: 0.6,
28
36
  data: 0.5,
29
37
  script: 0.7,
30
- task: 0.8
38
+ task: 0.8,
39
+ workflow: 0.4,
40
+ util: 0.6,
41
+ tool: 0.7
31
42
  };
32
43
 
44
+ const EXTERNAL_TOOLS = new Set([
45
+ 'coderabbit', 'git', 'github-cli', 'docker', 'supabase', 'browser',
46
+ 'ffmpeg', 'n8n', 'context7', 'playwright', 'apify', 'clickup',
47
+ 'jira', 'slack', 'exa', 'eslint', 'jest', 'npm', 'node',
48
+ 'docker-gateway', 'desktop-commander', 'railway'
49
+ ]);
50
+
51
+ const DEPRECATED_PATTERNS = [/^old[-_]/, /^backup[-_]/, /deprecated/i, /^legacy[-_]/];
52
+
53
+ const SENTINEL_VALUES = new Set(['n/a', 'na', 'none', 'tbd', 'todo', '-', '']);
54
+
55
+ function isSentinel(value) {
56
+ return SENTINEL_VALUES.has(value.toLowerCase().trim());
57
+ }
58
+
59
+ function isNoise(value) {
60
+ const trimmed = value.trim();
61
+ // Very short fragments (1-2 chars) unless they are known agent refs
62
+ if (trimmed.length <= 2 && !KNOWN_AGENTS.includes(trimmed)) return true;
63
+ // Natural language fragments (contains spaces and > 2 words)
64
+ if (trimmed.includes(' ') && trimmed.split(/\s+/).length > 2) return true;
65
+ // Template placeholders
66
+ if (trimmed.includes('{{') || trimmed.includes('${')) return true;
67
+ return false;
68
+ }
69
+
33
70
  function computeChecksum(filePath) {
34
71
  const content = fs.readFileSync(filePath);
35
72
  return 'sha256:' + crypto.createHash('sha256').update(content).digest('hex');
@@ -74,7 +111,163 @@ function extractPurpose(content, filePath) {
74
111
  return `Entity at ${path.relative(REPO_ROOT, filePath)}`;
75
112
  }
76
113
 
77
- function detectDependencies(content, entityId) {
114
+ const YAML_DEP_FIELDS = {
115
+ agent: {
116
+ nested: ['tasks', 'templates', 'checklists', 'tools', 'scripts'],
117
+ arrayFields: [
118
+ { arrayPath: 'commands', field: 'task' },
119
+ ],
120
+ },
121
+ workflow: {
122
+ nested: [],
123
+ arrayFields: [
124
+ { arrayPath: 'phases', field: 'task' },
125
+ { arrayPath: 'phases', field: 'agent' },
126
+ { arrayPath: 'sequence', field: 'agent' },
127
+ { arrayPath: 'steps', field: 'task' },
128
+ { arrayPath: 'steps', field: 'uses' },
129
+ ],
130
+ },
131
+ };
132
+
133
+ const KNOWN_AGENTS = [
134
+ 'dev', 'qa', 'pm', 'po', 'sm', 'architect', 'devops',
135
+ 'analyst', 'data-engineer', 'ux-design-expert', 'aios-master'
136
+ ];
137
+
138
+ // Pattern A: YAML dependency block items (- name.md)
139
+ const YAML_BLOCK_RE = /^\s*[-*]\s+([\w.-]+\.(?:md|yaml|js))\s*$/gm;
140
+ // Pattern B: Label list (- **Tasks:** a.md, b.md)
141
+ const LABEL_LIST_RE = /^\s*[-*]\s+\*\*[\w\s]+:\*\*\s+(.+)$/gm;
142
+ // Pattern C: Markdown links to entity files
143
+ const MD_LINK_RE = /\[([^\]]+)\]\(([^)]+\.(?:md|yaml|js))\)/g;
144
+ // Pattern D: Agent references
145
+ const AGENT_REF_RE = new RegExp('@(' + KNOWN_AGENTS.join('|') + ')\\b', 'g');
146
+
147
+ function extractYamlDependencies(filePath, entityType, verbose = false) {
148
+ const deps = new Set();
149
+ const fieldMap = YAML_DEP_FIELDS[entityType];
150
+ if (!fieldMap) return [];
151
+
152
+ let content;
153
+ try {
154
+ content = fs.readFileSync(filePath, 'utf8');
155
+ } catch {
156
+ return [];
157
+ }
158
+
159
+ let doc;
160
+ // For MD files, extract YAML from code blocks instead of parsing the whole file
161
+ if (path.extname(filePath) === '.md') {
162
+ const yamlBlockMatch = content.match(/```yaml\n([\s\S]*?)```/);
163
+ if (!yamlBlockMatch) return [];
164
+ try {
165
+ doc = yaml.load(yamlBlockMatch[1]);
166
+ } catch {
167
+ console.warn(`[IDS] YAML parse warning (embedded block): ${filePath} — skipping`);
168
+ return [];
169
+ }
170
+ } else {
171
+ try {
172
+ doc = yaml.load(content);
173
+ } catch {
174
+ console.warn(`[IDS] YAML parse warning: ${filePath} — skipping YAML extraction`);
175
+ return [];
176
+ }
177
+ }
178
+
179
+ if (!doc || typeof doc !== 'object') return [];
180
+
181
+ // Extract nested dependency fields (e.g., doc.dependencies.tasks)
182
+ const depsSection = doc.dependencies || {};
183
+ for (const field of fieldMap.nested) {
184
+ const items = depsSection[field];
185
+ if (Array.isArray(items)) {
186
+ for (const item of items) {
187
+ if (typeof item === 'string') {
188
+ const cleaned = item.replace(/#.*$/, '').trim().replace(/\.md$/, '');
189
+ if (!cleaned) continue;
190
+ if (isSentinel(cleaned)) {
191
+ if (verbose) console.log(`[IDS] Filtered sentinel "${cleaned}" from YAML deps in "${filePath}"`);
192
+ continue;
193
+ }
194
+ if (isNoise(cleaned)) {
195
+ if (verbose) console.log(`[IDS] Filtered noise "${cleaned}" from YAML deps in "${filePath}"`);
196
+ continue;
197
+ }
198
+ deps.add(cleaned);
199
+ }
200
+ }
201
+ }
202
+ }
203
+
204
+ // Extract array fields (e.g., doc.commands[].task, doc.sequence[].agent)
205
+ for (const { arrayPath, field } of fieldMap.arrayFields) {
206
+ const arr = doc[arrayPath] || doc.workflow?.[arrayPath] || [];
207
+ if (Array.isArray(arr)) {
208
+ for (const item of arr) {
209
+ if (item && typeof item === 'object') {
210
+ const val = item[field];
211
+ if (typeof val === 'string' && val.trim()) {
212
+ deps.add(val.trim().replace(/\.md$/, ''));
213
+ }
214
+ }
215
+ }
216
+ }
217
+ }
218
+
219
+ return [...deps];
220
+ }
221
+
222
+ function extractMarkdownCrossReferences(content, entityId, verbose = false) {
223
+ const deps = new Set();
224
+
225
+ const addDep = (ref) => {
226
+ if (ref === entityId) return;
227
+ if (isSentinel(ref)) {
228
+ if (verbose) console.log(`[IDS] Filtered sentinel "${ref}" from MD cross-refs in "${entityId}"`);
229
+ return;
230
+ }
231
+ if (isNoise(ref)) {
232
+ if (verbose) console.log(`[IDS] Filtered noise "${ref}" from MD cross-refs in "${entityId}"`);
233
+ return;
234
+ }
235
+ deps.add(ref);
236
+ };
237
+
238
+ // Pattern A: YAML block items (- filename.md)
239
+ let match;
240
+ while ((match = YAML_BLOCK_RE.exec(content)) !== null) {
241
+ addDep(match[1].replace(/\.md$/, ''));
242
+ }
243
+
244
+ // Pattern B: Label lists (- **Tasks:** a.md, b.md)
245
+ while ((match = LABEL_LIST_RE.exec(content)) !== null) {
246
+ const items = match[1].split(/[,;]\s*/);
247
+ for (const item of items) {
248
+ const fileMatch = item.trim().match(/([\w.-]+\.(?:md|yaml|js))/);
249
+ if (fileMatch) {
250
+ addDep(fileMatch[1].replace(/\.md$/, ''));
251
+ }
252
+ }
253
+ }
254
+
255
+ // Pattern C: Markdown links to entity files
256
+ while ((match = MD_LINK_RE.exec(content)) !== null) {
257
+ const linkPath = match[2];
258
+ const basename = path.basename(linkPath, path.extname(linkPath));
259
+ addDep(basename);
260
+ }
261
+
262
+ // Pattern D: Agent references (@dev, @qa, etc.)
263
+ while ((match = AGENT_REF_RE.exec(content)) !== null) {
264
+ deps.add(match[1]);
265
+ }
266
+
267
+ return [...deps];
268
+ }
269
+
270
+ function detectDependencies(content, entityId, verbose = false) {
78
271
  const deps = new Set();
79
272
 
80
273
  const requireMatches = content.matchAll(/require\s*\(\s*['"]([^'"]+)['"]\s*\)/g);
@@ -100,14 +293,23 @@ function detectDependencies(content, entityId) {
100
293
  const items = depListMatch[1].matchAll(/-\s+(.+)/g);
101
294
  for (const item of items) {
102
295
  const dep = item[1].trim().replace(/\.md$/, '');
103
- if (dep !== entityId) deps.add(dep);
296
+ if (dep === entityId) continue;
297
+ if (isSentinel(dep)) {
298
+ if (verbose) console.log(`[IDS] Filtered sentinel "${dep}" from "${entityId}"`);
299
+ continue;
300
+ }
301
+ if (isNoise(dep)) {
302
+ if (verbose) console.log(`[IDS] Filtered noise "${dep}" from "${entityId}"`);
303
+ continue;
304
+ }
305
+ deps.add(dep);
104
306
  }
105
307
  }
106
308
 
107
309
  return [...deps];
108
310
  }
109
311
 
110
- function scanCategory(config) {
312
+ function scanCategory(config, verbose = false) {
111
313
  const absBase = path.resolve(REPO_ROOT, config.basePath);
112
314
 
113
315
  if (!fs.existsSync(absBase)) {
@@ -141,17 +343,56 @@ function scanCategory(config) {
141
343
  const relPath = path.relative(REPO_ROOT, filePath).replace(/\\/g, '/');
142
344
  const keywords = extractKeywords(filePath, content);
143
345
  const purpose = extractPurpose(content, filePath);
144
- const dependencies = detectDependencies(content, entityId);
346
+ const baseDeps = detectDependencies(content, entityId, verbose);
347
+
348
+ // Semantic YAML extraction for agents and workflows
349
+ const yamlCategories = ['agents', 'workflows'];
350
+ const yamlDeps = yamlCategories.includes(config.category)
351
+ ? extractYamlDependencies(filePath, config.type, verbose)
352
+ : [];
353
+
354
+ // Markdown cross-reference extraction for tasks, checklists, templates, product-checklists
355
+ const mdCategories = ['tasks', 'checklists', 'templates', 'product-checklists'];
356
+ const mdDeps = mdCategories.includes(config.category)
357
+ ? extractMarkdownCrossReferences(content, entityId, verbose)
358
+ : [];
359
+
360
+ // Merge all dependencies (deduplicated — each extractor already filters sentinel/noise)
361
+ const dependencies = [...new Set([...baseDeps, ...yamlDeps, ...mdDeps])];
362
+
363
+ // Extract lifecycle override from YAML frontmatter or metadata (NOG-16B AC5)
364
+ let lifecycleOverride = null;
365
+ const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
366
+ if (frontmatterMatch) {
367
+ const lfMatch = frontmatterMatch[1].match(/^lifecycle:\s*(.+)$/m);
368
+ if (lfMatch) lifecycleOverride = lfMatch[1].trim();
369
+ }
370
+ if (!lifecycleOverride) {
371
+ const yamlBlockMatch = content.match(/```yaml\n([\s\S]*?)```/);
372
+ if (yamlBlockMatch) {
373
+ const lfMatch = yamlBlockMatch[1].match(/^lifecycle:\s*(.+)$/m);
374
+ if (lfMatch) lifecycleOverride = lfMatch[1].trim();
375
+ }
376
+ }
377
+ if (!lifecycleOverride) {
378
+ const inlineMatch = content.match(/^lifecycle:\s*(.+)$/m);
379
+ if (inlineMatch) lifecycleOverride = inlineMatch[1].trim();
380
+ }
381
+
145
382
  const checksum = computeChecksum(filePath);
146
383
  const defaultScore = ADAPTABILITY_DEFAULTS[config.type] || 0.5;
147
384
 
148
- entities[entityId] = {
385
+ const entity = {
149
386
  path: relPath,
387
+ layer: classifyLayer(relPath),
150
388
  type: config.type,
151
389
  purpose,
152
390
  keywords,
153
391
  usedBy: [],
154
392
  dependencies,
393
+ externalDeps: [],
394
+ plannedDeps: [],
395
+ lifecycle: 'experimental',
155
396
  adaptability: {
156
397
  score: defaultScore,
157
398
  constraints: [],
@@ -160,25 +401,68 @@ function scanCategory(config) {
160
401
  checksum,
161
402
  lastVerified: new Date().toISOString()
162
403
  };
404
+
405
+ if (lifecycleOverride) {
406
+ entity._lifecycleOverride = lifecycleOverride;
407
+ }
408
+
409
+ entities[entityId] = entity;
163
410
  }
164
411
 
165
412
  return entities;
166
413
  }
167
414
 
168
- function resolveUsedBy(allEntities) {
169
- const idToCategory = {};
415
+ function buildNameIndex(allEntities) {
416
+ const nameIndex = new Map();
170
417
  for (const [category, entities] of Object.entries(allEntities)) {
171
- for (const id of Object.keys(entities)) {
172
- idToCategory[id] = category;
418
+ for (const [id, entity] of Object.entries(entities)) {
419
+ nameIndex.set(id, { category, id });
420
+ if (entity.path) {
421
+ const filename = entity.path.split('/').pop();
422
+ if (!nameIndex.has(filename)) {
423
+ nameIndex.set(filename, { category, id });
424
+ }
425
+ const basename = filename.replace(/\.[^.]+$/, '');
426
+ if (!nameIndex.has(basename)) {
427
+ nameIndex.set(basename, { category, id });
428
+ }
429
+ }
430
+ }
431
+ }
432
+ return nameIndex;
433
+ }
434
+
435
+ function countResolution(allEntities, nameIndex) {
436
+ let total = 0;
437
+ let resolved = 0;
438
+ for (const entities of Object.values(allEntities)) {
439
+ for (const entity of Object.values(entities)) {
440
+ for (const dep of entity.dependencies) {
441
+ total++;
442
+ if (nameIndex.has(dep)) resolved++;
443
+ }
444
+ }
445
+ }
446
+ return { total, resolved, unresolved: total - resolved };
447
+ }
448
+
449
+ function resolveUsedBy(allEntities) {
450
+ const nameIndex = buildNameIndex(allEntities);
451
+
452
+ // Reset usedBy to avoid duplicates on re-scan
453
+ for (const entities of Object.values(allEntities)) {
454
+ for (const entity of Object.values(entities)) {
455
+ entity.usedBy = [];
173
456
  }
174
457
  }
175
458
 
459
+ // Build reverse references
176
460
  for (const [category, entities] of Object.entries(allEntities)) {
177
461
  for (const [entityId, entity] of Object.entries(entities)) {
178
- for (const depId of entity.dependencies) {
179
- const depCategory = idToCategory[depId];
180
- if (depCategory && allEntities[depCategory][depId]) {
181
- const usedBy = allEntities[depCategory][depId].usedBy;
462
+ for (const depRef of entity.dependencies) {
463
+ const target = nameIndex.get(depRef);
464
+ if (target && allEntities[target.category] && allEntities[target.category][target.id]) {
465
+ const usedBy = allEntities[target.category][target.id].usedBy;
182
466
  if (!usedBy.includes(entityId)) {
183
467
  usedBy.push(entityId);
184
468
  }
@@ -188,7 +472,57 @@ function resolveUsedBy(allEntities) {
188
472
  }
189
473
  }
190
474
 
191
- function populate() {
475
+ function classifyDependencies(allEntities, nameIndex) {
476
+ for (const entities of Object.values(allEntities)) {
477
+ for (const entity of Object.values(entities)) {
478
+ const internal = [];
479
+ const external = [];
480
+ const planned = [];
481
+ for (const dep of entity.dependencies) {
482
+ if (nameIndex.has(dep)) {
483
+ internal.push(dep);
484
+ } else if (EXTERNAL_TOOLS.has(dep.toLowerCase())) {
485
+ external.push(dep);
486
+ } else {
487
+ planned.push(dep);
488
+ }
489
+ }
490
+ entity.dependencies = internal;
491
+ entity.externalDeps = external;
492
+ entity.plannedDeps = planned;
493
+ }
494
+ }
495
+ }
496
+
497
+ function detectLifecycle(entityId, entity) {
498
+ if (entity._lifecycleOverride) {
499
+ const val = entity._lifecycleOverride;
500
+ delete entity._lifecycleOverride;
501
+ return val;
502
+ }
503
+ for (const pat of DEPRECATED_PATTERNS) {
504
+ if (pat.test(entityId)) return 'deprecated';
505
+ }
506
+ const hasDeps = entity.dependencies.length > 0 ||
507
+ (entity.externalDeps && entity.externalDeps.length > 0) ||
508
+ (entity.plannedDeps && entity.plannedDeps.length > 0);
509
+ const hasUsedBy = entity.usedBy.length > 0;
510
+ if (!hasDeps && !hasUsedBy) return 'orphan';
511
+ if (hasUsedBy) return 'production';
512
+ return 'experimental';
513
+ }
514
+
515
+ function assignLifecycles(allEntities) {
516
+ for (const [, entities] of Object.entries(allEntities)) {
517
+ for (const [entityId, entity] of Object.entries(entities)) {
518
+ entity.lifecycle = detectLifecycle(entityId, entity);
519
+ }
520
+ }
521
+ }
522
+
523
+ function populate(options = {}) {
524
+ const verbose = options.verbose || process.argv.includes('--verbose') || process.env.AIOS_DEBUG === 'true';
525
+
192
526
  console.log('[IDS] Starting entity registry population...');
193
527
 
194
528
  const allEntities = {};
@@ -196,16 +530,53 @@ function populate() {
196
530
 
197
531
  for (const config of SCAN_CONFIG) {
198
532
  console.log(`[IDS] Scanning ${config.category} in ${config.basePath}...`);
199
- const entities = scanCategory(config);
533
+ const entities = scanCategory(config, verbose);
200
534
  const count = Object.keys(entities).length;
201
535
  allEntities[config.category] = entities;
202
536
  totalCount += count;
203
537
  console.log(`[IDS] Found ${count} ${config.category}`);
204
538
  }
205
539
 
540
+ // Preserve invocationExamples from existing registry (TOK-4B)
541
+ // invocationExamples are manually curated and must survive re-population.
542
+ // Limits: max 3 examples per entity, max 200 tokens per example (ADR-5).
543
+ try {
544
+ const existingYaml = fs.readFileSync(REGISTRY_PATH, 'utf8');
545
+ const existingRegistry = yaml.load(existingYaml);
546
+ if (existingRegistry && existingRegistry.entities) {
547
+ for (const [category, entities] of Object.entries(existingRegistry.entities)) {
548
+ if (!allEntities[category]) continue;
549
+ for (const [entityId, entity] of Object.entries(entities)) {
550
+ if (entity.invocationExamples && Array.isArray(entity.invocationExamples) && allEntities[category][entityId]) {
551
+ // Enforce limits: max 3 examples, each max 200 chars
552
+ const examples = entity.invocationExamples.slice(0, 3).map((e) => String(e).slice(0, 200));
553
+ allEntities[category][entityId].invocationExamples = examples;
554
+ }
555
+ }
556
+ }
557
+ console.log('[IDS] Preserved invocationExamples from existing registry');
558
+ }
559
+ } catch {
560
+ // No existing registry or parse error — skip preservation
561
+ }
562
+
206
563
  console.log('[IDS] Resolving usedBy relationships...');
207
564
  resolveUsedBy(allEntities);
208
565
 
566
+ // Classify dependencies into internal, external, planned (NOG-16B)
567
+ const nameIndex = buildNameIndex(allEntities);
568
+ console.log('[IDS] Classifying dependencies (internal/external/planned)...');
569
+ classifyDependencies(allEntities, nameIndex);
570
+
571
+ // Assign lifecycle states (NOG-16B)
572
+ console.log('[IDS] Detecting entity lifecycle states...');
573
+ assignLifecycles(allEntities);
574
+
575
+ // Resolution rate metric (uses internal deps only after classification)
576
+ const { total, resolved, unresolved } = countResolution(allEntities, nameIndex);
577
+ const rate = total > 0 ? Math.round(resolved / total * 100) : 0;
578
+ console.log(`[IDS] Resolution rate: ${rate}% (${resolved}/${total} deps resolved, ${unresolved} unresolved)`);
579
+
209
580
  const categories = SCAN_CONFIG.map((c) => ({
210
581
  id: c.category,
211
582
  description: getCategoryDescription(c.category),
@@ -217,7 +588,8 @@ function populate() {
217
588
  version: '1.0.0',
218
589
  lastUpdated: new Date().toISOString(),
219
590
  entityCount: totalCount,
220
- checksumAlgorithm: 'sha256'
591
+ checksumAlgorithm: 'sha256',
592
+ resolutionRate: rate
221
593
  },
222
594
  entities: allEntities,
223
595
  categories
@@ -248,7 +620,14 @@ function getCategoryDescription(category) {
248
620
  modules: 'Core framework modules and libraries',
249
621
  agents: 'Agent persona definitions and configurations',
250
622
  checklists: 'Validation and review checklists',
251
- data: 'Configuration and reference data files'
623
+ data: 'Configuration and reference data files',
624
+ workflows: 'Multi-phase orchestration workflows',
625
+ utils: 'Shared utility libraries and helpers',
626
+ tools: 'Development tool definitions and configurations',
627
+ 'infra-scripts': 'Infrastructure automation and utility scripts',
628
+ 'infra-tools': 'Infrastructure tool definitions and configurations',
629
+ 'product-checklists': 'Product validation and review checklists',
630
+ 'product-data': 'Product reference data and configuration files'
252
631
  };
253
632
  return descriptions[category] || category;
254
633
  }
@@ -271,10 +650,24 @@ module.exports = {
271
650
  extractKeywords,
272
651
  extractPurpose,
273
652
  detectDependencies,
653
+ extractYamlDependencies,
654
+ extractMarkdownCrossReferences,
274
655
  computeChecksum,
275
656
  resolveUsedBy,
657
+ buildNameIndex,
658
+ countResolution,
659
+ classifyDependencies,
660
+ detectLifecycle,
661
+ assignLifecycles,
662
+ isSentinel,
663
+ isNoise,
276
664
  SCAN_CONFIG,
277
665
  ADAPTABILITY_DEFAULTS,
666
+ SENTINEL_VALUES,
667
+ YAML_DEP_FIELDS,
668
+ KNOWN_AGENTS,
669
+ EXTERNAL_TOOLS,
670
+ DEPRECATED_PATTERNS,
278
671
  REPO_ROOT,
279
672
  REGISTRY_PATH
280
673
  };
@@ -47,12 +47,14 @@ const yaml = require('js-yaml');
47
47
  const GreetingBuilder = require('./greeting-builder');
48
48
  const { AgentConfigLoader } = require('./agent-config-loader');
49
49
  const SessionContextLoader = require('../../core/session/context-loader');
50
- const { loadProjectStatus } = require('../../infrastructure/scripts/project-status-loader');
50
+ // NOG-18: loadProjectStatus removed gitStatus is native in Claude Code system prompt.
51
+ // const { loadProjectStatus } = require('../../infrastructure/scripts/project-status-loader');
51
52
  const GitConfigDetector = require('../../infrastructure/scripts/git-config-detector');
52
53
  const { PermissionMode } = require('../../core/permissions');
53
54
  const GreetingPreferenceManager = require('./greeting-preference-manager');
54
55
  const ContextDetector = require('../../core/session/context-detector');
55
56
  const WorkflowNavigator = require('./workflow-navigator');
57
+ const { atomicWriteSync } = require('../../core/synapse/utils/atomic-write');
56
58
  // BUG-1 fix (INS-1): Graceful degradation when pro-detector is not available
57
59
  // In installed projects, bin/utils/pro-detector.js does not exist
58
60
  let isProAvailable, loadProModule;
@@ -82,9 +84,9 @@ const LOADER_TIERS = {
82
84
  description: 'Permission badge + branch name — visually degraded without these',
83
85
  },
84
86
  bestEffort: {
85
- loaders: ['sessionContext', 'projectStatus'],
87
+ loaders: ['sessionContext'],
86
88
  timeout: 180,
87
- description: 'Session awareness + project status — greeting works fine without these',
89
+ description: 'Session awareness — greeting works fine without this. NOG-18: projectStatus removed (native gitStatus)',
88
90
  },
89
91
  };
90
92
 
@@ -279,15 +281,16 @@ class UnifiedActivationPipeline {
279
281
  const elapsedAfterT2 = Date.now() - pipelineStart;
280
282
  const tier3Remaining = Math.max(tier3Budget - elapsedAfterT2, 20);
281
283
 
282
- const [sessionContext, projectStatus] = await Promise.all([
284
+ // NOG-18: projectStatus loader removed — gitStatus is native in Claude Code system prompt.
285
+ // The loadProjectStatus() function ran 5+ git commands (~76ms) duplicating native features.
286
+ // GreetingBuilder handles projectStatus: null gracefully (null-checks everywhere).
287
+ const [sessionContext] = await Promise.all([
283
288
  this._profileLoader('sessionContext', metrics, tier3Remaining, () => {
284
289
  const loader = new SessionContextLoader();
285
290
  return loader.loadContext(agentId);
286
291
  }),
287
- this._profileLoader('projectStatus', metrics, tier3Remaining, () => {
288
- return loadProjectStatus();
289
- }),
290
292
  ]);
293
+ const projectStatus = null;
291
294
 
292
295
  // --- Sequential steps with data dependencies ---
293
296
 
@@ -710,7 +713,7 @@ class UnifiedActivationPipeline {
710
713
  };
711
714
 
712
715
  const bridgePath = path.join(sessionsDir, '_active-agent.json');
713
- fsSync.writeFileSync(bridgePath, JSON.stringify(bridgeData, null, 2), 'utf8');
716
+ atomicWriteSync(bridgePath, JSON.stringify(bridgeData, null, 2));
714
717
 
715
718
  const duration = Date.now() - start;
716
719
  metrics.loaders.synapseSession = { duration, status: 'ok', start, end: start + duration };
@@ -756,9 +759,9 @@ class UnifiedActivationPipeline {
756
759
  status: info.status || 'unknown',
757
760
  };
758
761
  }
759
- fsSync.writeFileSync(
762
+ atomicWriteSync(
760
763
  path.join(metricsDir, 'uap-metrics.json'),
761
- JSON.stringify(data, null, 2), 'utf8',
764
+ JSON.stringify(data, null, 2),
762
765
  );
763
766
  } catch {
764
767
  // Fire-and-forget: never block the activation pipeline
@@ -792,3 +795,21 @@ module.exports = {
792
795
  // ACT-12: Single English fallback (language delegated to Claude Code settings.json)
793
796
  FALLBACK_PHRASE,
794
797
  };
798
+
799
+ // CLI entrypoint: `node unified-activation-pipeline.js <agentId>`
800
+ if (require.main === module) {
801
+ const agentId = process.argv[2];
802
+ if (!agentId || !ALL_AGENT_IDS.includes(agentId)) {
803
+ console.error(`Usage: node unified-activation-pipeline.js <agentId>\nValid agents: ${ALL_AGENT_IDS.join(', ')}`);
804
+ process.exit(1);
805
+ }
806
+ UnifiedActivationPipeline.activate(agentId)
807
+ .then(result => {
808
+ console.log(result.greeting);
809
+ process.exit(0);
810
+ })
811
+ .catch(err => {
812
+ console.error(`Activation error: ${err.message}`);
813
+ process.exit(1);
814
+ });
815
+ }