@winspan/claude-forge 8.54.3 → 9.2.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.
- package/DEVELOPMENT.md +649 -33
- package/README.md +155 -17
- package/dist/catalogs/agents.json +72 -0
- package/dist/catalogs/skills.json +194 -0
- package/dist/claudemd/claudemd-generator.d.ts +45 -45
- package/dist/claudemd/claudemd-generator.d.ts.map +1 -1
- package/dist/claudemd/claudemd-generator.js +128 -449
- package/dist/claudemd/claudemd-generator.js.map +1 -1
- package/dist/claudemd/index.d.ts +14 -4
- package/dist/claudemd/index.d.ts.map +1 -1
- package/dist/claudemd/index.js +15 -4
- package/dist/claudemd/index.js.map +1 -1
- package/dist/claudemd/resume-manager.d.ts.map +1 -1
- package/dist/claudemd/resume-manager.js +37 -9
- package/dist/claudemd/resume-manager.js.map +1 -1
- package/dist/claudemd/templates/swarm-protocol.md +35 -186
- package/dist/claudemd/violations-manager.d.ts +40 -0
- package/dist/claudemd/violations-manager.d.ts.map +1 -0
- package/dist/claudemd/violations-manager.js +106 -0
- package/dist/claudemd/violations-manager.js.map +1 -0
- package/dist/cli/commands/admin.d.ts +15 -0
- package/dist/cli/commands/admin.d.ts.map +1 -0
- package/dist/cli/commands/admin.js +177 -0
- package/dist/cli/commands/admin.js.map +1 -0
- package/dist/cli/commands/agents.d.ts +18 -0
- package/dist/cli/commands/agents.d.ts.map +1 -0
- package/dist/cli/commands/agents.js +160 -0
- package/dist/cli/commands/agents.js.map +1 -0
- package/dist/cli/commands/bypass.d.ts +18 -0
- package/dist/cli/commands/bypass.d.ts.map +1 -0
- package/dist/cli/commands/bypass.js +87 -0
- package/dist/cli/commands/bypass.js.map +1 -0
- package/dist/cli/commands/claudemd.d.ts +60 -0
- package/dist/cli/commands/claudemd.d.ts.map +1 -1
- package/dist/cli/commands/claudemd.js +174 -37
- package/dist/cli/commands/claudemd.js.map +1 -1
- package/dist/cli/commands/config.d.ts.map +1 -1
- package/dist/cli/commands/config.js +94 -1
- package/dist/cli/commands/config.js.map +1 -1
- package/dist/cli/commands/daemon.d.ts +39 -0
- package/dist/cli/commands/daemon.d.ts.map +1 -1
- package/dist/cli/commands/daemon.js +167 -20
- package/dist/cli/commands/daemon.js.map +1 -1
- package/dist/cli/commands/decisions.d.ts +129 -0
- package/dist/cli/commands/decisions.d.ts.map +1 -0
- package/dist/cli/commands/decisions.js +669 -0
- package/dist/cli/commands/decisions.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +29 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +124 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/entropy.d.ts +35 -0
- package/dist/cli/commands/entropy.d.ts.map +1 -0
- package/dist/cli/commands/entropy.js +121 -0
- package/dist/cli/commands/entropy.js.map +1 -0
- package/dist/cli/commands/executions.d.ts +1 -0
- package/dist/cli/commands/executions.d.ts.map +1 -1
- package/dist/cli/commands/executions.js +10 -1
- package/dist/cli/commands/executions.js.map +1 -1
- package/dist/cli/commands/fix.d.ts +31 -0
- package/dist/cli/commands/fix.d.ts.map +1 -0
- package/dist/cli/commands/fix.js +108 -0
- package/dist/cli/commands/fix.js.map +1 -0
- package/dist/cli/commands/governance.d.ts +21 -0
- package/dist/cli/commands/governance.d.ts.map +1 -0
- package/dist/cli/commands/governance.js +60 -0
- package/dist/cli/commands/governance.js.map +1 -0
- package/dist/cli/commands/init.d.ts +27 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +158 -146
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/insights-goal-check.d.ts +50 -0
- package/dist/cli/commands/insights-goal-check.d.ts.map +1 -0
- package/dist/cli/commands/insights-goal-check.js +318 -0
- package/dist/cli/commands/insights-goal-check.js.map +1 -0
- package/dist/cli/commands/insights.d.ts +15 -0
- package/dist/cli/commands/insights.d.ts.map +1 -0
- package/dist/cli/commands/insights.js +127 -0
- package/dist/cli/commands/insights.js.map +1 -0
- package/dist/cli/commands/knowledge.d.ts +66 -0
- package/dist/cli/commands/knowledge.d.ts.map +1 -0
- package/dist/cli/commands/knowledge.js +897 -0
- package/dist/cli/commands/knowledge.js.map +1 -0
- package/dist/cli/commands/mcp.d.ts +0 -12
- package/dist/cli/commands/mcp.d.ts.map +1 -1
- package/dist/cli/commands/mcp.js +11 -5
- package/dist/cli/commands/mcp.js.map +1 -1
- package/dist/cli/commands/menu.d.ts.map +1 -1
- package/dist/cli/commands/menu.js +10 -184
- package/dist/cli/commands/menu.js.map +1 -1
- package/dist/cli/commands/project.d.ts +98 -0
- package/dist/cli/commands/project.d.ts.map +1 -0
- package/dist/cli/commands/project.js +382 -0
- package/dist/cli/commands/project.js.map +1 -0
- package/dist/cli/commands/skills.d.ts.map +1 -1
- package/dist/cli/commands/skills.js +14 -128
- package/dist/cli/commands/skills.js.map +1 -1
- package/dist/cli/commands/spec.d.ts +40 -0
- package/dist/cli/commands/spec.d.ts.map +1 -0
- package/dist/cli/commands/spec.js +49 -0
- package/dist/cli/commands/spec.js.map +1 -0
- package/dist/cli/commands/stats.d.ts.map +1 -1
- package/dist/cli/commands/stats.js +3 -2
- package/dist/cli/commands/stats.js.map +1 -1
- package/dist/cli/commands/status.d.ts.map +1 -1
- package/dist/cli/commands/status.js +17 -2
- package/dist/cli/commands/status.js.map +1 -1
- package/dist/cli/commands/trace.d.ts.map +1 -1
- package/dist/cli/commands/trace.js +4 -9
- package/dist/cli/commands/trace.js.map +1 -1
- package/dist/cli/commands/violations.d.ts +14 -0
- package/dist/cli/commands/violations.d.ts.map +1 -0
- package/dist/cli/commands/violations.js +43 -0
- package/dist/cli/commands/violations.js.map +1 -0
- package/dist/cli/index.js +26 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/init/hook-manager.d.ts +1 -1
- package/dist/cli/init/hook-manager.d.ts.map +1 -1
- package/dist/cli/init/hook-manager.js +6 -0
- package/dist/cli/init/hook-manager.js.map +1 -1
- package/dist/cli/utils/resolve-session.d.ts +32 -0
- package/dist/cli/utils/resolve-session.d.ts.map +1 -0
- package/dist/cli/utils/resolve-session.js +39 -0
- package/dist/cli/utils/resolve-session.js.map +1 -0
- package/dist/core/config.d.ts +4 -1
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +11 -23
- package/dist/core/config.js.map +1 -1
- package/dist/core/constants.d.ts +14 -13
- package/dist/core/constants.d.ts.map +1 -1
- package/dist/core/constants.js +20 -13
- package/dist/core/constants.js.map +1 -1
- package/dist/core/diagnostics/checks.d.ts +151 -0
- package/dist/core/diagnostics/checks.d.ts.map +1 -0
- package/dist/core/diagnostics/checks.js +765 -0
- package/dist/core/diagnostics/checks.js.map +1 -0
- package/dist/core/diagnostics/daemon-status.d.ts +77 -0
- package/dist/core/diagnostics/daemon-status.d.ts.map +1 -0
- package/dist/core/diagnostics/daemon-status.js +113 -0
- package/dist/core/diagnostics/daemon-status.js.map +1 -0
- package/dist/core/diagnostics/entropy-checks.d.ts +82 -0
- package/dist/core/diagnostics/entropy-checks.d.ts.map +1 -0
- package/dist/core/diagnostics/entropy-checks.js +395 -0
- package/dist/core/diagnostics/entropy-checks.js.map +1 -0
- package/dist/core/diagnostics/fix-runner.d.ts +54 -0
- package/dist/core/diagnostics/fix-runner.d.ts.map +1 -0
- package/dist/core/diagnostics/fix-runner.js +90 -0
- package/dist/core/diagnostics/fix-runner.js.map +1 -0
- package/dist/core/diagnostics/knip-runner.d.ts +49 -0
- package/dist/core/diagnostics/knip-runner.d.ts.map +1 -0
- package/dist/core/diagnostics/knip-runner.js +100 -0
- package/dist/core/diagnostics/knip-runner.js.map +1 -0
- package/dist/core/diagnostics/markers.d.ts +96 -0
- package/dist/core/diagnostics/markers.d.ts.map +1 -0
- package/dist/core/diagnostics/markers.js +153 -0
- package/dist/core/diagnostics/markers.js.map +1 -0
- package/dist/core/governance/global-inject.d.ts +60 -0
- package/dist/core/governance/global-inject.d.ts.map +1 -0
- package/dist/core/governance/global-inject.js +129 -0
- package/dist/core/governance/global-inject.js.map +1 -0
- package/dist/core/queue/index.d.ts +16 -3
- package/dist/core/queue/index.d.ts.map +1 -1
- package/dist/core/queue/index.js +14 -3
- package/dist/core/queue/index.js.map +1 -1
- package/dist/core/storage/base.d.ts +158 -0
- package/dist/core/storage/base.d.ts.map +1 -1
- package/dist/core/storage/base.js +570 -0
- package/dist/core/storage/base.js.map +1 -1
- package/dist/core/storage/codec/tool-input-codec.d.ts +93 -0
- package/dist/core/storage/codec/tool-input-codec.d.ts.map +1 -0
- package/dist/core/storage/codec/tool-input-codec.js +159 -0
- package/dist/core/storage/codec/tool-input-codec.js.map +1 -0
- package/dist/core/storage/decisions.d.ts +362 -0
- package/dist/core/storage/decisions.d.ts.map +1 -0
- package/dist/core/storage/decisions.js +502 -0
- package/dist/core/storage/decisions.js.map +1 -0
- package/dist/core/storage/events.d.ts +112 -8
- package/dist/core/storage/events.d.ts.map +1 -1
- package/dist/core/storage/events.js +390 -39
- package/dist/core/storage/events.js.map +1 -1
- package/dist/core/storage/feedback.d.ts +131 -0
- package/dist/core/storage/feedback.d.ts.map +1 -0
- package/dist/core/storage/feedback.js +187 -0
- package/dist/core/storage/feedback.js.map +1 -0
- package/dist/core/storage/forge-config.d.ts +40 -0
- package/dist/core/storage/forge-config.d.ts.map +1 -0
- package/dist/core/storage/forge-config.js +65 -0
- package/dist/core/storage/forge-config.js.map +1 -0
- package/dist/core/storage/injections.d.ts +28 -0
- package/dist/core/storage/injections.d.ts.map +1 -1
- package/dist/core/storage/injections.js +62 -5
- package/dist/core/storage/injections.js.map +1 -1
- package/dist/core/storage/knowledge.d.ts +106 -0
- package/dist/core/storage/knowledge.d.ts.map +1 -0
- package/dist/core/storage/knowledge.js +202 -0
- package/dist/core/storage/knowledge.js.map +1 -0
- package/dist/core/storage/maintenance.d.ts +36 -9
- package/dist/core/storage/maintenance.d.ts.map +1 -1
- package/dist/core/storage/maintenance.js +56 -24
- package/dist/core/storage/maintenance.js.map +1 -1
- package/dist/core/storage/pipeline-rollup.d.ts +117 -0
- package/dist/core/storage/pipeline-rollup.d.ts.map +1 -0
- package/dist/core/storage/pipeline-rollup.js +471 -0
- package/dist/core/storage/pipeline-rollup.js.map +1 -0
- package/dist/core/storage/routing.d.ts +16 -3
- package/dist/core/storage/routing.d.ts.map +1 -1
- package/dist/core/storage/routing.js +39 -8
- package/dist/core/storage/routing.js.map +1 -1
- package/dist/core/storage/rows.d.ts +50 -7
- package/dist/core/storage/rows.d.ts.map +1 -1
- package/dist/core/storage/schema.sql +302 -23
- package/dist/core/storage/sessions.d.ts +136 -0
- package/dist/core/storage/sessions.d.ts.map +1 -1
- package/dist/core/storage/sessions.js +351 -15
- package/dist/core/storage/sessions.js.map +1 -1
- package/dist/core/storage/skills.d.ts +1 -0
- package/dist/core/storage/skills.d.ts.map +1 -1
- package/dist/core/storage/skills.js +21 -6
- package/dist/core/storage/skills.js.map +1 -1
- package/dist/core/storage/sqlite.d.ts +253 -20
- package/dist/core/storage/sqlite.d.ts.map +1 -1
- package/dist/core/storage/sqlite.js +425 -16
- package/dist/core/storage/sqlite.js.map +1 -1
- package/dist/core/storage/tasks.d.ts +474 -2
- package/dist/core/storage/tasks.d.ts.map +1 -1
- package/dist/core/storage/tasks.js +1213 -18
- package/dist/core/storage/tasks.js.map +1 -1
- package/dist/core/storage/tool-intercepts.d.ts +69 -0
- package/dist/core/storage/tool-intercepts.d.ts.map +1 -0
- package/dist/core/storage/tool-intercepts.js +116 -0
- package/dist/core/storage/tool-intercepts.js.map +1 -0
- package/dist/core/storage/workflow-recommendations.d.ts +124 -0
- package/dist/core/storage/workflow-recommendations.d.ts.map +1 -0
- package/dist/core/storage/workflow-recommendations.js +274 -0
- package/dist/core/storage/workflow-recommendations.js.map +1 -0
- package/dist/core/types.d.ts +112 -17
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +12 -0
- package/dist/core/types.js.map +1 -1
- package/dist/core/utils/backup.d.ts +81 -0
- package/dist/core/utils/backup.d.ts.map +1 -0
- package/dist/core/utils/backup.js +98 -0
- package/dist/core/utils/backup.js.map +1 -0
- package/dist/core/utils/binary-paths.d.ts +92 -0
- package/dist/core/utils/binary-paths.d.ts.map +1 -0
- package/dist/core/utils/binary-paths.js +166 -0
- package/dist/core/utils/binary-paths.js.map +1 -0
- package/dist/core/utils/bypass-token.d.ts +75 -0
- package/dist/core/utils/bypass-token.d.ts.map +1 -0
- package/dist/core/utils/bypass-token.js +133 -0
- package/dist/core/utils/bypass-token.js.map +1 -0
- package/dist/core/utils/cc-builtin-agents.d.ts +3 -0
- package/dist/core/utils/cc-builtin-agents.d.ts.map +1 -0
- package/dist/core/utils/cc-builtin-agents.js +29 -0
- package/dist/core/utils/cc-builtin-agents.js.map +1 -0
- package/dist/core/utils/claude-cli-spawn.d.ts +106 -0
- package/dist/core/utils/claude-cli-spawn.d.ts.map +1 -0
- package/dist/core/utils/claude-cli-spawn.js +219 -0
- package/dist/core/utils/claude-cli-spawn.js.map +1 -0
- package/dist/core/utils/forge-resume-block.d.ts.map +1 -1
- package/dist/core/utils/forge-resume-block.js +3 -2
- package/dist/core/utils/forge-resume-block.js.map +1 -1
- package/dist/core/utils/logger.d.ts +15 -3
- package/dist/core/utils/logger.d.ts.map +1 -1
- package/dist/core/utils/logger.js +20 -2
- package/dist/core/utils/logger.js.map +1 -1
- package/dist/core/utils/noise-prompt.d.ts +97 -0
- package/dist/core/utils/noise-prompt.d.ts.map +1 -0
- package/dist/core/utils/noise-prompt.js +127 -0
- package/dist/core/utils/noise-prompt.js.map +1 -0
- package/dist/core/utils/path.d.ts +0 -4
- package/dist/core/utils/path.d.ts.map +1 -1
- package/dist/core/utils/path.js +0 -7
- package/dist/core/utils/path.js.map +1 -1
- package/dist/core/utils/time.d.ts +41 -0
- package/dist/core/utils/time.d.ts.map +1 -1
- package/dist/core/utils/time.js +114 -0
- package/dist/core/utils/time.js.map +1 -1
- package/dist/daemon/agent-sync.d.ts +24 -0
- package/dist/daemon/agent-sync.d.ts.map +1 -0
- package/dist/daemon/agent-sync.js +114 -0
- package/dist/daemon/agent-sync.js.map +1 -0
- package/dist/daemon/config-store.d.ts +55 -0
- package/dist/daemon/config-store.d.ts.map +1 -0
- package/dist/daemon/config-store.js +137 -0
- package/dist/daemon/config-store.js.map +1 -0
- package/dist/daemon/event-parser.d.ts +22 -0
- package/dist/daemon/event-parser.d.ts.map +1 -1
- package/dist/daemon/event-parser.js +49 -3
- package/dist/daemon/event-parser.js.map +1 -1
- package/dist/daemon/handlers/history-exporter.d.ts.map +1 -1
- package/dist/daemon/handlers/history-exporter.js +9 -8
- package/dist/daemon/handlers/history-exporter.js.map +1 -1
- package/dist/daemon/handlers/post-tool-use.d.ts +58 -4
- package/dist/daemon/handlers/post-tool-use.d.ts.map +1 -1
- package/dist/daemon/handlers/post-tool-use.js +261 -8
- package/dist/daemon/handlers/post-tool-use.js.map +1 -1
- package/dist/daemon/handlers/pre-tool-use.d.ts +156 -0
- package/dist/daemon/handlers/pre-tool-use.d.ts.map +1 -0
- package/dist/daemon/handlers/pre-tool-use.js +585 -0
- package/dist/daemon/handlers/pre-tool-use.js.map +1 -0
- package/dist/daemon/handlers/stop.d.ts +35 -7
- package/dist/daemon/handlers/stop.d.ts.map +1 -1
- package/dist/daemon/handlers/stop.js +157 -8
- package/dist/daemon/handlers/stop.js.map +1 -1
- package/dist/daemon/handlers/user-prompt.d.ts +36 -14
- package/dist/daemon/handlers/user-prompt.d.ts.map +1 -1
- package/dist/daemon/handlers/user-prompt.js +135 -48
- package/dist/daemon/handlers/user-prompt.js.map +1 -1
- package/dist/daemon/hook-sync.d.ts.map +1 -1
- package/dist/daemon/hook-sync.js +2 -1
- package/dist/daemon/hook-sync.js.map +1 -1
- package/dist/daemon/index.d.ts.map +1 -1
- package/dist/daemon/index.js +471 -43
- package/dist/daemon/index.js.map +1 -1
- package/dist/daemon/lifecycle.d.ts +48 -1
- package/dist/daemon/lifecycle.d.ts.map +1 -1
- package/dist/daemon/lifecycle.js +98 -2
- package/dist/daemon/lifecycle.js.map +1 -1
- package/dist/daemon/router.d.ts +4 -1
- package/dist/daemon/router.d.ts.map +1 -1
- package/dist/daemon/router.js +4 -2
- package/dist/daemon/router.js.map +1 -1
- package/dist/daemon/rules/defaults.d.ts +20 -0
- package/dist/daemon/rules/defaults.d.ts.map +1 -0
- package/dist/daemon/rules/defaults.js +692 -0
- package/dist/daemon/rules/defaults.js.map +1 -0
- package/dist/daemon/rules/registry.d.ts +47 -0
- package/dist/daemon/rules/registry.d.ts.map +1 -0
- package/dist/daemon/rules/registry.js +84 -0
- package/dist/daemon/rules/registry.js.map +1 -0
- package/dist/daemon/rules/types.d.ts +170 -0
- package/dist/daemon/rules/types.d.ts.map +1 -0
- package/dist/daemon/rules/types.js +15 -0
- package/dist/daemon/rules/types.js.map +1 -0
- package/dist/daemon/rules/whitelist.d.ts +101 -0
- package/dist/daemon/rules/whitelist.d.ts.map +1 -0
- package/dist/daemon/rules/whitelist.js +210 -0
- package/dist/daemon/rules/whitelist.js.map +1 -0
- package/dist/daemon/rules/workflow-defaults.d.ts +52 -0
- package/dist/daemon/rules/workflow-defaults.d.ts.map +1 -0
- package/dist/daemon/rules/workflow-defaults.js +521 -0
- package/dist/daemon/rules/workflow-defaults.js.map +1 -0
- package/dist/daemon/server.d.ts +11 -1
- package/dist/daemon/server.d.ts.map +1 -1
- package/dist/daemon/server.js +7 -1
- package/dist/daemon/server.js.map +1 -1
- package/dist/daemon/services/context-injector.d.ts +34 -0
- package/dist/daemon/services/context-injector.d.ts.map +1 -0
- package/dist/daemon/services/context-injector.js +61 -0
- package/dist/daemon/services/context-injector.js.map +1 -0
- package/dist/daemon/services/decision-hint.d.ts +203 -0
- package/dist/daemon/services/decision-hint.d.ts.map +1 -0
- package/dist/daemon/services/decision-hint.js +487 -0
- package/dist/daemon/services/decision-hint.js.map +1 -0
- package/dist/daemon/services/event-ttl-sweep.d.ts +86 -0
- package/dist/daemon/services/event-ttl-sweep.d.ts.map +1 -0
- package/dist/daemon/services/event-ttl-sweep.js +123 -0
- package/dist/daemon/services/event-ttl-sweep.js.map +1 -0
- package/dist/daemon/services/experience-extractor.d.ts +67 -0
- package/dist/daemon/services/experience-extractor.d.ts.map +1 -0
- package/dist/daemon/services/experience-extractor.js +323 -0
- package/dist/daemon/services/experience-extractor.js.map +1 -0
- package/dist/daemon/services/feedback-aggregator.d.ts +179 -0
- package/dist/daemon/services/feedback-aggregator.d.ts.map +1 -0
- package/dist/daemon/services/feedback-aggregator.js +455 -0
- package/dist/daemon/services/feedback-aggregator.js.map +1 -0
- package/dist/daemon/services/heartbeat-writer.d.ts +55 -0
- package/dist/daemon/services/heartbeat-writer.d.ts.map +1 -0
- package/dist/daemon/services/heartbeat-writer.js +111 -0
- package/dist/daemon/services/heartbeat-writer.js.map +1 -0
- package/dist/daemon/services/idle-session-sweeper.d.ts +61 -0
- package/dist/daemon/services/idle-session-sweeper.d.ts.map +1 -0
- package/dist/daemon/services/idle-session-sweeper.js +94 -0
- package/dist/daemon/services/idle-session-sweeper.js.map +1 -0
- package/dist/daemon/services/idle-task-budget.d.ts +50 -0
- package/dist/daemon/services/idle-task-budget.d.ts.map +1 -0
- package/dist/daemon/services/idle-task-budget.js +72 -0
- package/dist/daemon/services/idle-task-budget.js.map +1 -0
- package/dist/daemon/services/intercept-revive.d.ts +60 -0
- package/dist/daemon/services/intercept-revive.d.ts.map +1 -0
- package/dist/daemon/services/intercept-revive.js +86 -0
- package/dist/daemon/services/intercept-revive.js.map +1 -0
- package/dist/daemon/services/intercept-rollback-guard.d.ts +105 -0
- package/dist/daemon/services/intercept-rollback-guard.d.ts.map +1 -0
- package/dist/daemon/services/intercept-rollback-guard.js +152 -0
- package/dist/daemon/services/intercept-rollback-guard.js.map +1 -0
- package/dist/daemon/services/intercept-timeout-sweeper.d.ts +58 -0
- package/dist/daemon/services/intercept-timeout-sweeper.d.ts.map +1 -0
- package/dist/daemon/services/intercept-timeout-sweeper.js +83 -0
- package/dist/daemon/services/intercept-timeout-sweeper.js.map +1 -0
- package/dist/daemon/services/kb-injector.d.ts +57 -0
- package/dist/daemon/services/kb-injector.d.ts.map +1 -0
- package/dist/daemon/services/kb-injector.js +140 -0
- package/dist/daemon/services/kb-injector.js.map +1 -0
- package/dist/daemon/services/outcome-classification-service.d.ts +49 -0
- package/dist/daemon/services/outcome-classification-service.d.ts.map +1 -0
- package/dist/daemon/services/outcome-classification-service.js +214 -0
- package/dist/daemon/services/outcome-classification-service.js.map +1 -0
- package/dist/daemon/services/outcome-classifier.d.ts +136 -0
- package/dist/daemon/services/outcome-classifier.d.ts.map +1 -0
- package/dist/daemon/services/outcome-classifier.js +178 -0
- package/dist/daemon/services/outcome-classifier.js.map +1 -0
- package/dist/daemon/services/outcome-nudge.d.ts +107 -0
- package/dist/daemon/services/outcome-nudge.d.ts.map +1 -0
- package/dist/daemon/services/outcome-nudge.js +242 -0
- package/dist/daemon/services/outcome-nudge.js.map +1 -0
- package/dist/daemon/services/spec-approval.d.ts +127 -0
- package/dist/daemon/services/spec-approval.d.ts.map +1 -0
- package/dist/daemon/services/spec-approval.js +216 -0
- package/dist/daemon/services/spec-approval.js.map +1 -0
- package/dist/daemon/services/spec-gate.d.ts +54 -0
- package/dist/daemon/services/spec-gate.d.ts.map +1 -0
- package/dist/daemon/services/spec-gate.js +113 -0
- package/dist/daemon/services/spec-gate.js.map +1 -0
- package/dist/daemon/services/task-boundary-classifier.d.ts +78 -0
- package/dist/daemon/services/task-boundary-classifier.d.ts.map +1 -0
- package/dist/daemon/services/task-boundary-classifier.js +202 -0
- package/dist/daemon/services/task-boundary-classifier.js.map +1 -0
- package/dist/daemon/services/task-segmenter.d.ts +219 -1
- package/dist/daemon/services/task-segmenter.d.ts.map +1 -1
- package/dist/daemon/services/task-segmenter.js +481 -17
- package/dist/daemon/services/task-segmenter.js.map +1 -1
- package/dist/daemon/services/violation-reporter.d.ts +130 -0
- package/dist/daemon/services/violation-reporter.d.ts.map +1 -0
- package/dist/daemon/services/violation-reporter.js +339 -0
- package/dist/daemon/services/violation-reporter.js.map +1 -0
- package/dist/daemon/skill-sync.d.ts +7 -2
- package/dist/daemon/skill-sync.d.ts.map +1 -1
- package/dist/daemon/skill-sync.js +114 -9
- package/dist/daemon/skill-sync.js.map +1 -1
- package/dist/daemon/templates/agents/claudemd-writer.md +101 -0
- package/dist/daemon/templates/agents/coder.md +105 -0
- package/dist/daemon/templates/agents/decision-maker.md +460 -0
- package/dist/daemon/templates/agents/doc-reviewer.md +115 -0
- package/dist/daemon/templates/agents/harness-debug-full.md +114 -0
- package/dist/daemon/templates/agents/harness-hotfix.md +99 -0
- package/dist/daemon/templates/agents/hybrid-feature-with-safety.md +104 -0
- package/dist/daemon/templates/agents/knowledge-builder.md +119 -0
- package/dist/daemon/templates/agents/patch-applier.md +144 -0
- package/dist/daemon/templates/agents/planner.md +165 -0
- package/dist/daemon/templates/agents/refactor-specialist.md +98 -0
- package/dist/daemon/templates/agents/skill-distiller.md +113 -0
- package/dist/daemon/templates/agents/task-boundary-classifier.md +64 -0
- package/dist/daemon/templates/agents/verify-agent.md +136 -0
- package/dist/daemon/utils/inject-block.d.ts +39 -0
- package/dist/daemon/utils/inject-block.d.ts.map +1 -0
- package/dist/daemon/utils/inject-block.js +25 -0
- package/dist/daemon/utils/inject-block.js.map +1 -0
- package/dist/hooks/hook-lib.sh +8 -0
- package/dist/hooks/notification.sh +19 -8
- package/dist/hooks/post-tool-use.sh +41 -23
- package/dist/hooks/pre-tool-use.sh +54 -23
- package/dist/hooks/session-start.sh +68 -0
- package/dist/hooks/stop.sh +24 -10
- package/dist/hooks/user-prompt-submit.sh +37 -21
- package/dist/knowledge/adapters/go-adapter.d.ts +65 -0
- package/dist/knowledge/adapters/go-adapter.d.ts.map +1 -0
- package/dist/knowledge/adapters/go-adapter.js +294 -0
- package/dist/knowledge/adapters/go-adapter.js.map +1 -0
- package/dist/knowledge/adapters/index.d.ts +41 -0
- package/dist/knowledge/adapters/index.d.ts.map +1 -0
- package/dist/knowledge/adapters/index.js +71 -0
- package/dist/knowledge/adapters/index.js.map +1 -0
- package/dist/knowledge/adapters/java-adapter.d.ts +66 -0
- package/dist/knowledge/adapters/java-adapter.d.ts.map +1 -0
- package/dist/knowledge/adapters/java-adapter.js +260 -0
- package/dist/knowledge/adapters/java-adapter.js.map +1 -0
- package/dist/knowledge/adapters/js-vue-adapter.d.ts +56 -0
- package/dist/knowledge/adapters/js-vue-adapter.d.ts.map +1 -0
- package/dist/knowledge/adapters/js-vue-adapter.js +203 -0
- package/dist/knowledge/adapters/js-vue-adapter.js.map +1 -0
- package/dist/knowledge/adapters/kotlin-adapter.d.ts +55 -0
- package/dist/knowledge/adapters/kotlin-adapter.d.ts.map +1 -0
- package/dist/knowledge/adapters/kotlin-adapter.js +209 -0
- package/dist/knowledge/adapters/kotlin-adapter.js.map +1 -0
- package/dist/knowledge/adapters/monorepo-adapter.d.ts +77 -0
- package/dist/knowledge/adapters/monorepo-adapter.d.ts.map +1 -0
- package/dist/knowledge/adapters/monorepo-adapter.js +170 -0
- package/dist/knowledge/adapters/monorepo-adapter.js.map +1 -0
- package/dist/knowledge/adapters/python-adapter.d.ts +89 -0
- package/dist/knowledge/adapters/python-adapter.d.ts.map +1 -0
- package/dist/knowledge/adapters/python-adapter.js +358 -0
- package/dist/knowledge/adapters/python-adapter.js.map +1 -0
- package/dist/knowledge/adapters/rust-adapter.d.ts +73 -0
- package/dist/knowledge/adapters/rust-adapter.d.ts.map +1 -0
- package/dist/knowledge/adapters/rust-adapter.js +329 -0
- package/dist/knowledge/adapters/rust-adapter.js.map +1 -0
- package/dist/knowledge/adapters/types.d.ts +99 -0
- package/dist/knowledge/adapters/types.d.ts.map +1 -0
- package/dist/knowledge/adapters/types.js +17 -0
- package/dist/knowledge/adapters/types.js.map +1 -0
- package/dist/knowledge/adapters/typescript-adapter.d.ts +57 -0
- package/dist/knowledge/adapters/typescript-adapter.d.ts.map +1 -0
- package/dist/knowledge/adapters/typescript-adapter.js +171 -0
- package/dist/knowledge/adapters/typescript-adapter.js.map +1 -0
- package/dist/knowledge/audit-applier.d.ts +70 -0
- package/dist/knowledge/audit-applier.d.ts.map +1 -0
- package/dist/knowledge/audit-applier.js +251 -0
- package/dist/knowledge/audit-applier.js.map +1 -0
- package/dist/knowledge/builder.d.ts +261 -0
- package/dist/knowledge/builder.d.ts.map +1 -0
- package/dist/knowledge/builder.js +937 -0
- package/dist/knowledge/builder.js.map +1 -0
- package/dist/knowledge/cli-provider.d.ts +151 -0
- package/dist/knowledge/cli-provider.d.ts.map +1 -0
- package/dist/knowledge/cli-provider.js +313 -0
- package/dist/knowledge/cli-provider.js.map +1 -0
- package/dist/knowledge/constants.d.ts +73 -0
- package/dist/knowledge/constants.d.ts.map +1 -0
- package/dist/knowledge/constants.js +93 -0
- package/dist/knowledge/constants.js.map +1 -0
- package/dist/knowledge/cross-module.d.ts +139 -0
- package/dist/knowledge/cross-module.d.ts.map +1 -0
- package/dist/knowledge/cross-module.js +370 -0
- package/dist/knowledge/cross-module.js.map +1 -0
- package/dist/knowledge/git-hooks.d.ts +67 -0
- package/dist/knowledge/git-hooks.d.ts.map +1 -0
- package/dist/knowledge/git-hooks.js +258 -0
- package/dist/knowledge/git-hooks.js.map +1 -0
- package/dist/knowledge/module-hash.d.ts +88 -0
- package/dist/knowledge/module-hash.d.ts.map +1 -0
- package/dist/knowledge/module-hash.js +162 -0
- package/dist/knowledge/module-hash.js.map +1 -0
- package/dist/knowledge/project-detector.d.ts +101 -0
- package/dist/knowledge/project-detector.d.ts.map +1 -0
- package/dist/knowledge/project-detector.js +223 -0
- package/dist/knowledge/project-detector.js.map +1 -0
- package/dist/knowledge/prompt.d.ts +228 -0
- package/dist/knowledge/prompt.d.ts.map +1 -0
- package/dist/knowledge/prompt.js +404 -0
- package/dist/knowledge/prompt.js.map +1 -0
- package/dist/knowledge/query.d.ts +105 -0
- package/dist/knowledge/query.d.ts.map +1 -0
- package/dist/knowledge/query.js +341 -0
- package/dist/knowledge/query.js.map +1 -0
- package/dist/knowledge/repo-map.d.ts +91 -0
- package/dist/knowledge/repo-map.d.ts.map +1 -0
- package/dist/knowledge/repo-map.js +408 -0
- package/dist/knowledge/repo-map.js.map +1 -0
- package/dist/knowledge/tools/index.d.ts +14 -0
- package/dist/knowledge/tools/index.d.ts.map +1 -0
- package/dist/knowledge/tools/index.js +11 -0
- package/dist/knowledge/tools/index.js.map +1 -0
- package/dist/knowledge/tools/knowledge-get-page.d.ts +46 -0
- package/dist/knowledge/tools/knowledge-get-page.d.ts.map +1 -0
- package/dist/knowledge/tools/knowledge-get-page.js +101 -0
- package/dist/knowledge/tools/knowledge-get-page.js.map +1 -0
- package/dist/knowledge/tools/knowledge-query.d.ts +77 -0
- package/dist/knowledge/tools/knowledge-query.d.ts.map +1 -0
- package/dist/knowledge/tools/knowledge-query.js +104 -0
- package/dist/knowledge/tools/knowledge-query.js.map +1 -0
- package/dist/knowledge/tools/repo-map-lookup.d.ts +45 -0
- package/dist/knowledge/tools/repo-map-lookup.d.ts.map +1 -0
- package/dist/knowledge/tools/repo-map-lookup.js +82 -0
- package/dist/knowledge/tools/repo-map-lookup.js.map +1 -0
- package/dist/knowledge/types.d.ts +269 -0
- package/dist/knowledge/types.d.ts.map +1 -0
- package/dist/knowledge/types.js +10 -0
- package/dist/knowledge/types.js.map +1 -0
- package/dist/knowledge/validator.d.ts +90 -0
- package/dist/knowledge/validator.d.ts.map +1 -0
- package/dist/knowledge/validator.js +288 -0
- package/dist/knowledge/validator.js.map +1 -0
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +222 -1
- package/dist/mcp/server.js.map +1 -1
- package/dist/skills/builtin-skills.d.ts +35 -0
- package/dist/skills/builtin-skills.d.ts.map +1 -0
- package/dist/skills/builtin-skills.js +68 -0
- package/dist/skills/builtin-skills.js.map +1 -0
- package/dist/skills/distill/attribution.d.ts +59 -0
- package/dist/skills/distill/attribution.d.ts.map +1 -0
- package/dist/skills/distill/attribution.js +101 -0
- package/dist/skills/distill/attribution.js.map +1 -0
- package/dist/skills/distill/claude-cli-resolver.d.ts +26 -0
- package/dist/skills/distill/claude-cli-resolver.d.ts.map +1 -0
- package/dist/skills/distill/claude-cli-resolver.js +115 -0
- package/dist/skills/distill/claude-cli-resolver.js.map +1 -0
- package/dist/skills/distill/distiller.d.ts +161 -0
- package/dist/skills/distill/distiller.d.ts.map +1 -0
- package/dist/skills/distill/distiller.js +461 -0
- package/dist/skills/distill/distiller.js.map +1 -0
- package/dist/skills/distill/index.d.ts +223 -0
- package/dist/skills/distill/index.d.ts.map +1 -0
- package/dist/skills/distill/index.js +466 -0
- package/dist/skills/distill/index.js.map +1 -0
- package/dist/skills/distill/project-anchor-guard.d.ts +116 -0
- package/dist/skills/distill/project-anchor-guard.d.ts.map +1 -0
- package/dist/skills/distill/project-anchor-guard.js +334 -0
- package/dist/skills/distill/project-anchor-guard.js.map +1 -0
- package/dist/skills/distill/topic-deduper.d.ts +77 -0
- package/dist/skills/distill/topic-deduper.d.ts.map +1 -0
- package/dist/skills/distill/topic-deduper.js +119 -0
- package/dist/skills/distill/topic-deduper.js.map +1 -0
- package/dist/skills/distill/upstream-fetcher.d.ts +71 -0
- package/dist/skills/distill/upstream-fetcher.d.ts.map +1 -0
- package/dist/skills/distill/upstream-fetcher.js +202 -0
- package/dist/skills/distill/upstream-fetcher.js.map +1 -0
- package/dist/skills/distilled/distilled-api-design.md +491 -0
- package/dist/skills/distilled/distilled-architecture-decision.md +173 -0
- package/dist/skills/distilled/distilled-creator.md +178 -0
- package/dist/skills/distilled/distilled-db-schema-design.md +245 -0
- package/dist/skills/distilled/distilled-defi-amm-security.md +293 -0
- package/dist/skills/distilled/distilled-executing-plans.md +113 -0
- package/dist/skills/distilled/distilled-harness-engineering.md +242 -0
- package/dist/skills/distilled/distilled-karpathy-guidelines.md +104 -0
- package/dist/skills/distilled/distilled-performance-optimization.md +175 -0
- package/dist/skills/distilled/distilled-spec-driven-design.md +193 -0
- package/dist/skills/distilled/distilled-systematic-debugging.md +306 -0
- package/dist/skills/distilled/distilled-verification-before-completion.md +203 -0
- package/dist/skills/keyword-score.d.ts +29 -0
- package/dist/skills/keyword-score.d.ts.map +1 -0
- package/dist/skills/keyword-score.js +54 -0
- package/dist/skills/keyword-score.js.map +1 -0
- package/dist/skills/registry.d.ts +64 -20
- package/dist/skills/registry.d.ts.map +1 -1
- package/dist/skills/registry.js +102 -105
- package/dist/skills/registry.js.map +1 -1
- package/dist/skills/tools/pipeline-suggest.js +14 -14
- package/dist/skills/tools/skill-invoke.d.ts +1 -1
- package/dist/skills/tools/skill-invoke.js +1 -1
- package/dist/web/routes/agent-content.d.ts +30 -0
- package/dist/web/routes/agent-content.d.ts.map +1 -0
- package/dist/web/routes/agent-content.js +139 -0
- package/dist/web/routes/agent-content.js.map +1 -0
- package/dist/web/routes/decisions.d.ts +15 -0
- package/dist/web/routes/decisions.d.ts.map +1 -0
- package/dist/web/routes/decisions.js +181 -0
- package/dist/web/routes/decisions.js.map +1 -0
- package/dist/web/routes/diagnostics.d.ts +61 -0
- package/dist/web/routes/diagnostics.d.ts.map +1 -0
- package/dist/web/routes/diagnostics.js +203 -0
- package/dist/web/routes/diagnostics.js.map +1 -0
- package/dist/web/routes/events.d.ts.map +1 -1
- package/dist/web/routes/events.js +24 -0
- package/dist/web/routes/events.js.map +1 -1
- package/dist/web/routes/health.d.ts +33 -0
- package/dist/web/routes/health.d.ts.map +1 -0
- package/dist/web/routes/health.js +37 -0
- package/dist/web/routes/health.js.map +1 -0
- package/dist/web/routes/insights.d.ts +0 -5
- package/dist/web/routes/insights.d.ts.map +1 -1
- package/dist/web/routes/insights.js +783 -2
- package/dist/web/routes/insights.js.map +1 -1
- package/dist/web/routes/knowledge.d.ts +16 -0
- package/dist/web/routes/knowledge.d.ts.map +1 -0
- package/dist/web/routes/knowledge.js +661 -0
- package/dist/web/routes/knowledge.js.map +1 -0
- package/dist/web/routes/patch.d.ts +60 -1
- package/dist/web/routes/patch.d.ts.map +1 -1
- package/dist/web/routes/patch.js +170 -64
- package/dist/web/routes/patch.js.map +1 -1
- package/dist/web/routes/pipeline.d.ts +37 -0
- package/dist/web/routes/pipeline.d.ts.map +1 -0
- package/dist/web/routes/pipeline.js +149 -0
- package/dist/web/routes/pipeline.js.map +1 -0
- package/dist/web/routes/rules.d.ts.map +1 -1
- package/dist/web/routes/rules.js +6 -1
- package/dist/web/routes/rules.js.map +1 -1
- package/dist/web/routes/sessions.d.ts.map +1 -1
- package/dist/web/routes/sessions.js +9 -1
- package/dist/web/routes/sessions.js.map +1 -1
- package/dist/web/routes/skill-content.d.ts +30 -0
- package/dist/web/routes/skill-content.d.ts.map +1 -0
- package/dist/web/routes/skill-content.js +117 -0
- package/dist/web/routes/skill-content.js.map +1 -0
- package/dist/web/routes/skills-distill.d.ts +29 -0
- package/dist/web/routes/skills-distill.d.ts.map +1 -0
- package/dist/web/routes/skills-distill.js +552 -0
- package/dist/web/routes/skills-distill.js.map +1 -0
- package/dist/web/routes/skills.js +7 -7
- package/dist/web/routes/skills.js.map +1 -1
- package/dist/web/routes/task-timeline.d.ts +102 -0
- package/dist/web/routes/task-timeline.d.ts.map +1 -0
- package/dist/web/routes/task-timeline.js +274 -0
- package/dist/web/routes/task-timeline.js.map +1 -0
- package/dist/web/routes/tasks.d.ts.map +1 -1
- package/dist/web/routes/tasks.js +355 -8
- package/dist/web/routes/tasks.js.map +1 -1
- package/dist/web/routes/trace.d.ts.map +1 -1
- package/dist/web/routes/trace.js +3 -2
- package/dist/web/routes/trace.js.map +1 -1
- package/dist/web/routes/types.d.ts +0 -4
- package/dist/web/routes/types.d.ts.map +1 -1
- package/dist/web/routes/types.js +1 -1
- package/dist/web/routes/types.js.map +1 -1
- package/dist/web/routes/violations.d.ts +14 -0
- package/dist/web/routes/violations.d.ts.map +1 -0
- package/dist/web/routes/violations.js +111 -0
- package/dist/web/routes/violations.js.map +1 -0
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +79 -19
- package/dist/web/server.js.map +1 -1
- package/dist/web/services/build-manager.d.ts +72 -0
- package/dist/web/services/build-manager.d.ts.map +1 -0
- package/dist/web/services/build-manager.js +189 -0
- package/dist/web/services/build-manager.js.map +1 -0
- package/dist/web/services/distill-manager.d.ts +125 -0
- package/dist/web/services/distill-manager.d.ts.map +1 -0
- package/dist/web/services/distill-manager.js +308 -0
- package/dist/web/services/distill-manager.js.map +1 -0
- package/dist/web/static/assets/AgentContentPage-DkeRNxok.js +2 -0
- package/dist/web/static/assets/AgentContentPage-DkeRNxok.js.map +1 -0
- package/dist/web/static/assets/AgentDelegationTable-ByBa0x1l.js +2 -0
- package/dist/web/static/assets/AgentDelegationTable-ByBa0x1l.js.map +1 -0
- package/dist/web/static/assets/ContextInsightsPage-oUk7_I8u.js +3 -0
- package/dist/web/static/assets/ContextInsightsPage-oUk7_I8u.js.map +1 -0
- package/dist/web/static/assets/DaemonHealthPage-DG2fyOP7.js +2 -0
- package/dist/web/static/assets/DaemonHealthPage-DG2fyOP7.js.map +1 -0
- package/dist/web/static/assets/DecisionsPage-CMAPEnKb.js +2 -0
- package/dist/web/static/assets/DecisionsPage-CMAPEnKb.js.map +1 -0
- package/dist/web/static/assets/DiagnosticsPage-DQd-Zm4r.js +2 -0
- package/dist/web/static/assets/DiagnosticsPage-DQd-Zm4r.js.map +1 -0
- package/dist/web/static/assets/DriftTab-DqpepOhI.js +2 -0
- package/dist/web/static/assets/DriftTab-DqpepOhI.js.map +1 -0
- package/dist/web/static/assets/HealthHomePage-CN6zNIie.js +3 -0
- package/dist/web/static/assets/HealthHomePage-CN6zNIie.js.map +1 -0
- package/dist/web/static/assets/KbHitRateTable-ByEIWujF.js +2 -0
- package/dist/web/static/assets/KbHitRateTable-ByEIWujF.js.map +1 -0
- package/dist/web/static/assets/MarkdownRenderer-DZmTl-8J.js +3 -0
- package/dist/web/static/assets/MarkdownRenderer-DZmTl-8J.js.map +1 -0
- package/dist/web/static/assets/NotFound-BQPh0vaF.js +2 -0
- package/dist/web/static/assets/NotFound-BQPh0vaF.js.map +1 -0
- package/dist/web/static/assets/ProjectSwitcher-D3lZMFd3.js +2 -0
- package/dist/web/static/assets/ProjectSwitcher-D3lZMFd3.js.map +1 -0
- package/dist/web/static/assets/SettingsPage-oLJBNzQj.js +2 -0
- package/dist/web/static/assets/SettingsPage-oLJBNzQj.js.map +1 -0
- package/dist/web/static/assets/SkillContentPage-DK5rgfgw.js +2 -0
- package/dist/web/static/assets/SkillContentPage-DK5rgfgw.js.map +1 -0
- package/dist/web/static/assets/SkillStatsTable-DYMzjEUV.js +2 -0
- package/dist/web/static/assets/SkillStatsTable-DYMzjEUV.js.map +1 -0
- package/dist/web/static/assets/SkillsDistillTab-C7qaG8q3.js +2 -0
- package/dist/web/static/assets/SkillsDistillTab-C7qaG8q3.js.map +1 -0
- package/dist/web/static/assets/TasksHubPage-03wsRRsJ.js +6 -0
- package/dist/web/static/assets/TasksHubPage-03wsRRsJ.js.map +1 -0
- package/dist/web/static/assets/ViolationsPage-DSiLr-9O.js +3 -0
- package/dist/web/static/assets/ViolationsPage-DSiLr-9O.js.map +1 -0
- package/dist/web/static/assets/arco-Bhi3a6Qp.js +14 -0
- package/dist/web/static/assets/arco-Bhi3a6Qp.js.map +1 -0
- package/dist/web/static/assets/arco-DFQA6dO_.css +1 -0
- package/dist/web/static/assets/charts-BuHQWDbQ.js +37 -0
- package/dist/web/static/assets/charts-BuHQWDbQ.js.map +1 -0
- package/dist/web/static/assets/date-fns-sbWH3_uq.js +2 -0
- package/dist/web/static/assets/date-fns-sbWH3_uq.js.map +1 -0
- package/dist/web/static/assets/index-7bl3kbcx.css +1 -0
- package/dist/web/static/assets/index-BIYnq1Dx.js +4 -0
- package/dist/web/static/assets/index-BIYnq1Dx.js.map +1 -0
- package/dist/web/static/assets/lucide-CnlPQoG8.js +72 -0
- package/dist/web/static/assets/lucide-CnlPQoG8.js.map +1 -0
- package/dist/web/static/assets/outcome-DUn1NjlC.js +2 -0
- package/dist/web/static/assets/outcome-DUn1NjlC.js.map +1 -0
- package/dist/web/static/assets/query-S6X1S7K9.js +2 -0
- package/dist/web/static/assets/{query-C99w429o.js.map → query-S6X1S7K9.js.map} +1 -1
- package/dist/web/static/assets/{react-router-r79dBVy4.js → react-router-JVUrkhdd.js} +3 -3
- package/dist/web/static/assets/{react-router-r79dBVy4.js.map → react-router-JVUrkhdd.js.map} +1 -1
- package/dist/web/static/assets/react-vendor-tkvCrao7.js +57 -0
- package/dist/web/static/assets/react-vendor-tkvCrao7.js.map +1 -0
- package/dist/web/static/assets/syntax-highlighter-BkZfCDsz.js +6 -0
- package/dist/web/static/assets/syntax-highlighter-BkZfCDsz.js.map +1 -0
- package/dist/web/static/assets/useTabsParam-k8qte_0C.js +2 -0
- package/dist/web/static/assets/useTabsParam-k8qte_0C.js.map +1 -0
- package/dist/web/static/assets/vendor-DWgdB1eY.js +65 -0
- package/dist/web/static/assets/vendor-DWgdB1eY.js.map +1 -0
- package/dist/web/static/index.html +12 -8
- package/package.json +14 -3
- package/dist/core/ai/provider.d.ts +0 -63
- package/dist/core/ai/provider.d.ts.map +0 -1
- package/dist/core/ai/provider.js +0 -241
- package/dist/core/ai/provider.js.map +0 -1
- package/dist/core/ai/types.d.ts +0 -43
- package/dist/core/ai/types.d.ts.map +0 -1
- package/dist/core/ai/types.js +0 -5
- package/dist/core/ai/types.js.map +0 -1
- package/dist/core/storage/token-usage.d.ts +0 -36
- package/dist/core/storage/token-usage.d.ts.map +0 -1
- package/dist/core/storage/token-usage.js +0 -59
- package/dist/core/storage/token-usage.js.map +0 -1
- package/dist/core/utils/token-tracker.d.ts +0 -39
- package/dist/core/utils/token-tracker.d.ts.map +0 -1
- package/dist/core/utils/token-tracker.js +0 -69
- package/dist/core/utils/token-tracker.js.map +0 -1
- package/dist/skills/index.d.ts +0 -3
- package/dist/skills/index.d.ts.map +0 -1
- package/dist/skills/index.js +0 -3
- package/dist/skills/index.js.map +0 -1
- package/dist/skills/matcher.d.ts +0 -26
- package/dist/skills/matcher.d.ts.map +0 -1
- package/dist/skills/matcher.js +0 -113
- package/dist/skills/matcher.js.map +0 -1
- package/dist/skills/official/code-simplifier.md +0 -52
- package/dist/skills/official/find-skills.md +0 -142
- package/dist/skills/official/official-api-design.md +0 -30
- package/dist/skills/official/official-architecture-decision.md +0 -41
- package/dist/skills/official/official-bmad.md +0 -118
- package/dist/skills/official/official-db-schema-design.md +0 -34
- package/dist/skills/official/official-debug.md +0 -25
- package/dist/skills/official/official-doc-driven.md +0 -31
- package/dist/skills/official/official-harness-engineering.md +0 -108
- package/dist/skills/official/official-performance-optimization.md +0 -30
- package/dist/skills/official/official-pr-review.md +0 -35
- package/dist/skills/official/official-release-checklist.md +0 -30
- package/dist/skills/official/official-security-hardening.md +0 -32
- package/dist/skills/official/official-spec-driven-design.md +0 -31
- package/dist/skills/official/planning-with-files.md +0 -241
- package/dist/skills/official/ui-ux-pro-max.md +0 -105
- package/dist/skills/official/webapp-testing.md +0 -96
- package/dist/skills/official-skills.d.ts +0 -26
- package/dist/skills/official-skills.d.ts.map +0 -1
- package/dist/skills/official-skills.js +0 -73
- package/dist/skills/official-skills.js.map +0 -1
- package/dist/skills/semantic-matcher.d.ts +0 -60
- package/dist/skills/semantic-matcher.d.ts.map +0 -1
- package/dist/skills/semantic-matcher.js +0 -192
- package/dist/skills/semantic-matcher.js.map +0 -1
- package/dist/skills/upgrade-engine.d.ts +0 -93
- package/dist/skills/upgrade-engine.d.ts.map +0 -1
- package/dist/skills/upgrade-engine.js +0 -447
- package/dist/skills/upgrade-engine.js.map +0 -1
- package/dist/skills/upgrade-prompt.d.ts +0 -20
- package/dist/skills/upgrade-prompt.d.ts.map +0 -1
- package/dist/skills/upgrade-prompt.js +0 -75
- package/dist/skills/upgrade-prompt.js.map +0 -1
- package/dist/web/routes/ai.d.ts +0 -10
- package/dist/web/routes/ai.d.ts.map +0 -1
- package/dist/web/routes/ai.js +0 -186
- package/dist/web/routes/ai.js.map +0 -1
- package/dist/web/routes/token-usage.d.ts +0 -7
- package/dist/web/routes/token-usage.d.ts.map +0 -1
- package/dist/web/routes/token-usage.js +0 -18
- package/dist/web/routes/token-usage.js.map +0 -1
- package/dist/web/ssrf-guard.d.ts +0 -35
- package/dist/web/ssrf-guard.d.ts.map +0 -1
- package/dist/web/ssrf-guard.js +0 -93
- package/dist/web/ssrf-guard.js.map +0 -1
- package/dist/web/static/assets/AIConfig-CdDWzJyO.js +0 -2
- package/dist/web/static/assets/AIConfig-CdDWzJyO.js.map +0 -1
- package/dist/web/static/assets/Dashboard-CoEmmIDt.js +0 -2
- package/dist/web/static/assets/Dashboard-CoEmmIDt.js.map +0 -1
- package/dist/web/static/assets/Drawer-DdRTzlLB.js +0 -2
- package/dist/web/static/assets/Drawer-DdRTzlLB.js.map +0 -1
- package/dist/web/static/assets/Events-DrIq1SUS.js +0 -2
- package/dist/web/static/assets/Events-DrIq1SUS.js.map +0 -1
- package/dist/web/static/assets/Reports-DFBM3MDK.js +0 -2
- package/dist/web/static/assets/Reports-DFBM3MDK.js.map +0 -1
- package/dist/web/static/assets/SearchInput-qCj_jAcf.js +0 -2
- package/dist/web/static/assets/SearchInput-qCj_jAcf.js.map +0 -1
- package/dist/web/static/assets/SessionDetail-CCzwdoT7.js +0 -2
- package/dist/web/static/assets/SessionDetail-CCzwdoT7.js.map +0 -1
- package/dist/web/static/assets/Sessions-FfLYkAw9.js +0 -2
- package/dist/web/static/assets/Sessions-FfLYkAw9.js.map +0 -1
- package/dist/web/static/assets/Skills-C8Gvs3Qa.js +0 -2
- package/dist/web/static/assets/Skills-C8Gvs3Qa.js.map +0 -1
- package/dist/web/static/assets/TaskDetail-BS8pYhaR.js +0 -2
- package/dist/web/static/assets/TaskDetail-BS8pYhaR.js.map +0 -1
- package/dist/web/static/assets/Tasks-CyuhizG8.js +0 -2
- package/dist/web/static/assets/Tasks-CyuhizG8.js.map +0 -1
- package/dist/web/static/assets/charts-CLrM0_uM.js +0 -37
- package/dist/web/static/assets/charts-CLrM0_uM.js.map +0 -1
- package/dist/web/static/assets/date-fns-CZ_bHujz.js +0 -2
- package/dist/web/static/assets/date-fns-CZ_bHujz.js.map +0 -1
- package/dist/web/static/assets/export-L_VBD2p1.js +0 -4
- package/dist/web/static/assets/export-L_VBD2p1.js.map +0 -1
- package/dist/web/static/assets/index-CBX47X8l.js +0 -3
- package/dist/web/static/assets/index-CBX47X8l.js.map +0 -1
- package/dist/web/static/assets/index-DjIoMdoR.css +0 -1
- package/dist/web/static/assets/lucide-Bs_edTLa.js +0 -232
- package/dist/web/static/assets/lucide-Bs_edTLa.js.map +0 -1
- package/dist/web/static/assets/query-C99w429o.js +0 -2
- package/dist/web/static/assets/react-vendor-CSp-GLFF.js +0 -49
- package/dist/web/static/assets/react-vendor-CSp-GLFF.js.map +0 -1
- package/dist/web/static/assets/syntax-highlighter-44FakypI.js +0 -9
- package/dist/web/static/assets/syntax-highlighter-44FakypI.js.map +0 -1
- package/dist/web/static/assets/task-title-BhOcemuR.js +0 -2
- package/dist/web/static/assets/task-title-BhOcemuR.js.map +0 -1
- package/dist/web/static/assets/time-Bxuk0M-C.js +0 -2
- package/dist/web/static/assets/time-Bxuk0M-C.js.map +0 -1
- package/dist/web/static/assets/vendor-CMMjVdZs.js +0 -64
- package/dist/web/static/assets/vendor-CMMjVdZs.js.map +0 -1
|
@@ -0,0 +1,937 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file builder.ts
|
|
3
|
+
* KB Phase 2 — AI compilation layer orchestrator.
|
|
4
|
+
*
|
|
5
|
+
* Main entry point: `buildKnowledge(options?)`.
|
|
6
|
+
*
|
|
7
|
+
* Pipeline:
|
|
8
|
+
* 1. Static layer → buildRepoMap (TypeScript Compiler API)
|
|
9
|
+
* 2. Discover → src/ first-level subdirectories
|
|
10
|
+
* 3. AI compile → buildModulePage per module (concurrency-limited)
|
|
11
|
+
* 4. Validate → validatePage on each compiled page
|
|
12
|
+
* 5. Report → generateBuildReport → ~/.claude-forge/knowledge-build-report.md
|
|
13
|
+
* 6. Apply (opt) → applyPages → .forge-knowledge/modules/*.md + .meta.json + repo-map.json
|
|
14
|
+
*
|
|
15
|
+
* ── v9.1.2: module-hash cache ──────────────────────────────────────────────
|
|
16
|
+
* Per-module SHA-256 fingerprints (see module-hash.ts) are stored in
|
|
17
|
+
* `KBMeta.pages[*].source_hash`. When a hash matches the previous build, the
|
|
18
|
+
* AI call is skipped and the existing `.md` is left in place.
|
|
19
|
+
*
|
|
20
|
+
* Bypass mechanism: `BuildOptions.force = true` (CLI: `--force`).
|
|
21
|
+
*
|
|
22
|
+
* Known cache-aware-of-nothing edge: changes to `prompt.ts` do NOT invalidate
|
|
23
|
+
* cached pages. Run `--force` after prompt edits.
|
|
24
|
+
*
|
|
25
|
+
* Cross-module overview / architecture pages are reserved for Phase 3.
|
|
26
|
+
*/
|
|
27
|
+
import { promises as fsAsync, mkdirSync, writeFileSync, readFileSync, existsSync, readdirSync, copyFileSync } from 'node:fs';
|
|
28
|
+
import path from 'node:path';
|
|
29
|
+
import { filterByModule, writeRepoMap } from './repo-map.js';
|
|
30
|
+
import { validatePage, renderRef } from './validator.js';
|
|
31
|
+
import { deriveAuditStatus } from './audit-applier.js';
|
|
32
|
+
import { buildModulePrompt, parseAIResponse, stripMarkdownFence } from './prompt.js';
|
|
33
|
+
import * as K from './constants.js';
|
|
34
|
+
// D R-D (2026-05-29, spec 0902): `ConfigManager` import + `config()` helper
|
|
35
|
+
// were removed — the only consumer was `config().ai.model`, replaced by a
|
|
36
|
+
// 'claude-cli' sentinel since the AI provider lives in a subprocess.
|
|
37
|
+
import { logger } from '../core/utils/logger.js';
|
|
38
|
+
import { createTimestampedBackupSync } from '../core/utils/backup.js';
|
|
39
|
+
import { loadKBMetaSafe } from './module-hash.js';
|
|
40
|
+
import { compileCrossModulePages } from './cross-module.js';
|
|
41
|
+
import { getAdapter, MonorepoAdapter } from './adapters/index.js';
|
|
42
|
+
import { detectMonorepo } from './project-detector.js';
|
|
43
|
+
import { AGENTS_EXPERIENCE_DIR } from '../daemon/services/experience-extractor.js';
|
|
44
|
+
import { createDefaultKnowledgeProvider, withKnowledgeRoutingHints, } from './cli-provider.js';
|
|
45
|
+
/**
|
|
46
|
+
* Directories under `.forge-knowledge/` that the builder MUST leave untouched
|
|
47
|
+
* on every rebuild (no backup, no delete, no overwrite). These hold
|
|
48
|
+
* runtime-accumulated content (e.g. Phase 6 agent-experience writeback) that
|
|
49
|
+
* would be wiped if folded into the snapshot rebuild path.
|
|
50
|
+
*
|
|
51
|
+
* Keep this list in lock-step with whoever owns the directory — adding a new
|
|
52
|
+
* runtime-accumulated subdir requires a single-line addition here.
|
|
53
|
+
*/
|
|
54
|
+
const BUILDER_PRESERVED_DIRS = new Set([
|
|
55
|
+
AGENTS_EXPERIENCE_DIR,
|
|
56
|
+
]);
|
|
57
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
58
|
+
// Main entry point
|
|
59
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
60
|
+
/**
|
|
61
|
+
* Main entry: scan source roots → buildRepoMap → AI-compile each module →
|
|
62
|
+
* validate refs → write dry-run report. When `options.apply` is `true`,
|
|
63
|
+
* pages are also persisted to `.forge-knowledge/`.
|
|
64
|
+
*
|
|
65
|
+
* v10.1: Uses LanguageAdapter to support multi-language projects (TypeScript + Java).
|
|
66
|
+
*/
|
|
67
|
+
export async function buildKnowledge(options = {}) {
|
|
68
|
+
const projectRoot = options.projectRoot ?? process.cwd();
|
|
69
|
+
// v9.4: optional event sink (web SSE). emit() is failure-isolated so listener
|
|
70
|
+
// errors NEVER propagate to the caller (CLI/test paths unaffected). Hoisted
|
|
71
|
+
// above adapter resolution so the band-aid path can emit an 'error' event.
|
|
72
|
+
const emit = (ev) => {
|
|
73
|
+
const cb = options.onEvent;
|
|
74
|
+
if (!cb)
|
|
75
|
+
return;
|
|
76
|
+
try {
|
|
77
|
+
cb(ev);
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
logger.warn(`[KB] onEvent listener error: ${err instanceof Error ? err.message : String(err)}`);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
// v10.1: Get language adapter for the root.
|
|
84
|
+
//
|
|
85
|
+
// Monorepo / band-aid resolution (spec 2026-06-04/1200, decision e0eb1695):
|
|
86
|
+
// - root has a single-language adapter → use it (unchanged single-project path)
|
|
87
|
+
// - root has none, but ≥2 sub-projects each have one → MonorepoAdapter
|
|
88
|
+
// - root has none and no sub-projects (true-generic) → emit warning + return
|
|
89
|
+
// an empty BuildResult (NO throw). `cf project init` then marks the
|
|
90
|
+
// knowledge step `skipped` rather than `failed`.
|
|
91
|
+
let adapter = getAdapter(projectRoot);
|
|
92
|
+
if (!adapter) {
|
|
93
|
+
const monorepoInfo = detectMonorepo(projectRoot);
|
|
94
|
+
if (monorepoInfo) {
|
|
95
|
+
logger.info(`[KB] Monorepo detected: ${monorepoInfo.subprojects.length} sub-projects ` +
|
|
96
|
+
`(${monorepoInfo.subprojects.map((s) => s.name).join(', ')})`);
|
|
97
|
+
adapter = new MonorepoAdapter(monorepoInfo.subprojects);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
// True-generic: degrade gracefully (band-aid, Option A superset).
|
|
101
|
+
logger.warn('[KB] No supported project type detected (no single-language manifest, ' +
|
|
102
|
+
'no recognised sub-projects). Returning empty build result.');
|
|
103
|
+
emit({ type: 'error', message: 'No supported project type detected', step: 'adapter' });
|
|
104
|
+
const reportPath = options.reportPath ?? K.KB_BUILD_REPORT_PATH;
|
|
105
|
+
const emptyResult = {
|
|
106
|
+
mode: options.apply ? 'apply' : 'dry-run',
|
|
107
|
+
pages: [],
|
|
108
|
+
stats: { built: 0, cached: 0, total: 0, crossModuleBuilt: 0, crossModuleCached: 0 },
|
|
109
|
+
reportPath,
|
|
110
|
+
};
|
|
111
|
+
generateBuildReport(emptyResult, { reportPath });
|
|
112
|
+
emit({ type: 'done', stats: emptyResult.stats, reportPath });
|
|
113
|
+
return emptyResult;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
try {
|
|
117
|
+
// ── Step 0: Self-heal legacy fenced files ─────────────────────────────────
|
|
118
|
+
// Older builds (pre-`stripMarkdownFence`) sometimes wrote AI output verbatim,
|
|
119
|
+
// leaving an outer ```markdown ... ``` wrapper inside .forge-knowledge/*.md.
|
|
120
|
+
// Detect and rewrite those in-place so cached pages aren't perpetually dirty.
|
|
121
|
+
repairLegacyFencedFiles(path.join(projectRoot, K.KB_DIRNAME));
|
|
122
|
+
// ── Step 1: Static layer (repo-map) ────────────────────────────────────────
|
|
123
|
+
logger.info('[KB] Building repo-map...');
|
|
124
|
+
const repoMap = await buildRepoMapWithAdapter(projectRoot, adapter);
|
|
125
|
+
logger.info(`[KB] repo-map: ${repoMap.symbol_count} symbols / ${repoMap.file_count} files`);
|
|
126
|
+
// ── Step 2: Discover modules ───────────────────────────────────────────────
|
|
127
|
+
const allModules = adapter.discoverModules(projectRoot);
|
|
128
|
+
const modules = options.modules
|
|
129
|
+
? allModules.filter((m) => options.modules.includes(m.name))
|
|
130
|
+
: allModules;
|
|
131
|
+
const moduleNames = modules.map((m) => m.name);
|
|
132
|
+
logger.info(`[KB] Modules to compile: ${moduleNames.join(', ')}`);
|
|
133
|
+
// v9.4: emit start event after modules resolved
|
|
134
|
+
emit({
|
|
135
|
+
type: 'start',
|
|
136
|
+
modules: moduleNames,
|
|
137
|
+
force: !!options.force,
|
|
138
|
+
apply: !!options.apply,
|
|
139
|
+
skipCrossModule: !!options.skipCrossModule,
|
|
140
|
+
});
|
|
141
|
+
emit({
|
|
142
|
+
type: 'repo-map',
|
|
143
|
+
symbolCount: repoMap.symbol_count,
|
|
144
|
+
fileCount: repoMap.file_count,
|
|
145
|
+
sourceHash: repoMap.source_hash,
|
|
146
|
+
});
|
|
147
|
+
// ── Step 3: Initialise AI provider ─────────────────────────────────────────
|
|
148
|
+
// Production callers run through `CliKnowledgeProvider` which spawns
|
|
149
|
+
// `claude --agent knowledge-builder --bare ...` per page (see
|
|
150
|
+
// src/knowledge/cli-provider.ts). Tests inject a mock via
|
|
151
|
+
// `options.aiProvider` and bypass the shell-out path entirely.
|
|
152
|
+
const ai = options.aiProvider ?? createDefaultKnowledgeProvider();
|
|
153
|
+
// ── Step 3.5: Load previous build metadata for cache lookup ────────────────
|
|
154
|
+
const kbDir = path.join(projectRoot, K.KB_DIRNAME);
|
|
155
|
+
const oldMeta = loadKBMetaSafe(projectRoot);
|
|
156
|
+
if (oldMeta) {
|
|
157
|
+
logger.info('[KB] Found prior .meta.json — checking module hashes for cache hits');
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
logger.info('[KB] No prior .meta.json — full build');
|
|
161
|
+
}
|
|
162
|
+
// ── Step 4: Concurrency-limited module compilation (with hash cache) ───────
|
|
163
|
+
const concurrency = options.maxConcurrency ?? K.KB_MAX_CONCURRENCY;
|
|
164
|
+
logger.info(`[KB] Compiling ${modules.length} module(s) with concurrency=${concurrency}`);
|
|
165
|
+
const compilationResults = await runWithConcurrency(modules, concurrency, async (mod) => {
|
|
166
|
+
const pageName = `modules/${mod.name}.md`;
|
|
167
|
+
// v10.x polyglot fix (decision 638c62bf): hash via the module's own
|
|
168
|
+
// adapter so non-TypeScript sub-projects (Java/Go/Python/Rust, and each
|
|
169
|
+
// monorepo sub-project) fingerprint their real source files instead of
|
|
170
|
+
// hashing an empty `.ts` set (which collapsed to the empty-SHA
|
|
171
|
+
// `e3b0c44…` and made the cache permanently miss). For single-project TS
|
|
172
|
+
// the adapter walks the same `.ts` file set, so the hash is unchanged.
|
|
173
|
+
const currentHash = await computeModuleHashForAdapter(mod, adapter);
|
|
174
|
+
const cachedHash = oldMeta?.pages[pageName]?.source_hash;
|
|
175
|
+
const pageOnDisk = path.join(kbDir, pageName);
|
|
176
|
+
const canUseCache = !options.force &&
|
|
177
|
+
cachedHash !== undefined &&
|
|
178
|
+
cachedHash === currentHash &&
|
|
179
|
+
existsSync(pageOnDisk);
|
|
180
|
+
const startedAt = performance.now();
|
|
181
|
+
emit({ type: 'module', name: mod.name, status: 'compiling' });
|
|
182
|
+
if (canUseCache) {
|
|
183
|
+
logger.info(`[KB] Cached: ${pageName} (hash ${currentHash})`);
|
|
184
|
+
const page = makeCachedPagePlaceholder(pageName, mod.name, currentHash, oldMeta, pageOnDisk);
|
|
185
|
+
// Cache hit still re-validates refs — cheap and catches drift caused
|
|
186
|
+
// by changes in *other* modules that this page references.
|
|
187
|
+
const validation = validatePage(page, { repoMap: repoMap.symbols });
|
|
188
|
+
// Preserve the previously-recorded source_files when present so a
|
|
189
|
+
// pure cache-hit build doesn't drop tracking metadata. Fall back to
|
|
190
|
+
// re-walking the module's files for legacy `.meta.json` written by
|
|
191
|
+
// versions that hardcoded `source_files: []`.
|
|
192
|
+
let sourceFiles = oldMeta?.pages[pageName]?.source_files ?? [];
|
|
193
|
+
if (!Array.isArray(sourceFiles) || sourceFiles.length === 0) {
|
|
194
|
+
try {
|
|
195
|
+
const files = await adapter.walkModuleFiles(mod);
|
|
196
|
+
sourceFiles = files.map((f) => f.projectRelPath);
|
|
197
|
+
}
|
|
198
|
+
catch (err) {
|
|
199
|
+
logger.warn(`[KB] Failed to backfill source_files for cached ${pageName}: ${err instanceof Error ? err.message : String(err)}`);
|
|
200
|
+
sourceFiles = [];
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
emit({
|
|
204
|
+
type: 'module',
|
|
205
|
+
name: mod.name,
|
|
206
|
+
status: validation.valid ? 'ok' : 'issues',
|
|
207
|
+
refsValid: validation.refsValid,
|
|
208
|
+
refsTotal: validation.refsTotal,
|
|
209
|
+
durationMs: Math.round(performance.now() - startedAt),
|
|
210
|
+
cached: true,
|
|
211
|
+
});
|
|
212
|
+
return { page, validation, cached: true, sourceFiles };
|
|
213
|
+
}
|
|
214
|
+
logger.info(`[KB] Compiling module: ${mod.name}`);
|
|
215
|
+
const files = await adapter.walkModuleFiles(mod);
|
|
216
|
+
const sourceFiles = files.map((f) => f.projectRelPath);
|
|
217
|
+
const built = await buildModulePage(mod.name, files, repoMap, ai, path.basename(projectRoot));
|
|
218
|
+
// Overwrite the source_hash with the module content hash so future builds
|
|
219
|
+
// can short-circuit on this entry. Only do this if the AI call succeeded
|
|
220
|
+
// (i.e., not an error placeholder from makeEmptyPage).
|
|
221
|
+
const isErrorPlaceholder = built.page.content.startsWith('<!-- Build failed:');
|
|
222
|
+
if (!isErrorPlaceholder) {
|
|
223
|
+
built.page.source_hash = currentHash;
|
|
224
|
+
}
|
|
225
|
+
logger.info(`[KB] Module ${mod.name}: ${built.validation.valid ? 'ok' : 'issues'} ` +
|
|
226
|
+
`(refs ${built.validation.refsValid}/${built.validation.refsTotal})`);
|
|
227
|
+
const failedBuild = built.page.source_hash === 'unknown';
|
|
228
|
+
emit({
|
|
229
|
+
type: 'module',
|
|
230
|
+
name: mod.name,
|
|
231
|
+
status: failedBuild ? 'failed' : built.validation.valid ? 'ok' : 'issues',
|
|
232
|
+
refsValid: built.validation.refsValid,
|
|
233
|
+
refsTotal: built.validation.refsTotal,
|
|
234
|
+
durationMs: Math.round(performance.now() - startedAt),
|
|
235
|
+
cached: false,
|
|
236
|
+
});
|
|
237
|
+
return { ...built, cached: false, sourceFiles };
|
|
238
|
+
});
|
|
239
|
+
// ── Step 5: Cross-module pages (overview / architecture / decisions / glossary / tech-stack) ──
|
|
240
|
+
// v9.2: 5 project-level pages compiled from module summaries + config files,
|
|
241
|
+
// sharing a single crossHash cache (see cross-module.ts).
|
|
242
|
+
const pages = compilationResults.map((r, i) => ({
|
|
243
|
+
name: `modules/${modules[i].name}.md`,
|
|
244
|
+
page: r.page,
|
|
245
|
+
validation: r.validation,
|
|
246
|
+
ready: r.validation.valid,
|
|
247
|
+
cached: r.cached,
|
|
248
|
+
kind: 'module',
|
|
249
|
+
sourceFiles: r.sourceFiles,
|
|
250
|
+
}));
|
|
251
|
+
if (!options.skipCrossModule) {
|
|
252
|
+
const moduleHashes = new Map(compilationResults.map((r, i) => [`modules/${modules[i].name}.md`, r.page.source_hash]));
|
|
253
|
+
const moduleResults = compilationResults.map((r, i) => ({
|
|
254
|
+
name: `modules/${modules[i].name}.md`,
|
|
255
|
+
page: r.page,
|
|
256
|
+
}));
|
|
257
|
+
const crossEntries = await compileCrossModulePages({
|
|
258
|
+
moduleHashes,
|
|
259
|
+
moduleResults,
|
|
260
|
+
repoMap,
|
|
261
|
+
projectRoot,
|
|
262
|
+
ai,
|
|
263
|
+
oldMeta,
|
|
264
|
+
kbDir,
|
|
265
|
+
force: !!options.force,
|
|
266
|
+
concurrency,
|
|
267
|
+
onEvent: emit,
|
|
268
|
+
});
|
|
269
|
+
for (const e of crossEntries) {
|
|
270
|
+
pages.push({
|
|
271
|
+
name: e.name,
|
|
272
|
+
page: e.page,
|
|
273
|
+
validation: e.validation,
|
|
274
|
+
ready: e.validation.valid,
|
|
275
|
+
cached: e.cached,
|
|
276
|
+
kind: 'cross',
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
const stats = {
|
|
281
|
+
built: pages.filter((p) => !p.cached).length,
|
|
282
|
+
cached: pages.filter((p) => p.cached).length,
|
|
283
|
+
total: pages.length,
|
|
284
|
+
crossModuleBuilt: pages.filter((p) => p.kind === 'cross' && !p.cached).length,
|
|
285
|
+
crossModuleCached: pages.filter((p) => p.kind === 'cross' && p.cached).length,
|
|
286
|
+
};
|
|
287
|
+
logger.info(`[KB] Summary: ${stats.built} built / ${stats.cached} cached / ${stats.total} total` +
|
|
288
|
+
(options.skipCrossModule
|
|
289
|
+
? ' (cross-module skipped)'
|
|
290
|
+
: ` (cross: ${stats.crossModuleBuilt} built / ${stats.crossModuleCached} cached)`));
|
|
291
|
+
const buildResult = {
|
|
292
|
+
mode: options.apply ? 'apply' : 'dry-run',
|
|
293
|
+
pages,
|
|
294
|
+
stats,
|
|
295
|
+
reportPath: options.reportPath ?? K.KB_BUILD_REPORT_PATH,
|
|
296
|
+
};
|
|
297
|
+
// ── Step 6: Write dry-run report ───────────────────────────────────────────
|
|
298
|
+
generateBuildReport(buildResult, { reportPath: buildResult.reportPath });
|
|
299
|
+
logger.info(`[KB] Report written to ${buildResult.reportPath}`);
|
|
300
|
+
// ── Step 7: Apply (optional) ───────────────────────────────────────────────
|
|
301
|
+
if (options.apply) {
|
|
302
|
+
const { appliedPath, backupPath } = applyPages(pages, projectRoot);
|
|
303
|
+
buildResult.appliedTo = appliedPath;
|
|
304
|
+
logger.info(`[KB] Applied to ${appliedPath} (backup: ${backupPath})`);
|
|
305
|
+
writeMetadata(appliedPath, repoMap, pages, oldMeta);
|
|
306
|
+
writeRepoMap(appliedPath, repoMap);
|
|
307
|
+
}
|
|
308
|
+
emit({
|
|
309
|
+
type: 'done',
|
|
310
|
+
stats: buildResult.stats,
|
|
311
|
+
reportPath: buildResult.reportPath,
|
|
312
|
+
appliedTo: buildResult.appliedTo,
|
|
313
|
+
});
|
|
314
|
+
return buildResult;
|
|
315
|
+
}
|
|
316
|
+
catch (err) {
|
|
317
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
318
|
+
emit({ type: 'error', message });
|
|
319
|
+
throw err;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
323
|
+
// Single-module compilation
|
|
324
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
325
|
+
/**
|
|
326
|
+
* Compile a single module knowledge page.
|
|
327
|
+
*
|
|
328
|
+
* Called by `buildKnowledge` internally and exported for use by
|
|
329
|
+
* `cf knowledge build --module <name>` (Phase 3 CLI).
|
|
330
|
+
*
|
|
331
|
+
* On AI failure (malformed response / API error) the function returns an
|
|
332
|
+
* invalid page rather than throwing, so the overall build continues.
|
|
333
|
+
*
|
|
334
|
+
* v10.1: Accepts SourceFile[] from adapter instead of legacy { path, content }.
|
|
335
|
+
*/
|
|
336
|
+
export async function buildModulePage(moduleName, files, repoMap, ai, projectName = 'project') {
|
|
337
|
+
const repoMapSubset = filterByModule(repoMap, moduleName);
|
|
338
|
+
// Normalize files to legacy format for prompt builder (v10.1 keeps prompt unchanged)
|
|
339
|
+
const fileContents = files.map((f) => ({
|
|
340
|
+
path: 'projectRelPath' in f ? f.projectRelPath : f.path,
|
|
341
|
+
content: f.content,
|
|
342
|
+
}));
|
|
343
|
+
const { system, user } = buildModulePrompt({
|
|
344
|
+
moduleName,
|
|
345
|
+
projectName,
|
|
346
|
+
repoMapSubset,
|
|
347
|
+
fileContents,
|
|
348
|
+
});
|
|
349
|
+
// R-B (sub-spec B): routing hints get the prompt to the right place when
|
|
350
|
+
// `ai` is the CliKnowledgeProvider. When `ai` is a test mock the hints are
|
|
351
|
+
// ignored — extractRoutingHints just sees extra tags it doesn't read.
|
|
352
|
+
const systemWithHints = withKnowledgeRoutingHints(system, {
|
|
353
|
+
pageKind: 'module',
|
|
354
|
+
pageName: `modules/${moduleName}.md`,
|
|
355
|
+
});
|
|
356
|
+
let aiText;
|
|
357
|
+
let aiModel;
|
|
358
|
+
try {
|
|
359
|
+
const response = await ai.completeWithUsage(user, {
|
|
360
|
+
system: systemWithHints,
|
|
361
|
+
maxTokens: K.KB_AI_MAX_TOKENS,
|
|
362
|
+
timeoutMs: K.KB_AI_TIMEOUT_MS,
|
|
363
|
+
});
|
|
364
|
+
aiText = response.text;
|
|
365
|
+
aiModel = response.model;
|
|
366
|
+
}
|
|
367
|
+
catch (err) {
|
|
368
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
369
|
+
logger.error(`[KB] AI error for module "${moduleName}": ${msg}`);
|
|
370
|
+
return {
|
|
371
|
+
page: makeEmptyPage(moduleName, `[KB] AI call failed: ${msg}`),
|
|
372
|
+
validation: {
|
|
373
|
+
valid: false,
|
|
374
|
+
issues: [{ severity: 'error', msg: `AI call failed: ${msg}` }],
|
|
375
|
+
refsTotal: 0,
|
|
376
|
+
refsValid: 0,
|
|
377
|
+
},
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
const parsed = parseAIResponse(aiText);
|
|
381
|
+
if (!parsed) {
|
|
382
|
+
logger.warn(`[KB] AI response for module "${moduleName}" could not be parsed as JSON.`);
|
|
383
|
+
// Parse 失败时 dump AI 原始返回到 ~/.claude-forge/knowledge-debug/,
|
|
384
|
+
// 用于排查(AI 截断 / 非法 JSON / network 问题)
|
|
385
|
+
try {
|
|
386
|
+
const { FORGE_HOME } = await import('../core/constants.js');
|
|
387
|
+
const debugDir = path.join(FORGE_HOME, 'knowledge-debug');
|
|
388
|
+
mkdirSync(debugDir, { recursive: true });
|
|
389
|
+
const debugPath = path.join(debugDir, `${moduleName}.txt`);
|
|
390
|
+
writeFileSync(debugPath, aiText);
|
|
391
|
+
logger.warn(`[KB] AI raw text dumped to ${debugPath} (${aiText.length} chars)`);
|
|
392
|
+
}
|
|
393
|
+
catch { /* ignore */ }
|
|
394
|
+
return {
|
|
395
|
+
page: makeEmptyPage(moduleName, '[KB] AI response not parseable'),
|
|
396
|
+
validation: {
|
|
397
|
+
valid: false,
|
|
398
|
+
issues: [{ severity: 'error', msg: 'AI response not parseable as module-page schema' }],
|
|
399
|
+
refsTotal: 0,
|
|
400
|
+
refsValid: 0,
|
|
401
|
+
},
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
const page = {
|
|
405
|
+
name: `modules/${moduleName}.md`,
|
|
406
|
+
title: moduleName,
|
|
407
|
+
content: parsed.content,
|
|
408
|
+
refs: parsed.refs,
|
|
409
|
+
generated_at: new Date().toISOString(),
|
|
410
|
+
source_hash: repoMap.source_hash,
|
|
411
|
+
// D R-D (2026-05-29, spec 0902): `config().ai.model` schema is gone.
|
|
412
|
+
// Fallback to the model name returned by the CLI subprocess (or 'claude-cli'
|
|
413
|
+
// sentinel when the provider doesn't echo a model — older `claude` builds).
|
|
414
|
+
ai_model: aiModel ?? 'claude-cli',
|
|
415
|
+
};
|
|
416
|
+
const validation = validatePage(page, { repoMap: repoMap.symbols });
|
|
417
|
+
return { page, validation };
|
|
418
|
+
}
|
|
419
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
420
|
+
// Report generation
|
|
421
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
422
|
+
/**
|
|
423
|
+
* Write a markdown dry-run report to `reportPath`.
|
|
424
|
+
*
|
|
425
|
+
* Uses synchronous fs calls so this function can remain non-async and
|
|
426
|
+
* be called easily from both CLI and test contexts.
|
|
427
|
+
*/
|
|
428
|
+
export function generateBuildReport(result, options) {
|
|
429
|
+
const totalRefs = result.pages.reduce((s, p) => s + p.page.refs.length, 0);
|
|
430
|
+
const errorCount = result.pages.reduce((s, p) => s + p.validation.issues.filter((i) => i.severity === 'error').length, 0);
|
|
431
|
+
const { built, cached, total } = result.stats;
|
|
432
|
+
const lines = [
|
|
433
|
+
`# 知识库构建报告`,
|
|
434
|
+
``,
|
|
435
|
+
`生成时间:${new Date().toISOString()} | 模式:**${result.mode}**`,
|
|
436
|
+
``,
|
|
437
|
+
`**概要:新建 ${built} / 缓存 ${cached} / 共 ${total} 个页面**`,
|
|
438
|
+
``,
|
|
439
|
+
`| 指标 | 值 |`,
|
|
440
|
+
`|------|-----|`,
|
|
441
|
+
`| 页面总数 | ${result.pages.length} |`,
|
|
442
|
+
`| AI 编译 | ${built} |`,
|
|
443
|
+
`| 缓存命中 | ${cached} |`,
|
|
444
|
+
`| 引用总数 | ${totalRefs} |`,
|
|
445
|
+
`| 校验异常 | ${errorCount} |`,
|
|
446
|
+
`| 可应用 | ${result.pages.filter((p) => p.ready).length} / ${result.pages.length} |`,
|
|
447
|
+
``,
|
|
448
|
+
`## 各页面详情`,
|
|
449
|
+
``,
|
|
450
|
+
];
|
|
451
|
+
for (const { name, page, validation, ready, cached: isCached } of result.pages) {
|
|
452
|
+
const lineCount = page.content.split('\n').length;
|
|
453
|
+
const status = ready ? '`就绪`' : '`有问题`';
|
|
454
|
+
const cacheLine = isCached
|
|
455
|
+
? `- 缓存:\`命中\`(hash: ${page.source_hash})`
|
|
456
|
+
: `- 缓存:\`未命中\``;
|
|
457
|
+
lines.push(`### ${name}`);
|
|
458
|
+
lines.push(`- 状态:${status}`);
|
|
459
|
+
lines.push(cacheLine);
|
|
460
|
+
lines.push(`- 内容:${lineCount} 行`);
|
|
461
|
+
lines.push(`- 引用:${validation.refsTotal} 个(${validation.refsValid} 个有效)`);
|
|
462
|
+
if (validation.issues.length > 0) {
|
|
463
|
+
for (const issue of validation.issues) {
|
|
464
|
+
const icon = issue.severity === 'error' ? '⚠️' : 'ℹ️';
|
|
465
|
+
lines.push(`- ${icon} **${issue.severity}**: ${issue.msg}`);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
lines.push(``);
|
|
469
|
+
}
|
|
470
|
+
lines.push(`## Apply`);
|
|
471
|
+
lines.push(``);
|
|
472
|
+
if (result.mode === 'dry-run') {
|
|
473
|
+
lines.push(`This was a dry-run. To apply, run:`);
|
|
474
|
+
lines.push('```bash');
|
|
475
|
+
lines.push('cf knowledge build --apply');
|
|
476
|
+
lines.push('```');
|
|
477
|
+
}
|
|
478
|
+
else {
|
|
479
|
+
lines.push(`Applied to \`${result.appliedTo ?? '.forge-knowledge/'}\``);
|
|
480
|
+
}
|
|
481
|
+
mkdirSync(path.dirname(options.reportPath), { recursive: true });
|
|
482
|
+
writeFileSync(options.reportPath, lines.join('\n'));
|
|
483
|
+
}
|
|
484
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
485
|
+
// Apply (write pages to .forge-knowledge/)
|
|
486
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
487
|
+
/**
|
|
488
|
+
* Write compiled pages to `.forge-knowledge/`, backing up any
|
|
489
|
+
* previous content into `.forge-knowledge/backups/<timestamp>/`.
|
|
490
|
+
*
|
|
491
|
+
* Backs up both `modules/<name>.md` and the 5 root-level cross-module pages
|
|
492
|
+
* (`overview.md` / `architecture.md` / `decisions.md` / `glossary.md` /
|
|
493
|
+
* `tech-stack.md`) so `cf knowledge rollback` can restore the full set.
|
|
494
|
+
*/
|
|
495
|
+
export function applyPages(pages, projectRoot) {
|
|
496
|
+
const kbDir = path.join(projectRoot, K.KB_DIRNAME);
|
|
497
|
+
const modulesDir = path.join(kbDir, K.KB_MODULES_DIR);
|
|
498
|
+
// Historical timestamp format for KB backups: ISO with `:` / `.` replaced
|
|
499
|
+
// by `-` and sliced to minute precision (e.g. `2026-05-26T07-15`). Kept
|
|
500
|
+
// verbatim to preserve byte-identical on-disk directory names. No
|
|
501
|
+
// collision suffix — two builds in the same minute merge into one dir
|
|
502
|
+
// (mkdir -p idempotent), matching pre-refactor behavior. `mkdir: false`
|
|
503
|
+
// because applyPages historically only created the backup dir inside the
|
|
504
|
+
// conditional branches below (lazy — no empty backups when modules/ is
|
|
505
|
+
// missing AND no cross-module pages exist).
|
|
506
|
+
const tsFormatter = () => new Date().toISOString().replace(/[:.]/g, '-').slice(0, 16);
|
|
507
|
+
const { path: backupDir } = createTimestampedBackupSync({
|
|
508
|
+
baseDir: path.join(kbDir, K.KB_BACKUPS_DIR),
|
|
509
|
+
tsFormatter,
|
|
510
|
+
conflictSuffix: 'never',
|
|
511
|
+
mkdir: false,
|
|
512
|
+
});
|
|
513
|
+
// Backup existing modules/ before overwriting.
|
|
514
|
+
if (existsSync(modulesDir)) {
|
|
515
|
+
const backupModulesDir = path.join(backupDir, K.KB_MODULES_DIR);
|
|
516
|
+
mkdirSync(backupModulesDir, { recursive: true });
|
|
517
|
+
for (const f of readdirSync(modulesDir)) {
|
|
518
|
+
copyFileSync(path.join(modulesDir, f), path.join(backupModulesDir, f));
|
|
519
|
+
}
|
|
520
|
+
logger.info(`[KB] Backed up existing modules to ${backupModulesDir}`);
|
|
521
|
+
}
|
|
522
|
+
// v9.2: Backup existing root-level cross-module pages.
|
|
523
|
+
const crossNames = ['overview.md', 'architecture.md', 'decisions.md', 'glossary.md', 'tech-stack.md'];
|
|
524
|
+
for (const name of crossNames) {
|
|
525
|
+
const src = path.join(kbDir, name);
|
|
526
|
+
if (existsSync(src)) {
|
|
527
|
+
mkdirSync(backupDir, { recursive: true });
|
|
528
|
+
copyFileSync(src, path.join(backupDir, name));
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
mkdirSync(modulesDir, { recursive: true });
|
|
532
|
+
for (const { name, page, cached, kind } of pages) {
|
|
533
|
+
// Cache hit: the existing `.md` is already on disk and was just backed up
|
|
534
|
+
// above. Skip the write so we preserve byte-identical content and avoid
|
|
535
|
+
// changing mtime unnecessarily.
|
|
536
|
+
if (cached)
|
|
537
|
+
continue;
|
|
538
|
+
// Skip placeholder pages whose AI call failed — keep the previous good
|
|
539
|
+
// version on disk (already backed up).
|
|
540
|
+
if (page.source_hash === 'unknown')
|
|
541
|
+
continue;
|
|
542
|
+
const outPath = path.join(kbDir, name);
|
|
543
|
+
mkdirSync(path.dirname(outPath), { recursive: true });
|
|
544
|
+
// Defence-in-depth: strip any ```markdown / ``` fence that slipped through
|
|
545
|
+
// the AI parsing step. New compilations are already cleaned in
|
|
546
|
+
// cross-module.ts / parseAIResponse, but this guards against future
|
|
547
|
+
// regressions and unusual provider responses.
|
|
548
|
+
const cleanedContent = stripMarkdownFence(page.content);
|
|
549
|
+
const sanitizedPage = cleanedContent === page.content ? page : { ...page, content: cleanedContent };
|
|
550
|
+
// v9.2: cross-module pages are written as raw markdown (no References
|
|
551
|
+
// section / no Generated header). Their content is the AI's plain-markdown
|
|
552
|
+
// output, with no refs to render.
|
|
553
|
+
if (kind === 'cross') {
|
|
554
|
+
writeFileSync(outPath, sanitizedPage.content);
|
|
555
|
+
}
|
|
556
|
+
else {
|
|
557
|
+
writeFileSync(outPath, renderPageMarkdown(sanitizedPage));
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
return { appliedPath: kbDir, backupPath: backupDir };
|
|
561
|
+
}
|
|
562
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
563
|
+
// Internal helpers
|
|
564
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
565
|
+
/**
|
|
566
|
+
* Scan an existing `.forge-knowledge/` directory and strip any leftover
|
|
567
|
+
* ```` ```markdown ```` / ```` ``` ```` fences from previously written pages.
|
|
568
|
+
*
|
|
569
|
+
* Background: pre-fix builds occasionally persisted AI output verbatim, leaving
|
|
570
|
+
* the outer markdown fence wrapping the entire page body. Newly compiled pages
|
|
571
|
+
* are already cleaned via `stripMarkdownFence`, but legacy on-disk content
|
|
572
|
+
* keeps re-entering the cache hit path. Running this once at the start of
|
|
573
|
+
* every build self-heals those files in-place.
|
|
574
|
+
*
|
|
575
|
+
* Failure isolation: per-file errors are logged at `warn` level but never
|
|
576
|
+
* propagate — a single unreadable file must not block the build.
|
|
577
|
+
*/
|
|
578
|
+
function repairLegacyFencedFiles(kbDir) {
|
|
579
|
+
if (!existsSync(kbDir))
|
|
580
|
+
return;
|
|
581
|
+
const candidates = [];
|
|
582
|
+
// Top-level cross-module pages: overview / architecture / decisions / glossary / tech-stack.
|
|
583
|
+
// Subdirectories under BUILDER_PRESERVED_DIRS (e.g. agents-experience/) are
|
|
584
|
+
// never entered — those files belong to runtime accumulators, not the build.
|
|
585
|
+
try {
|
|
586
|
+
for (const entry of readdirSync(kbDir, { withFileTypes: true })) {
|
|
587
|
+
if (entry.isFile() && entry.name.endsWith('.md') && !entry.name.startsWith('.')) {
|
|
588
|
+
candidates.push(path.join(kbDir, entry.name));
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
catch (err) {
|
|
593
|
+
logger.warn(`[KB] Could not enumerate ${kbDir} for legacy-fence scan: ${err instanceof Error ? err.message : String(err)}`);
|
|
594
|
+
}
|
|
595
|
+
// Module pages live under modules/.
|
|
596
|
+
const modulesDir = path.join(kbDir, K.KB_MODULES_DIR);
|
|
597
|
+
if (existsSync(modulesDir)) {
|
|
598
|
+
try {
|
|
599
|
+
for (const entry of readdirSync(modulesDir, { withFileTypes: true })) {
|
|
600
|
+
if (entry.isFile() && entry.name.endsWith('.md')) {
|
|
601
|
+
candidates.push(path.join(modulesDir, entry.name));
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
catch (err) {
|
|
606
|
+
logger.warn(`[KB] Could not enumerate ${modulesDir} for legacy-fence scan: ${err instanceof Error ? err.message : String(err)}`);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
let fixed = 0;
|
|
610
|
+
for (const file of candidates) {
|
|
611
|
+
try {
|
|
612
|
+
const original = readFileSync(file, 'utf-8');
|
|
613
|
+
const cleaned = stripMarkdownFence(original);
|
|
614
|
+
if (cleaned !== original) {
|
|
615
|
+
writeFileSync(file, cleaned);
|
|
616
|
+
fixed++;
|
|
617
|
+
logger.info(`[KB] Repaired legacy fence wrapping in ${path.relative(kbDir, file)}`);
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
catch (err) {
|
|
621
|
+
// Per-file failure is non-fatal; carry on so the rest of the build runs.
|
|
622
|
+
logger.warn(`[KB] Failed to repair ${file}: ${err instanceof Error ? err.message : String(err)}`);
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
if (fixed > 0) {
|
|
626
|
+
logger.info(`[KB] Fixed ${fixed} legacy file(s) with markdown fence wrapping`);
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
/**
|
|
630
|
+
* Build repo-map using adapter's parseSymbols method.
|
|
631
|
+
* v10.1: Replaces hard-coded buildRepoMap(srcDir) with adapter-driven approach.
|
|
632
|
+
*/
|
|
633
|
+
async function buildRepoMapWithAdapter(projectRoot, adapter) {
|
|
634
|
+
const symbols = [];
|
|
635
|
+
const modules = adapter.discoverModules(projectRoot);
|
|
636
|
+
let totalFiles = 0;
|
|
637
|
+
// Monorepo: parseSymbols has no module context, so route per-module to the
|
|
638
|
+
// owning sub-project adapter via MonorepoAdapter.parseSymbolsForModule.
|
|
639
|
+
const isMonorepo = adapter instanceof MonorepoAdapter;
|
|
640
|
+
for (const mod of modules) {
|
|
641
|
+
const files = await adapter.walkModuleFiles(mod);
|
|
642
|
+
totalFiles += files.length;
|
|
643
|
+
for (const file of files) {
|
|
644
|
+
if (isMonorepo) {
|
|
645
|
+
try {
|
|
646
|
+
const fileSymbols = await adapter.parseSymbolsForModule(mod.name, file);
|
|
647
|
+
symbols.push(...fileSymbols);
|
|
648
|
+
}
|
|
649
|
+
catch (err) {
|
|
650
|
+
logger.warn(`[KB] Failed to parse symbols from ${file.projectRelPath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
else if (adapter.parseSymbols) {
|
|
654
|
+
try {
|
|
655
|
+
const fileSymbols = await adapter.parseSymbols(file);
|
|
656
|
+
symbols.push(...fileSymbols);
|
|
657
|
+
}
|
|
658
|
+
catch (err) {
|
|
659
|
+
logger.warn(`[KB] Failed to parse symbols from ${file.projectRelPath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
// Compute source hash (git short hash)
|
|
665
|
+
let sourceHash = 'unknown';
|
|
666
|
+
try {
|
|
667
|
+
const { execSync } = await import('node:child_process');
|
|
668
|
+
sourceHash = execSync('git rev-parse --short HEAD', {
|
|
669
|
+
cwd: projectRoot,
|
|
670
|
+
encoding: 'utf-8',
|
|
671
|
+
}).trim();
|
|
672
|
+
}
|
|
673
|
+
catch {
|
|
674
|
+
// Not a git repo or git not available
|
|
675
|
+
}
|
|
676
|
+
return {
|
|
677
|
+
version: '1.0',
|
|
678
|
+
generated_at: new Date().toISOString(),
|
|
679
|
+
source_hash: sourceHash,
|
|
680
|
+
symbols,
|
|
681
|
+
file_count: totalFiles,
|
|
682
|
+
symbol_count: symbols.length,
|
|
683
|
+
};
|
|
684
|
+
}
|
|
685
|
+
/**
|
|
686
|
+
* Compute module hash using adapter's walkModuleFiles.
|
|
687
|
+
* v10.1: Replaces computeModuleHash(moduleDir) with adapter-driven approach.
|
|
688
|
+
*
|
|
689
|
+
* Algorithm matches module-hash.ts:computeModuleHash for cache compatibility:
|
|
690
|
+
* 1. Collect files via adapter.walkModuleFiles
|
|
691
|
+
* 2. For each file, compute sha256(relPath|content)
|
|
692
|
+
* 3. Sort per-file hashes by relPath
|
|
693
|
+
* 4. Hash the joined hashes and truncate to 12 chars
|
|
694
|
+
*/
|
|
695
|
+
async function computeModuleHashForAdapter(module, adapter) {
|
|
696
|
+
const files = await adapter.walkModuleFiles(module);
|
|
697
|
+
// Sort by relPath for deterministic hashing.
|
|
698
|
+
// Use codepoint (`<`/`>`) comparison — NOT localeCompare — to stay
|
|
699
|
+
// byte-for-byte identical to module-hash.ts:computeModuleHash so existing
|
|
700
|
+
// single-project (TypeScript) cache entries keep hitting after this wiring.
|
|
701
|
+
const sorted = files
|
|
702
|
+
.slice()
|
|
703
|
+
.sort((a, b) => (a.relPath < b.relPath ? -1 : a.relPath > b.relPath ? 1 : 0));
|
|
704
|
+
// Compute per-file hashes (same algorithm as module-hash.ts)
|
|
705
|
+
const { createHash } = await import('node:crypto');
|
|
706
|
+
const perFileHashes = sorted.map((f) => createHash('sha256').update(f.relPath + '|' + f.content).digest('hex'));
|
|
707
|
+
// Hash the joined per-file hashes and truncate to 12 chars
|
|
708
|
+
return createHash('sha256')
|
|
709
|
+
.update(perFileHashes.join('\n'))
|
|
710
|
+
.digest('hex')
|
|
711
|
+
.slice(0, 12);
|
|
712
|
+
}
|
|
713
|
+
/**
|
|
714
|
+
* Discover first-level subdirectories of `srcDir`.
|
|
715
|
+
* If `filter` is provided, only those directories are returned.
|
|
716
|
+
*
|
|
717
|
+
* DEPRECATED in v10.1: Use adapter.discoverModules() instead.
|
|
718
|
+
* Kept for backward compatibility with tests.
|
|
719
|
+
*/
|
|
720
|
+
async function discoverModules(srcDir, filter) {
|
|
721
|
+
const entries = await fsAsync.readdir(srcDir, { withFileTypes: true });
|
|
722
|
+
const modules = entries
|
|
723
|
+
.filter((e) => e.isDirectory())
|
|
724
|
+
.map((e) => e.name)
|
|
725
|
+
.filter((name) => !filter || filter.includes(name));
|
|
726
|
+
return modules.sort();
|
|
727
|
+
}
|
|
728
|
+
/**
|
|
729
|
+
* Recursively read all `.ts` source files (excluding `.test.ts`) under
|
|
730
|
+
* `moduleDir`, returning their content as an array.
|
|
731
|
+
*/
|
|
732
|
+
async function readModuleFiles(moduleDir) {
|
|
733
|
+
const result = [];
|
|
734
|
+
async function walk(dir) {
|
|
735
|
+
let entries;
|
|
736
|
+
try {
|
|
737
|
+
entries = await fsAsync.readdir(dir, { withFileTypes: true });
|
|
738
|
+
}
|
|
739
|
+
catch {
|
|
740
|
+
// Directory may not exist (e.g. filter specified a non-existent module).
|
|
741
|
+
return;
|
|
742
|
+
}
|
|
743
|
+
for (const e of entries) {
|
|
744
|
+
const name = e.name;
|
|
745
|
+
const full = path.join(dir, name);
|
|
746
|
+
if (e.isDirectory()) {
|
|
747
|
+
if (name === 'node_modules' || name.startsWith('.'))
|
|
748
|
+
continue;
|
|
749
|
+
await walk(full);
|
|
750
|
+
}
|
|
751
|
+
else if (e.isFile() &&
|
|
752
|
+
name.endsWith('.ts') &&
|
|
753
|
+
!name.endsWith('.test.ts') &&
|
|
754
|
+
!name.endsWith('.d.ts')) {
|
|
755
|
+
try {
|
|
756
|
+
const content = await fsAsync.readFile(full, 'utf-8');
|
|
757
|
+
result.push({ path: path.relative(process.cwd(), full), content });
|
|
758
|
+
}
|
|
759
|
+
catch {
|
|
760
|
+
// Skip unreadable files silently.
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
await walk(moduleDir);
|
|
766
|
+
return result;
|
|
767
|
+
}
|
|
768
|
+
/**
|
|
769
|
+
* Run `fn` over each item in `items` with at most `concurrency` promises
|
|
770
|
+
* in-flight at a time. Preserves the input order in the returned array.
|
|
771
|
+
*/
|
|
772
|
+
async function runWithConcurrency(items, concurrency, fn) {
|
|
773
|
+
const results = new Array(items.length);
|
|
774
|
+
let nextIndex = 0;
|
|
775
|
+
async function worker() {
|
|
776
|
+
while (nextIndex < items.length) {
|
|
777
|
+
const i = nextIndex++;
|
|
778
|
+
results[i] = await fn(items[i]);
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
const workers = Array.from({ length: Math.min(concurrency, items.length) }, () => worker());
|
|
782
|
+
await Promise.all(workers);
|
|
783
|
+
return results;
|
|
784
|
+
}
|
|
785
|
+
/**
|
|
786
|
+
* Build an empty/error placeholder `KBPage` for a module that failed to compile.
|
|
787
|
+
*/
|
|
788
|
+
function makeEmptyPage(moduleName, reason) {
|
|
789
|
+
return {
|
|
790
|
+
name: `modules/${moduleName}.md`,
|
|
791
|
+
title: moduleName,
|
|
792
|
+
content: `<!-- Build failed: ${reason} -->`,
|
|
793
|
+
refs: [],
|
|
794
|
+
generated_at: new Date().toISOString(),
|
|
795
|
+
source_hash: 'unknown',
|
|
796
|
+
ai_model: 'unknown',
|
|
797
|
+
};
|
|
798
|
+
}
|
|
799
|
+
/**
|
|
800
|
+
* Reconstruct a `KBPage` from an existing on-disk markdown file plus the
|
|
801
|
+
* prior build's metadata.
|
|
802
|
+
*
|
|
803
|
+
* This is invoked on cache hits — the .md was last written by `renderPageMarkdown`
|
|
804
|
+
* in a previous build, so the inverse parse here only needs to recover enough
|
|
805
|
+
* structure for `validatePage` to recheck refs.
|
|
806
|
+
*
|
|
807
|
+
* Best-effort: if parsing fails, returns a placeholder with empty refs (validation
|
|
808
|
+
* will report refsTotal=0 but cache reuse still proceeds — the .md on disk is
|
|
809
|
+
* untouched).
|
|
810
|
+
*
|
|
811
|
+
* @internal
|
|
812
|
+
*/
|
|
813
|
+
function makeCachedPagePlaceholder(pageName, moduleName, currentHash, oldMeta, pageOnDisk) {
|
|
814
|
+
const prior = oldMeta.pages[pageName];
|
|
815
|
+
let rawMarkdown = '';
|
|
816
|
+
try {
|
|
817
|
+
rawMarkdown = readFileSync(pageOnDisk, 'utf-8');
|
|
818
|
+
}
|
|
819
|
+
catch {
|
|
820
|
+
// Fall through to a stub page; the cache file should exist (caller checked),
|
|
821
|
+
// but if it suddenly went missing we still return a non-crashing placeholder.
|
|
822
|
+
}
|
|
823
|
+
return {
|
|
824
|
+
name: pageName,
|
|
825
|
+
title: moduleName,
|
|
826
|
+
content: rawMarkdown,
|
|
827
|
+
refs: parseRefsFromMarkdown(rawMarkdown),
|
|
828
|
+
generated_at: oldMeta.generated_at,
|
|
829
|
+
source_hash: currentHash,
|
|
830
|
+
ai_model: prior?.ai_model ?? 'unknown',
|
|
831
|
+
};
|
|
832
|
+
}
|
|
833
|
+
/**
|
|
834
|
+
* Parse the `## References` section of a rendered KB page back into
|
|
835
|
+
* structured `KBRef` entries.
|
|
836
|
+
*
|
|
837
|
+
* Inverse of `renderRef` (validator.ts). Format:
|
|
838
|
+
* - `[\`src/foo.ts:L10\`](../src/foo.ts#L10)`
|
|
839
|
+
* - `[\`src/foo.ts:L10-L20\`](../src/foo.ts#L10-L20)`
|
|
840
|
+
*
|
|
841
|
+
* Tolerant: skips any line that doesn't match the expected shape.
|
|
842
|
+
*
|
|
843
|
+
* @internal
|
|
844
|
+
*/
|
|
845
|
+
function parseRefsFromMarkdown(markdown) {
|
|
846
|
+
const refs = [];
|
|
847
|
+
if (!markdown)
|
|
848
|
+
return refs;
|
|
849
|
+
// Match the `- [`<file>:L<n>[-L<m>]`]` portion of each reference bullet.
|
|
850
|
+
const re = /^- \[`([^`:]+):L(\d+)(?:-L(\d+))?`\]/gm;
|
|
851
|
+
let m;
|
|
852
|
+
while ((m = re.exec(markdown)) !== null) {
|
|
853
|
+
const file = m[1];
|
|
854
|
+
const lineStart = parseInt(m[2], 10);
|
|
855
|
+
const lineEnd = m[3] !== undefined ? parseInt(m[3], 10) : undefined;
|
|
856
|
+
if (Number.isFinite(lineStart)) {
|
|
857
|
+
refs.push(lineEnd !== undefined ? { file, lineStart, lineEnd } : { file, lineStart });
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
return refs;
|
|
861
|
+
}
|
|
862
|
+
/**
|
|
863
|
+
* Render a `KBPage` as a self-contained markdown string, appending a
|
|
864
|
+
* References section with GitHub-style links.
|
|
865
|
+
*/
|
|
866
|
+
function renderPageMarkdown(page) {
|
|
867
|
+
const lines = [
|
|
868
|
+
`# ${page.title}`,
|
|
869
|
+
``,
|
|
870
|
+
`> Generated: ${page.generated_at} | source: \`${page.source_hash}\``,
|
|
871
|
+
``,
|
|
872
|
+
page.content,
|
|
873
|
+
];
|
|
874
|
+
if (page.refs.length > 0) {
|
|
875
|
+
lines.push(``);
|
|
876
|
+
lines.push(`## References`);
|
|
877
|
+
lines.push(``);
|
|
878
|
+
for (const ref of page.refs) {
|
|
879
|
+
lines.push(`- ${renderRef(ref)}`);
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
return lines.join('\n');
|
|
883
|
+
}
|
|
884
|
+
/**
|
|
885
|
+
* Write `.meta.json` to `kbDir` summarising the build.
|
|
886
|
+
*
|
|
887
|
+
* Failure protection: when a page failed AI compilation (`!cached &&
|
|
888
|
+
* source_hash === 'unknown'`), this function preserves the previous build's
|
|
889
|
+
* source_hash for that page (or writes `'build-failed'` if no prior hash
|
|
890
|
+
* exists). This guarantees the next build will detect a cache miss and
|
|
891
|
+
* retry, rather than accidentally locking in a sentinel as a valid hash.
|
|
892
|
+
*
|
|
893
|
+
* source_files semantics (B-1 regression fix):
|
|
894
|
+
* - module pages, fresh AI compile → populated from the page entry's
|
|
895
|
+
* `sourceFiles` (set by buildKnowledge during walkModuleFiles).
|
|
896
|
+
* - module pages, cache hit → carried over from `oldMeta` (or
|
|
897
|
+
* re-walked when legacy meta had `[]`).
|
|
898
|
+
* - cross-module pages → entry omits `sourceFiles`; we record
|
|
899
|
+
* `[]` (these pages are not derived from a fixed file set).
|
|
900
|
+
* - failed AI compile → preserves prior `source_files` from
|
|
901
|
+
* oldMeta so the next retry sees the original tracking, mirroring the
|
|
902
|
+
* `source_hash` failure-protection branch above.
|
|
903
|
+
*/
|
|
904
|
+
function writeMetadata(kbDir, repoMap, pages, oldMeta) {
|
|
905
|
+
// Partial-mode merge (2026-06-01 follow-up #1): when buildKnowledge ran with
|
|
906
|
+
// `options.modules` set, `pages` only includes the requested subset. We must
|
|
907
|
+
// carry over entries for pages NOT touched this run so callers like
|
|
908
|
+
// `cf kb fix --module X` don't truncate the rest of `.meta.json`.
|
|
909
|
+
const meta = {
|
|
910
|
+
version: K.KB_VERSION,
|
|
911
|
+
generated_at: new Date().toISOString(),
|
|
912
|
+
source_hash: repoMap.source_hash,
|
|
913
|
+
pages: { ...(oldMeta?.pages ?? {}) },
|
|
914
|
+
};
|
|
915
|
+
for (const { name, page, validation, cached, sourceFiles } of pages) {
|
|
916
|
+
const isFailedBuild = !cached && page.source_hash === 'unknown';
|
|
917
|
+
const finalHash = isFailedBuild
|
|
918
|
+
? (oldMeta?.pages[name]?.source_hash ?? 'build-failed')
|
|
919
|
+
: page.source_hash;
|
|
920
|
+
const finalSourceFiles = isFailedBuild
|
|
921
|
+
? (oldMeta?.pages[name]?.source_files ?? [])
|
|
922
|
+
: (sourceFiles ?? []);
|
|
923
|
+
meta.pages[name] = {
|
|
924
|
+
source_files: finalSourceFiles,
|
|
925
|
+
source_hash: finalHash,
|
|
926
|
+
ai_model: page.ai_model ?? 'unknown',
|
|
927
|
+
refs_count: page.refs.length,
|
|
928
|
+
audit_status: deriveAuditStatus(validation.issues),
|
|
929
|
+
};
|
|
930
|
+
}
|
|
931
|
+
writeFileSync(path.join(kbDir, K.KB_META_FILE), JSON.stringify(meta, null, 2));
|
|
932
|
+
}
|
|
933
|
+
// D R-D (2026-05-29, spec 0902): the `config()` thin wrapper used to feed
|
|
934
|
+
// `config().ai.model` to KBPage.ai_model when the AI provider didn't echo a
|
|
935
|
+
// model. The `ai.*` schema is gone; a static 'claude-cli' sentinel is used
|
|
936
|
+
// instead at the single call site (see L652).
|
|
937
|
+
//# sourceMappingURL=builder.js.map
|