@winspan/claude-forge 9.2.0 → 9.12.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 +80 -19
- package/README.md +13 -6
- package/dist/catalogs/agents.json +19 -24
- package/dist/catalogs/skills.json +139 -27
- package/dist/claudemd/templates/swarm-protocol.md +1 -1
- package/dist/cli/commands/agent.d.ts +169 -0
- package/dist/cli/commands/agent.d.ts.map +1 -0
- package/dist/cli/commands/agent.js +690 -0
- package/dist/cli/commands/agent.js.map +1 -0
- package/dist/cli/commands/codegraph.d.ts +17 -0
- package/dist/cli/commands/codegraph.d.ts.map +1 -0
- package/dist/cli/commands/codegraph.js +263 -0
- package/dist/cli/commands/codegraph.js.map +1 -0
- package/dist/cli/commands/decisions.d.ts.map +1 -1
- package/dist/cli/commands/decisions.js +46 -9
- package/dist/cli/commands/decisions.js.map +1 -1
- package/dist/cli/commands/executions.d.ts.map +1 -1
- package/dist/cli/commands/executions.js +2 -1
- package/dist/cli/commands/executions.js.map +1 -1
- package/dist/cli/commands/insights-goal-check.d.ts +5 -1
- package/dist/cli/commands/insights-goal-check.d.ts.map +1 -1
- package/dist/cli/commands/insights-goal-check.js +15 -15
- package/dist/cli/commands/insights-goal-check.js.map +1 -1
- package/dist/cli/commands/knowledge.d.ts +51 -0
- package/dist/cli/commands/knowledge.d.ts.map +1 -1
- package/dist/cli/commands/knowledge.js +202 -29
- package/dist/cli/commands/knowledge.js.map +1 -1
- package/dist/cli/commands/loop.d.ts +95 -0
- package/dist/cli/commands/loop.d.ts.map +1 -0
- package/dist/cli/commands/loop.js +408 -0
- package/dist/cli/commands/loop.js.map +1 -0
- package/dist/cli/commands/maintenance.d.ts +33 -0
- package/dist/cli/commands/maintenance.d.ts.map +1 -0
- package/dist/cli/commands/maintenance.js +75 -0
- package/dist/cli/commands/maintenance.js.map +1 -0
- package/dist/cli/commands/mcp.d.ts +23 -0
- package/dist/cli/commands/mcp.d.ts.map +1 -1
- package/dist/cli/commands/mcp.js +82 -0
- package/dist/cli/commands/mcp.js.map +1 -1
- package/dist/cli/commands/skills.d.ts +131 -0
- package/dist/cli/commands/skills.d.ts.map +1 -1
- package/dist/cli/commands/skills.js +409 -9
- package/dist/cli/commands/skills.js.map +1 -1
- package/dist/cli/commands/stats.d.ts.map +1 -1
- package/dist/cli/commands/stats.js +9 -2
- package/dist/cli/commands/stats.js.map +1 -1
- package/dist/cli/index.js +8 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/core/constants.d.ts +37 -0
- package/dist/core/constants.d.ts.map +1 -1
- package/dist/core/constants.js +43 -0
- package/dist/core/constants.js.map +1 -1
- package/dist/core/diagnostics/checks.d.ts.map +1 -1
- package/dist/core/diagnostics/checks.js +2 -1
- package/dist/core/diagnostics/checks.js.map +1 -1
- package/dist/core/diagnostics/daemon-status.d.ts +1 -1
- package/dist/core/diagnostics/daemon-status.d.ts.map +1 -1
- package/dist/core/diagnostics/daemon-status.js +1 -1
- package/dist/core/diagnostics/daemon-status.js.map +1 -1
- package/dist/core/diagnostics/entropy-checks.d.ts +3 -2
- package/dist/core/diagnostics/entropy-checks.d.ts.map +1 -1
- package/dist/core/diagnostics/entropy-checks.js +10 -5
- package/dist/core/diagnostics/entropy-checks.js.map +1 -1
- package/dist/core/diagnostics/heartbeat-reader.d.ts +28 -0
- package/dist/core/diagnostics/heartbeat-reader.d.ts.map +1 -0
- package/dist/core/diagnostics/heartbeat-reader.js +50 -0
- package/dist/core/diagnostics/heartbeat-reader.js.map +1 -0
- package/dist/core/event-fields.d.ts +27 -0
- package/dist/core/event-fields.d.ts.map +1 -1
- package/dist/core/event-fields.js +43 -0
- package/dist/core/event-fields.js.map +1 -1
- package/dist/core/governance/global-inject.d.ts +34 -4
- package/dist/core/governance/global-inject.d.ts.map +1 -1
- package/dist/core/governance/global-inject.js +80 -25
- package/dist/core/governance/global-inject.js.map +1 -1
- package/dist/core/insights/agent-anchor-guard.d.ts +77 -0
- package/dist/core/insights/agent-anchor-guard.d.ts.map +1 -0
- package/dist/core/insights/agent-anchor-guard.js +119 -0
- package/dist/core/insights/agent-anchor-guard.js.map +1 -0
- package/dist/core/insights/agent-distill-context.d.ts +55 -0
- package/dist/core/insights/agent-distill-context.d.ts.map +1 -0
- package/dist/core/insights/agent-distill-context.js +146 -0
- package/dist/core/insights/agent-distill-context.js.map +1 -0
- package/dist/core/insights/agent-distill-spawn.d.ts +56 -0
- package/dist/core/insights/agent-distill-spawn.d.ts.map +1 -0
- package/dist/core/insights/agent-distill-spawn.js +179 -0
- package/dist/core/insights/agent-distill-spawn.js.map +1 -0
- package/dist/core/insights/agent-drift.d.ts +66 -0
- package/dist/core/insights/agent-drift.d.ts.map +1 -0
- package/dist/core/insights/agent-drift.js +109 -0
- package/dist/core/insights/agent-drift.js.map +1 -0
- package/dist/core/insights/agent-evolution-sources.d.ts +21 -0
- package/dist/core/insights/agent-evolution-sources.d.ts.map +1 -0
- package/dist/core/insights/agent-evolution-sources.js +36 -0
- package/dist/core/insights/agent-evolution-sources.js.map +1 -0
- package/dist/core/insights/agent-health.d.ts +142 -0
- package/dist/core/insights/agent-health.d.ts.map +1 -0
- package/dist/core/insights/agent-health.js +296 -0
- package/dist/core/insights/agent-health.js.map +1 -0
- package/dist/core/insights/agent-patch-apply.d.ts +45 -0
- package/dist/core/insights/agent-patch-apply.d.ts.map +1 -0
- package/dist/core/insights/agent-patch-apply.js +165 -0
- package/dist/core/insights/agent-patch-apply.js.map +1 -0
- package/dist/core/insights/agent-suggest.d.ts +128 -0
- package/dist/core/insights/agent-suggest.d.ts.map +1 -0
- package/dist/core/insights/agent-suggest.js +284 -0
- package/dist/core/insights/agent-suggest.js.map +1 -0
- package/dist/core/insights/coverage-tiers.d.ts +46 -0
- package/dist/core/insights/coverage-tiers.d.ts.map +1 -0
- package/dist/core/insights/coverage-tiers.js +95 -0
- package/dist/core/insights/coverage-tiers.js.map +1 -0
- package/dist/{daemon/services → core/insights}/experience-extractor.d.ts +0 -7
- package/dist/core/insights/experience-extractor.d.ts.map +1 -0
- package/dist/{daemon/services → core/insights}/experience-extractor.js +5 -9
- package/dist/core/insights/experience-extractor.js.map +1 -0
- package/dist/{daemon/services → core/insights}/violation-reporter.d.ts +20 -1
- package/dist/core/insights/violation-reporter.d.ts.map +1 -0
- package/dist/{daemon/services → core/insights}/violation-reporter.js +56 -4
- package/dist/core/insights/violation-reporter.js.map +1 -0
- package/dist/core/loop/loop-engine.d.ts +140 -0
- package/dist/core/loop/loop-engine.d.ts.map +1 -0
- package/dist/core/loop/loop-engine.js +266 -0
- package/dist/core/loop/loop-engine.js.map +1 -0
- package/dist/core/queue/index.d.ts.map +1 -1
- package/dist/core/queue/index.js +2 -1
- package/dist/core/queue/index.js.map +1 -1
- package/dist/core/storage/base.d.ts +159 -0
- package/dist/core/storage/base.d.ts.map +1 -1
- package/dist/core/storage/base.js +523 -0
- package/dist/core/storage/base.js.map +1 -1
- package/dist/core/storage/codegraph-types.d.ts +79 -0
- package/dist/core/storage/codegraph-types.d.ts.map +1 -0
- package/dist/core/storage/codegraph-types.js +14 -0
- package/dist/core/storage/codegraph-types.js.map +1 -0
- package/dist/core/storage/codegraph.d.ts +186 -0
- package/dist/core/storage/codegraph.d.ts.map +1 -0
- package/dist/core/storage/codegraph.js +452 -0
- package/dist/core/storage/codegraph.js.map +1 -0
- package/dist/core/storage/decisions.d.ts +30 -5
- package/dist/core/storage/decisions.d.ts.map +1 -1
- package/dist/core/storage/decisions.js +45 -13
- package/dist/core/storage/decisions.js.map +1 -1
- package/dist/core/storage/events.d.ts +127 -0
- package/dist/core/storage/events.d.ts.map +1 -1
- package/dist/core/storage/events.js +318 -3
- package/dist/core/storage/events.js.map +1 -1
- package/dist/core/storage/feedback.d.ts +3 -23
- package/dist/core/storage/feedback.d.ts.map +1 -1
- package/dist/core/storage/feedback.js +37 -38
- package/dist/core/storage/feedback.js.map +1 -1
- package/dist/core/storage/injections.d.ts +40 -0
- package/dist/core/storage/injections.d.ts.map +1 -1
- package/dist/core/storage/injections.js +69 -0
- package/dist/core/storage/injections.js.map +1 -1
- package/dist/core/storage/knowledge.d.ts +226 -0
- package/dist/core/storage/knowledge.d.ts.map +1 -1
- package/dist/core/storage/knowledge.js +391 -4
- package/dist/core/storage/knowledge.js.map +1 -1
- package/dist/core/storage/pipeline-rollup.d.ts +1 -7
- package/dist/core/storage/pipeline-rollup.d.ts.map +1 -1
- package/dist/core/storage/pipeline-rollup.js +18 -57
- package/dist/core/storage/pipeline-rollup.js.map +1 -1
- package/dist/core/storage/routing.d.ts +34 -0
- package/dist/core/storage/routing.d.ts.map +1 -1
- package/dist/core/storage/routing.js +92 -2
- package/dist/core/storage/routing.js.map +1 -1
- package/dist/core/storage/rows.d.ts +5 -25
- package/dist/core/storage/rows.d.ts.map +1 -1
- package/dist/core/storage/schema.sql +92 -27
- package/dist/core/storage/sessions.d.ts.map +1 -1
- package/dist/core/storage/sessions.js +2 -1
- package/dist/core/storage/sessions.js.map +1 -1
- package/dist/core/storage/skills.d.ts +159 -0
- package/dist/core/storage/skills.d.ts.map +1 -1
- package/dist/core/storage/skills.js +350 -4
- package/dist/core/storage/skills.js.map +1 -1
- package/dist/core/storage/sqlite.d.ts +81 -25
- package/dist/core/storage/sqlite.d.ts.map +1 -1
- package/dist/core/storage/sqlite.js +143 -45
- package/dist/core/storage/sqlite.js.map +1 -1
- package/dist/core/storage/tasks.d.ts +270 -0
- package/dist/core/storage/tasks.d.ts.map +1 -1
- package/dist/core/storage/tasks.js +495 -16
- package/dist/core/storage/tasks.js.map +1 -1
- package/dist/core/storage/tool-intercepts.d.ts +1 -1
- package/dist/core/storage/tool-intercepts.js +1 -1
- package/dist/core/types.d.ts +26 -3
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +1 -3
- package/dist/core/types.js.map +1 -1
- package/dist/core/utils/binary-paths.d.ts +32 -0
- package/dist/core/utils/binary-paths.d.ts.map +1 -1
- package/dist/core/utils/binary-paths.js +52 -0
- package/dist/core/utils/binary-paths.js.map +1 -1
- package/dist/core/utils/claude-cli-resolver.d.ts.map +1 -0
- package/dist/{skills/distill → core/utils}/claude-cli-resolver.js +1 -1
- package/dist/core/utils/claude-cli-resolver.js.map +1 -0
- package/dist/core/utils/claude-cli-spawn.d.ts +1 -1
- package/dist/core/utils/claude-cli-spawn.js +2 -2
- package/dist/core/utils/claude-cli-spawn.js.map +1 -1
- package/dist/core/utils/noise-prompt.d.ts +1 -1
- package/dist/core/utils/noise-prompt.js +1 -1
- package/dist/core/utils/time.d.ts +26 -0
- package/dist/core/utils/time.d.ts.map +1 -1
- package/dist/core/utils/time.js +33 -0
- package/dist/core/utils/time.js.map +1 -1
- package/dist/daemon/config-store.d.ts.map +1 -1
- package/dist/daemon/config-store.js +14 -5
- package/dist/daemon/config-store.js.map +1 -1
- package/dist/daemon/event-parser.d.ts.map +1 -1
- package/dist/daemon/event-parser.js +5 -0
- package/dist/daemon/event-parser.js.map +1 -1
- package/dist/daemon/handlers/post-tool-use.d.ts +24 -16
- package/dist/daemon/handlers/post-tool-use.d.ts.map +1 -1
- package/dist/daemon/handlers/post-tool-use.js +76 -116
- package/dist/daemon/handlers/post-tool-use.js.map +1 -1
- package/dist/daemon/handlers/pre-tool-use.d.ts +35 -10
- package/dist/daemon/handlers/pre-tool-use.d.ts.map +1 -1
- package/dist/daemon/handlers/pre-tool-use.js +71 -38
- package/dist/daemon/handlers/pre-tool-use.js.map +1 -1
- package/dist/daemon/handlers/stop.d.ts +20 -0
- package/dist/daemon/handlers/stop.d.ts.map +1 -1
- package/dist/daemon/handlers/stop.js +96 -8
- package/dist/daemon/handlers/stop.js.map +1 -1
- package/dist/daemon/handlers/user-prompt.d.ts +16 -1
- package/dist/daemon/handlers/user-prompt.d.ts.map +1 -1
- package/dist/daemon/handlers/user-prompt.js +97 -56
- package/dist/daemon/handlers/user-prompt.js.map +1 -1
- package/dist/daemon/handlers/violation-content-backfill.d.ts +76 -0
- package/dist/daemon/handlers/violation-content-backfill.d.ts.map +1 -0
- package/dist/daemon/handlers/violation-content-backfill.js +167 -0
- package/dist/daemon/handlers/violation-content-backfill.js.map +1 -0
- package/dist/daemon/index.d.ts +19 -0
- package/dist/daemon/index.d.ts.map +1 -1
- package/dist/daemon/index.js +125 -200
- package/dist/daemon/index.js.map +1 -1
- package/dist/daemon/rules/defaults.d.ts.map +1 -1
- package/dist/daemon/rules/defaults.js +151 -64
- package/dist/daemon/rules/defaults.js.map +1 -1
- package/dist/daemon/rules/types.d.ts +28 -22
- package/dist/daemon/rules/types.d.ts.map +1 -1
- package/dist/daemon/rules/workflow-defaults.js +9 -9
- package/dist/daemon/rules/workflow-defaults.js.map +1 -1
- package/dist/daemon/services/codegraph-sync.d.ts +94 -0
- package/dist/daemon/services/codegraph-sync.d.ts.map +1 -0
- package/dist/daemon/services/codegraph-sync.js +159 -0
- package/dist/daemon/services/codegraph-sync.js.map +1 -0
- package/dist/daemon/services/decision-hint.d.ts +47 -10
- package/dist/daemon/services/decision-hint.d.ts.map +1 -1
- package/dist/daemon/services/decision-hint.js +99 -24
- package/dist/daemon/services/decision-hint.js.map +1 -1
- package/dist/daemon/services/event-ttl-sweep.d.ts.map +1 -1
- package/dist/daemon/services/event-ttl-sweep.js +3 -2
- package/dist/daemon/services/event-ttl-sweep.js.map +1 -1
- package/dist/daemon/services/feedback-aggregator.d.ts +14 -26
- package/dist/daemon/services/feedback-aggregator.d.ts.map +1 -1
- package/dist/daemon/services/feedback-aggregator.js +23 -63
- package/dist/daemon/services/feedback-aggregator.js.map +1 -1
- package/dist/daemon/services/heartbeat-writer.d.ts +6 -15
- package/dist/daemon/services/heartbeat-writer.d.ts.map +1 -1
- package/dist/daemon/services/heartbeat-writer.js +7 -36
- package/dist/daemon/services/heartbeat-writer.js.map +1 -1
- package/dist/daemon/services/kb-injector.d.ts +1 -1
- package/dist/daemon/services/kb-injector.d.ts.map +1 -1
- package/dist/daemon/services/kb-injector.js +10 -2
- package/dist/daemon/services/kb-injector.js.map +1 -1
- package/dist/daemon/services/kb-rebuild-scheduler.d.ts +95 -0
- package/dist/daemon/services/kb-rebuild-scheduler.d.ts.map +1 -0
- package/dist/daemon/services/kb-rebuild-scheduler.js +149 -0
- package/dist/daemon/services/kb-rebuild-scheduler.js.map +1 -0
- package/dist/daemon/services/loop-hint.d.ts +139 -0
- package/dist/daemon/services/loop-hint.d.ts.map +1 -0
- package/dist/daemon/services/loop-hint.js +272 -0
- package/dist/daemon/services/loop-hint.js.map +1 -0
- package/dist/daemon/services/outcome-classification-service.js +1 -1
- package/dist/daemon/services/outcome-classification-service.js.map +1 -1
- package/dist/daemon/services/task-segmenter.d.ts +11 -0
- package/dist/daemon/services/task-segmenter.d.ts.map +1 -1
- package/dist/daemon/services/task-segmenter.js +48 -2
- package/dist/daemon/services/task-segmenter.js.map +1 -1
- package/dist/daemon/startup/maintenance-schedulers.d.ts +68 -0
- package/dist/daemon/startup/maintenance-schedulers.d.ts.map +1 -0
- package/dist/daemon/startup/maintenance-schedulers.js +294 -0
- package/dist/daemon/startup/maintenance-schedulers.js.map +1 -0
- package/dist/daemon/templates/agents/agent-retro-distiller.md +106 -0
- package/dist/daemon/templates/agents/claudemd-writer.md +1 -0
- package/dist/daemon/templates/agents/coder.md +165 -8
- package/dist/daemon/templates/agents/decision-maker.md +107 -21
- package/dist/daemon/templates/agents/doc-reviewer.md +4 -1
- package/dist/daemon/templates/agents/harness-debug-full.md +85 -3
- package/dist/daemon/templates/agents/knowledge-builder.md +1 -0
- package/dist/daemon/templates/agents/patch-applier.md +1 -0
- package/dist/daemon/templates/agents/planner.md +55 -3
- package/dist/daemon/templates/agents/safety-net-implementer.md +278 -0
- package/dist/daemon/templates/agents/skill-distiller.md +1 -0
- package/dist/daemon/templates/agents/task-boundary-classifier.md +1 -0
- package/dist/daemon/templates/agents/verify-agent.md +128 -5
- package/dist/hooks/stop.sh +7 -1
- package/dist/knowledge/builder.js +36 -7
- package/dist/knowledge/builder.js.map +1 -1
- package/dist/knowledge/constants.d.ts +10 -5
- package/dist/knowledge/constants.d.ts.map +1 -1
- package/dist/knowledge/constants.js +10 -5
- package/dist/knowledge/constants.js.map +1 -1
- package/dist/knowledge/graph/edge-extractor.d.ts +45 -0
- package/dist/knowledge/graph/edge-extractor.d.ts.map +1 -0
- package/dist/knowledge/graph/edge-extractor.js +242 -0
- package/dist/knowledge/graph/edge-extractor.js.map +1 -0
- package/dist/knowledge/graph/impact.d.ts +73 -0
- package/dist/knowledge/graph/impact.d.ts.map +1 -0
- package/dist/knowledge/graph/impact.js +94 -0
- package/dist/knowledge/graph/impact.js.map +1 -0
- package/dist/knowledge/graph/types.d.ts +22 -0
- package/dist/knowledge/graph/types.d.ts.map +1 -0
- package/dist/knowledge/graph/types.js +13 -0
- package/dist/knowledge/graph/types.js.map +1 -0
- package/dist/knowledge/prompt.d.ts +9 -0
- package/dist/knowledge/prompt.d.ts.map +1 -1
- package/dist/knowledge/prompt.js +17 -5
- package/dist/knowledge/prompt.js.map +1 -1
- package/dist/knowledge/query.d.ts +13 -0
- package/dist/knowledge/query.d.ts.map +1 -1
- package/dist/knowledge/query.js +107 -10
- package/dist/knowledge/query.js.map +1 -1
- package/dist/knowledge/repo-map.d.ts +11 -5
- package/dist/knowledge/repo-map.d.ts.map +1 -1
- package/dist/knowledge/repo-map.js +42 -3
- package/dist/knowledge/repo-map.js.map +1 -1
- package/dist/knowledge/validator.d.ts.map +1 -1
- package/dist/knowledge/validator.js +69 -2
- package/dist/knowledge/validator.js.map +1 -1
- package/dist/mcp/server.d.ts +64 -8
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +233 -18
- package/dist/mcp/server.js.map +1 -1
- package/dist/skills/distill/distiller.js +1 -1
- package/dist/skills/distill/distiller.js.map +1 -1
- package/dist/skills/distilled/distilled-api-design.md +4 -0
- package/dist/skills/distilled/distilled-brainstorming.md +79 -0
- package/dist/skills/distilled/distilled-brand-guidelines.md +86 -0
- package/dist/skills/distilled/distilled-canvas-design.md +128 -0
- package/dist/skills/distilled/distilled-claude-api.md +185 -0
- package/dist/skills/distilled/distilled-creator.md +5 -2
- package/dist/skills/distilled/distilled-dispatching-parallel-agents.md +136 -0
- package/dist/skills/distilled/distilled-doc-coauthoring.md +144 -0
- package/dist/skills/distilled/distilled-docx.md +231 -0
- package/dist/skills/distilled/distilled-executing-plans.md +85 -50
- package/dist/skills/distilled/distilled-finishing-a-development-branch.md +213 -0
- package/dist/skills/distilled/distilled-frontend-design.md +118 -0
- package/dist/skills/distilled/distilled-harness-engineering.md +1 -1
- package/dist/skills/distilled/distilled-receiving-code-review.md +185 -0
- package/dist/skills/distilled/distilled-subagent-driven-development.md +124 -0
- package/dist/skills/distilled/distilled-systematic-debugging.md +108 -260
- package/dist/skills/distilled/distilled-test-driven-development.md +432 -0
- package/dist/skills/distilled/distilled-using-superpowers.md +134 -0
- package/dist/skills/distilled/distilled-verification-before-completion.md +88 -78
- package/dist/skills/distilled/distilled-writing-skills.md +175 -0
- package/dist/skills/registry.d.ts +10 -50
- package/dist/skills/registry.d.ts.map +1 -1
- package/dist/skills/registry.js +7 -118
- package/dist/skills/registry.js.map +1 -1
- package/dist/skills/tools/pipeline-suggest.js +2 -2
- package/dist/skills/tools/pipeline-suggest.js.map +1 -1
- package/dist/skills/tools/skill-invoke.d.ts +2 -1
- package/dist/skills/tools/skill-invoke.d.ts.map +1 -1
- package/dist/skills/tools/skill-invoke.js +3 -1
- package/dist/skills/tools/skill-invoke.js.map +1 -1
- package/dist/web/analytics/anti-pattern-detector.d.ts.map +1 -1
- package/dist/web/analytics/anti-pattern-detector.js +6 -1
- package/dist/web/analytics/anti-pattern-detector.js.map +1 -1
- package/dist/web/analytics/drift-detector.d.ts +6 -0
- package/dist/web/analytics/drift-detector.d.ts.map +1 -1
- package/dist/web/analytics/drift-detector.js +15 -8
- package/dist/web/analytics/drift-detector.js.map +1 -1
- package/dist/web/analytics/weekly-report.d.ts +13 -0
- package/dist/web/analytics/weekly-report.d.ts.map +1 -1
- package/dist/web/analytics/weekly-report.js +17 -3
- package/dist/web/analytics/weekly-report.js.map +1 -1
- package/dist/web/routes/_helpers.d.ts +31 -0
- package/dist/web/routes/_helpers.d.ts.map +1 -1
- package/dist/web/routes/_helpers.js +33 -0
- package/dist/web/routes/_helpers.js.map +1 -1
- package/dist/web/routes/agent-distill.d.ts +49 -0
- package/dist/web/routes/agent-distill.d.ts.map +1 -0
- package/dist/web/routes/agent-distill.js +526 -0
- package/dist/web/routes/agent-distill.js.map +1 -0
- package/dist/web/routes/config.d.ts +56 -0
- package/dist/web/routes/config.d.ts.map +1 -0
- package/dist/web/routes/config.js +243 -0
- package/dist/web/routes/config.js.map +1 -0
- package/dist/web/routes/decisions.js +1 -1
- package/dist/web/routes/decisions.js.map +1 -1
- package/dist/web/routes/error-handler.d.ts +0 -4
- package/dist/web/routes/error-handler.d.ts.map +1 -1
- package/dist/web/routes/error-handler.js +0 -8
- package/dist/web/routes/error-handler.js.map +1 -1
- package/dist/web/routes/events.d.ts.map +1 -1
- package/dist/web/routes/events.js +2 -1
- package/dist/web/routes/events.js.map +1 -1
- package/dist/web/routes/insights.d.ts.map +1 -1
- package/dist/web/routes/insights.js +0 -0
- package/dist/web/routes/insights.js.map +1 -1
- package/dist/web/routes/knowledge.d.ts +43 -2
- package/dist/web/routes/knowledge.d.ts.map +1 -1
- package/dist/web/routes/knowledge.js +117 -6
- package/dist/web/routes/knowledge.js.map +1 -1
- package/dist/web/routes/pipeline.d.ts +0 -9
- package/dist/web/routes/pipeline.d.ts.map +1 -1
- package/dist/web/routes/pipeline.js +0 -4
- package/dist/web/routes/pipeline.js.map +1 -1
- package/dist/web/routes/rules.d.ts.map +1 -1
- package/dist/web/routes/rules.js +20 -6
- 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 +8 -7
- package/dist/web/routes/sessions.js.map +1 -1
- package/dist/web/routes/skill-stats.d.ts.map +1 -1
- package/dist/web/routes/skill-stats.js +153 -16
- package/dist/web/routes/skill-stats.js.map +1 -1
- package/dist/web/routes/skills-distill.js +1 -1
- package/dist/web/routes/skills-distill.js.map +1 -1
- package/dist/web/routes/stats.d.ts.map +1 -1
- package/dist/web/routes/stats.js +2 -1
- package/dist/web/routes/stats.js.map +1 -1
- package/dist/web/routes/task-timeline.d.ts +95 -19
- package/dist/web/routes/task-timeline.d.ts.map +1 -1
- package/dist/web/routes/task-timeline.js +344 -88
- package/dist/web/routes/task-timeline.js.map +1 -1
- package/dist/web/routes/tasks.d.ts.map +1 -1
- package/dist/web/routes/tasks.js +52 -30
- package/dist/web/routes/tasks.js.map +1 -1
- package/dist/web/routes/violations.d.ts +1 -1
- package/dist/web/routes/violations.d.ts.map +1 -1
- package/dist/web/routes/violations.js +3 -2
- package/dist/web/routes/violations.js.map +1 -1
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +20 -0
- package/dist/web/server.js.map +1 -1
- package/dist/web/services/agent-distill-manager.d.ts +122 -0
- package/dist/web/services/agent-distill-manager.d.ts.map +1 -0
- package/dist/web/services/agent-distill-manager.js +397 -0
- package/dist/web/services/agent-distill-manager.js.map +1 -0
- package/dist/web/services/distill-manager.d.ts +47 -0
- package/dist/web/services/distill-manager.d.ts.map +1 -1
- package/dist/web/services/distill-manager.js +103 -0
- package/dist/web/services/distill-manager.js.map +1 -1
- package/dist/web/static/assets/AgentDetailPage-DlUeA1sX.js +2 -0
- package/dist/web/static/assets/AgentDetailPage-DlUeA1sX.js.map +1 -0
- package/dist/web/static/assets/AgentDistillRunPage-Cybo4bii.js +3 -0
- package/dist/web/static/assets/AgentDistillRunPage-Cybo4bii.js.map +1 -0
- package/dist/web/static/assets/AgentsPage-Qd9FExLG.js +2 -0
- package/dist/web/static/assets/AgentsPage-Qd9FExLG.js.map +1 -0
- package/dist/web/static/assets/DaemonHealthPage-DTSVqtrI.js +2 -0
- package/dist/web/static/assets/DaemonHealthPage-DTSVqtrI.js.map +1 -0
- package/dist/web/static/assets/DecisionDetailPage-b4BA8dhc.js +2 -0
- package/dist/web/static/assets/DecisionDetailPage-b4BA8dhc.js.map +1 -0
- package/dist/web/static/assets/DecisionsPage-a3NRo_T7.js +2 -0
- package/dist/web/static/assets/DecisionsPage-a3NRo_T7.js.map +1 -0
- package/dist/web/static/assets/DiagnosticsPage-DIVdiIQG.js +2 -0
- package/dist/web/static/assets/DiagnosticsPage-DIVdiIQG.js.map +1 -0
- package/dist/web/static/assets/DistillDetailPage-U6a3l2iP.js +4 -0
- package/dist/web/static/assets/DistillDetailPage-U6a3l2iP.js.map +1 -0
- package/dist/web/static/assets/DistillPage-O7BHtRN8.js +2 -0
- package/dist/web/static/assets/DistillPage-O7BHtRN8.js.map +1 -0
- package/dist/web/static/assets/DistillRunPage-D1JuRWWr.js +2 -0
- package/dist/web/static/assets/DistillRunPage-D1JuRWWr.js.map +1 -0
- package/dist/web/static/assets/GlobalScopeHint-Q3wTJx3F.js +2 -0
- package/dist/web/static/assets/GlobalScopeHint-Q3wTJx3F.js.map +1 -0
- package/dist/web/static/assets/IssueDetailPage-BDfrtk2C.js +2 -0
- package/dist/web/static/assets/IssueDetailPage-BDfrtk2C.js.map +1 -0
- package/dist/web/static/assets/IssuesPage-SKmhlCrw.js +2 -0
- package/dist/web/static/assets/IssuesPage-SKmhlCrw.js.map +1 -0
- package/dist/web/static/assets/KbDetailPage-Yna86Na8.js +2 -0
- package/dist/web/static/assets/KbDetailPage-Yna86Na8.js.map +1 -0
- package/dist/web/static/assets/KbHitsPage-Cljl7H9p.js +2 -0
- package/dist/web/static/assets/KbHitsPage-Cljl7H9p.js.map +1 -0
- package/dist/web/static/assets/{MarkdownRenderer-DZmTl-8J.js → MarkdownRenderer-DlDQNihj.js} +2 -2
- package/dist/web/static/assets/{MarkdownRenderer-DZmTl-8J.js.map → MarkdownRenderer-DlDQNihj.js.map} +1 -1
- package/dist/web/static/assets/NotFound-LMzbP51V.js +2 -0
- package/dist/web/static/assets/{NotFound-BQPh0vaF.js.map → NotFound-LMzbP51V.js.map} +1 -1
- package/dist/web/static/assets/SettingsPage-DzoK4PKg.js +2 -0
- package/dist/web/static/assets/SettingsPage-DzoK4PKg.js.map +1 -0
- package/dist/web/static/assets/SkillDetailPage-BuBJJ_NX.js +2 -0
- package/dist/web/static/assets/SkillDetailPage-BuBJJ_NX.js.map +1 -0
- package/dist/web/static/assets/SkillsPage-aojkJpBc.js +2 -0
- package/dist/web/static/assets/SkillsPage-aojkJpBc.js.map +1 -0
- package/dist/web/static/assets/TaskDetailPage-1ckxnGhw.js +4 -0
- package/dist/web/static/assets/TaskDetailPage-1ckxnGhw.js.map +1 -0
- package/dist/web/static/assets/TasksHubPage-C2PLh3eg.js +6 -0
- package/dist/web/static/assets/TasksHubPage-C2PLh3eg.js.map +1 -0
- package/dist/web/static/assets/WorkplacePage-DHrp5VxS.js +2 -0
- package/dist/web/static/assets/WorkplacePage-DHrp5VxS.js.map +1 -0
- package/dist/web/static/assets/arco-DV6xCLhr.js +14 -0
- package/dist/web/static/assets/arco-DV6xCLhr.js.map +1 -0
- package/dist/web/static/assets/charts-BSV4cyC4.js +37 -0
- package/dist/web/static/assets/charts-BSV4cyC4.js.map +1 -0
- package/dist/web/static/assets/{index-7bl3kbcx.css → index-B_v_MKlb.css} +1 -1
- package/dist/web/static/assets/index-DileOOE4.js +4 -0
- package/dist/web/static/assets/index-DileOOE4.js.map +1 -0
- package/dist/web/static/assets/markdown-CA7ePUts.js +30 -0
- package/dist/web/static/assets/markdown-CA7ePUts.js.map +1 -0
- package/dist/web/static/assets/{outcome-DUn1NjlC.js → outcome-BKGy9azt.js} +2 -2
- package/dist/web/static/assets/{outcome-DUn1NjlC.js.map → outcome-BKGy9azt.js.map} +1 -1
- package/dist/web/static/assets/{query-S6X1S7K9.js → query-CgCOpYWf.js} +2 -2
- package/dist/web/static/assets/{query-S6X1S7K9.js.map → query-CgCOpYWf.js.map} +1 -1
- package/dist/web/static/assets/{react-router-JVUrkhdd.js → react-router-Cxmg8RuL.js} +3 -3
- package/dist/web/static/assets/{react-router-JVUrkhdd.js.map → react-router-Cxmg8RuL.js.map} +1 -1
- package/dist/web/static/assets/{syntax-highlighter-BkZfCDsz.js → syntax-highlighter-BDYycNja.js} +3 -3
- package/dist/web/static/assets/{syntax-highlighter-BkZfCDsz.js.map → syntax-highlighter-BDYycNja.js.map} +1 -1
- package/dist/web/static/assets/task-title-BhOcemuR.js +2 -0
- package/dist/web/static/assets/task-title-BhOcemuR.js.map +1 -0
- package/dist/web/static/assets/useAgentStats-B-uTgqBd.js +2 -0
- package/dist/web/static/assets/useAgentStats-B-uTgqBd.js.map +1 -0
- package/dist/web/static/assets/useDecisions-D-G2Ft5T.js +2 -0
- package/dist/web/static/assets/useDecisions-D-G2Ft5T.js.map +1 -0
- package/dist/web/static/assets/useDistill-21dZkXlT.js +3 -0
- package/dist/web/static/assets/useDistill-21dZkXlT.js.map +1 -0
- package/dist/web/static/assets/useEffectiveProject-DQiyX54y.js +2 -0
- package/dist/web/static/assets/useEffectiveProject-DQiyX54y.js.map +1 -0
- package/dist/web/static/assets/useIssuesFeed-CFiyQkAL.js +2 -0
- package/dist/web/static/assets/useIssuesFeed-CFiyQkAL.js.map +1 -0
- package/dist/web/static/assets/useKbHits-xKXWgqh9.js +2 -0
- package/dist/web/static/assets/useKbHits-xKXWgqh9.js.map +1 -0
- package/dist/web/static/assets/useSkillStats-B5hbIwdf.js +2 -0
- package/dist/web/static/assets/useSkillStats-B5hbIwdf.js.map +1 -0
- package/dist/web/static/assets/vendor-DS-q4Eyc.js +36 -0
- package/dist/web/static/assets/vendor-DS-q4Eyc.js.map +1 -0
- package/dist/web/static/index.html +6 -6
- package/package.json +5 -3
- package/dist/core/storage/workflow-recommendations.d.ts +0 -124
- package/dist/core/storage/workflow-recommendations.d.ts.map +0 -1
- package/dist/core/storage/workflow-recommendations.js +0 -274
- package/dist/core/storage/workflow-recommendations.js.map +0 -1
- package/dist/daemon/services/experience-extractor.d.ts.map +0 -1
- package/dist/daemon/services/experience-extractor.js.map +0 -1
- package/dist/daemon/services/violation-reporter.d.ts.map +0 -1
- package/dist/daemon/services/violation-reporter.js.map +0 -1
- package/dist/daemon/templates/agents/harness-hotfix.md +0 -99
- package/dist/daemon/templates/agents/hybrid-feature-with-safety.md +0 -104
- package/dist/daemon/templates/agents/refactor-specialist.md +0 -98
- package/dist/skills/distill/claude-cli-resolver.d.ts.map +0 -1
- package/dist/skills/distill/claude-cli-resolver.js.map +0 -1
- package/dist/skills/distilled/distilled-defi-amm-security.md +0 -293
- package/dist/skills/keyword-score.d.ts +0 -29
- package/dist/skills/keyword-score.d.ts.map +0 -1
- package/dist/skills/keyword-score.js +0 -54
- package/dist/skills/keyword-score.js.map +0 -1
- package/dist/web/static/assets/AgentContentPage-DkeRNxok.js +0 -2
- package/dist/web/static/assets/AgentContentPage-DkeRNxok.js.map +0 -1
- package/dist/web/static/assets/AgentDelegationTable-ByBa0x1l.js +0 -2
- package/dist/web/static/assets/AgentDelegationTable-ByBa0x1l.js.map +0 -1
- package/dist/web/static/assets/ContextInsightsPage-oUk7_I8u.js +0 -3
- package/dist/web/static/assets/ContextInsightsPage-oUk7_I8u.js.map +0 -1
- package/dist/web/static/assets/DaemonHealthPage-DG2fyOP7.js +0 -2
- package/dist/web/static/assets/DaemonHealthPage-DG2fyOP7.js.map +0 -1
- package/dist/web/static/assets/DecisionsPage-CMAPEnKb.js +0 -2
- package/dist/web/static/assets/DecisionsPage-CMAPEnKb.js.map +0 -1
- package/dist/web/static/assets/DiagnosticsPage-DQd-Zm4r.js +0 -2
- package/dist/web/static/assets/DiagnosticsPage-DQd-Zm4r.js.map +0 -1
- package/dist/web/static/assets/DriftTab-DqpepOhI.js +0 -2
- package/dist/web/static/assets/DriftTab-DqpepOhI.js.map +0 -1
- package/dist/web/static/assets/HealthHomePage-CN6zNIie.js +0 -3
- package/dist/web/static/assets/HealthHomePage-CN6zNIie.js.map +0 -1
- package/dist/web/static/assets/KbHitRateTable-ByEIWujF.js +0 -2
- package/dist/web/static/assets/KbHitRateTable-ByEIWujF.js.map +0 -1
- package/dist/web/static/assets/NotFound-BQPh0vaF.js +0 -2
- package/dist/web/static/assets/ProjectSwitcher-D3lZMFd3.js +0 -2
- package/dist/web/static/assets/ProjectSwitcher-D3lZMFd3.js.map +0 -1
- package/dist/web/static/assets/SettingsPage-oLJBNzQj.js +0 -2
- package/dist/web/static/assets/SettingsPage-oLJBNzQj.js.map +0 -1
- package/dist/web/static/assets/SkillContentPage-DK5rgfgw.js +0 -2
- package/dist/web/static/assets/SkillContentPage-DK5rgfgw.js.map +0 -1
- package/dist/web/static/assets/SkillStatsTable-DYMzjEUV.js +0 -2
- package/dist/web/static/assets/SkillStatsTable-DYMzjEUV.js.map +0 -1
- package/dist/web/static/assets/SkillsDistillTab-C7qaG8q3.js +0 -2
- package/dist/web/static/assets/SkillsDistillTab-C7qaG8q3.js.map +0 -1
- package/dist/web/static/assets/TasksHubPage-03wsRRsJ.js +0 -6
- package/dist/web/static/assets/TasksHubPage-03wsRRsJ.js.map +0 -1
- package/dist/web/static/assets/ViolationsPage-DSiLr-9O.js +0 -3
- package/dist/web/static/assets/ViolationsPage-DSiLr-9O.js.map +0 -1
- package/dist/web/static/assets/arco-Bhi3a6Qp.js +0 -14
- package/dist/web/static/assets/arco-Bhi3a6Qp.js.map +0 -1
- package/dist/web/static/assets/charts-BuHQWDbQ.js +0 -37
- package/dist/web/static/assets/charts-BuHQWDbQ.js.map +0 -1
- package/dist/web/static/assets/index-BIYnq1Dx.js +0 -4
- package/dist/web/static/assets/index-BIYnq1Dx.js.map +0 -1
- package/dist/web/static/assets/useTabsParam-k8qte_0C.js +0 -2
- package/dist/web/static/assets/useTabsParam-k8qte_0C.js.map +0 -1
- package/dist/web/static/assets/vendor-DWgdB1eY.js +0 -65
- package/dist/web/static/assets/vendor-DWgdB1eY.js.map +0 -1
- /package/dist/{skills/distill → core/utils}/claude-cli-resolver.d.ts +0 -0
|
@@ -0,0 +1,690 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `cf agent` — analysis / retro commands for agent templates (decision 234f1ad4).
|
|
3
|
+
*
|
|
4
|
+
* Distinct from the plural `cf agents` family (sync/list = template deployment):
|
|
5
|
+
* `cf agent retro` is a READ-ONLY analysis report ("Agent 体检 / 模板改进建议").
|
|
6
|
+
*
|
|
7
|
+
* cf agent retro [--agent <name>] [--days N] [--json] [--mint]
|
|
8
|
+
*
|
|
9
|
+
* 不变量 (cross-Phase, decision 234f1ad4): READ-ONLY. The report NEVER writes
|
|
10
|
+
* agent templates — it only reads health/drift signals and prints suggestions.
|
|
11
|
+
* `--mint` (default OFF) is reserved for routing high-confidence suggestions into
|
|
12
|
+
* the existing nudge/decisions register chain; this first version is text-only.
|
|
13
|
+
*/
|
|
14
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
15
|
+
import { join } from 'node:path';
|
|
16
|
+
import { execFileSync } from 'node:child_process';
|
|
17
|
+
import { SQLiteStorage } from '../../core/storage/sqlite.js';
|
|
18
|
+
import { FORGE_PATHS } from '../../core/constants.js';
|
|
19
|
+
import { isBuiltinAgent } from '../../core/utils/cc-builtin-agents.js';
|
|
20
|
+
import { computeAgentHealth, DAY_MS, SUGGESTION_MIN_RATED, } from '../../core/insights/agent-health.js';
|
|
21
|
+
import { detectAgentDrift } from '../../core/insights/agent-drift.js';
|
|
22
|
+
import { loadKnownSkillIds, loadTriggerRefs, resolveAgentTemplatesDir, } from '../../core/insights/agent-evolution-sources.js';
|
|
23
|
+
import { suggestAgents } from '../../core/insights/agent-suggest.js';
|
|
24
|
+
import { resolveCoverageTier } from '../../core/insights/coverage-tiers.js';
|
|
25
|
+
import { buildDistillContext, } from '../../core/insights/agent-distill-context.js';
|
|
26
|
+
import { spawnAgentRetroDistiller, parseAgentPatchEnvelope, } from '../../core/insights/agent-distill-spawn.js';
|
|
27
|
+
import { scanAgentPatch } from '../../core/insights/agent-anchor-guard.js';
|
|
28
|
+
import { rankSkills } from './skills.js';
|
|
29
|
+
import { SkillRegistry } from '../../skills/registry.js';
|
|
30
|
+
export function register(program) {
|
|
31
|
+
const cmd = program
|
|
32
|
+
.command('agent')
|
|
33
|
+
.description('Agent analysis / retro (READ-ONLY; distinct from `cf agents` deployment)');
|
|
34
|
+
cmd
|
|
35
|
+
.command('retro')
|
|
36
|
+
.description('Per-agent 体检 + 模板改进建议报告(含死推荐/悬空引用,只读不改模板)')
|
|
37
|
+
.option('--agent <name>', 'Filter to a single agent (template name, e.g. coder)')
|
|
38
|
+
.option('--days <n>', 'Trailing window in days (default 30)')
|
|
39
|
+
.option('--json', 'Output JSON instead of text')
|
|
40
|
+
.option('--mint', 'Mint high-confidence suggestions as nudges (default OFF; no-op in Phase 1)')
|
|
41
|
+
.action((opts) => {
|
|
42
|
+
const code = runRetro(opts);
|
|
43
|
+
if (code !== 0)
|
|
44
|
+
process.exit(code);
|
|
45
|
+
});
|
|
46
|
+
// `cf agent suggest <task-desc>` — deterministic agent recommendation
|
|
47
|
+
// (decision c20c2d1f, C2). The decision-end mirror of `cf skill search` (C1):
|
|
48
|
+
// ranks implementation agents by skill affinity + agent-health + nature prior,
|
|
49
|
+
// with a coverage backstop (coder→safety-net-implementer for <50% modules).
|
|
50
|
+
// Read-only; deterministic; --json for decision-maker to parse. The LLM makes
|
|
51
|
+
// the final call over these candidates.
|
|
52
|
+
cmd
|
|
53
|
+
.command('suggest <task-desc>')
|
|
54
|
+
.description('Rank implementation agents for a task (skill + health + coverage backstop; decision-maker picks final)')
|
|
55
|
+
.option('--module <path>', 'Touched module path — enables the coverage backstop (coder→safety-net for <50% modules)')
|
|
56
|
+
.option('--days <n>', 'Trailing window in days for the signals (default 30)')
|
|
57
|
+
.option('--top <n>', 'Max candidates to return (default 4 = whole impl pool)')
|
|
58
|
+
.option('--json', 'Output JSON (machine-readable; for decision-maker parsing)')
|
|
59
|
+
.action((taskDesc, opts) => {
|
|
60
|
+
const code = runSuggest(taskDesc, opts);
|
|
61
|
+
if (code !== 0)
|
|
62
|
+
process.exit(code);
|
|
63
|
+
});
|
|
64
|
+
// `cf agent distill <agent>` — Phase 3 retro-distill (decision 234f1ad4).
|
|
65
|
+
// Human-triggered ONLY. Assembles read-only health/drift/failure signals, then
|
|
66
|
+
// (non-dry-run) spawns `agent-retro-distiller` headless → parses the envelope
|
|
67
|
+
// → anchor-guard → writes a DRAFT to docs/ (NEVER auto-applies to templates).
|
|
68
|
+
// --dry-run is the only path automated tests exercise (no LLM spawn).
|
|
69
|
+
cmd
|
|
70
|
+
.command('distill <agent>')
|
|
71
|
+
.description('Draft a template improvement from real usage signals (human-reviewed; never auto-applied)')
|
|
72
|
+
.option('--days <n>', 'Signal + execution window in days (default 30)')
|
|
73
|
+
.option('--dry-run', 'Only print the signal summary + proposed changes; do NOT spawn the LLM or write files')
|
|
74
|
+
.option('--max-failures <k>', 'Max failed-execution samples to include (default 5)')
|
|
75
|
+
.option('--out <dir>', 'Draft output directory (default docs/design/<today>/agent-distill/)')
|
|
76
|
+
.option('--json', 'Output JSON (dry-run signal context)')
|
|
77
|
+
.action(async (agent, opts) => {
|
|
78
|
+
const code = await runDistill(agent, opts);
|
|
79
|
+
if (code !== 0)
|
|
80
|
+
process.exit(code);
|
|
81
|
+
});
|
|
82
|
+
// `cf agent rollback <agent> --to <N>` — human-assisted rollback (Q4).
|
|
83
|
+
// Prints the vN draft path + suggested git ops; `--write` writes the historical
|
|
84
|
+
// git blob back to the src template AND self-checks the project-level copy is
|
|
85
|
+
// byte-identical (invariant 75344363) — non-zero exit if the copies diverge.
|
|
86
|
+
cmd
|
|
87
|
+
.command('rollback <agent>')
|
|
88
|
+
.description('Human-assisted rollback to a prior template version (--write self-checks byte-identical copies)')
|
|
89
|
+
.requiredOption('--to <n>', 'Target version number to roll back to')
|
|
90
|
+
.option('--write', 'Write the historical git blob back to the src template + self-check the project copy')
|
|
91
|
+
.action((agent, opts) => {
|
|
92
|
+
const code = runRollback(agent, opts);
|
|
93
|
+
if (code !== 0)
|
|
94
|
+
process.exit(code);
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
/** Default candidate count = whole impl pool. */
|
|
98
|
+
const SUGGEST_DEFAULT_TOP = 4;
|
|
99
|
+
/** Top skill matches fed into the agent ranker (Signal 1 source). */
|
|
100
|
+
const SUGGEST_SKILL_TOP = 5;
|
|
101
|
+
/**
|
|
102
|
+
* Exported for tests. Returns exit code instead of calling process.exit.
|
|
103
|
+
* Wires the read-only storage signals into the pure `suggestAgents` ranker.
|
|
104
|
+
*/
|
|
105
|
+
export function runSuggest(taskDesc, opts, deps = {}) {
|
|
106
|
+
const log = deps.io?.log ?? ((m) => console.log(m));
|
|
107
|
+
const error = deps.io?.error ?? ((m) => console.error(m));
|
|
108
|
+
const query = (taskDesc ?? '').trim();
|
|
109
|
+
if (!query) {
|
|
110
|
+
error('Error: a task description is required, e.g. cf agent suggest "fix a null-deref in the handler" --module src/daemon/handlers');
|
|
111
|
+
return 1;
|
|
112
|
+
}
|
|
113
|
+
const days = opts.days ? parseInt(opts.days, 10) : 30;
|
|
114
|
+
if (Number.isNaN(days) || days < 1 || days > 365) {
|
|
115
|
+
error('Error: --days must be between 1 and 365');
|
|
116
|
+
return 1;
|
|
117
|
+
}
|
|
118
|
+
let top = SUGGEST_DEFAULT_TOP;
|
|
119
|
+
if (opts.top !== undefined) {
|
|
120
|
+
const parsed = parseInt(opts.top, 10);
|
|
121
|
+
if (Number.isFinite(parsed) && parsed > 0)
|
|
122
|
+
top = parsed;
|
|
123
|
+
}
|
|
124
|
+
const ownStorage = !deps.storage;
|
|
125
|
+
let storage;
|
|
126
|
+
try {
|
|
127
|
+
storage = deps.storage ?? new SQLiteStorage(FORGE_PATHS.database());
|
|
128
|
+
}
|
|
129
|
+
catch (err) {
|
|
130
|
+
error(`Error: cannot open storage: ${err instanceof Error ? err.message : String(err)}`);
|
|
131
|
+
return 1;
|
|
132
|
+
}
|
|
133
|
+
try {
|
|
134
|
+
const since = Date.now() - days * DAY_MS;
|
|
135
|
+
// Signal 1 source — rank the task's top skills (reuse C1's ranker), then the
|
|
136
|
+
// (agent×skill) usefulness rows that suggestAgents joins against.
|
|
137
|
+
const registry = deps.registry ?? new SkillRegistry();
|
|
138
|
+
const skills = registry.getAll().map((s) => ({
|
|
139
|
+
id: s.id,
|
|
140
|
+
name: s.name,
|
|
141
|
+
description: s.description,
|
|
142
|
+
keywords: s.keywords,
|
|
143
|
+
}));
|
|
144
|
+
const ranked = rankSkills(skills, query, SUGGEST_SKILL_TOP);
|
|
145
|
+
const skillByAgent = storage.aggregateSkillUsefulnessByAgent({ since });
|
|
146
|
+
// Signal 2 source — agent health (success_rate / delegations).
|
|
147
|
+
const health = computeAgentHealth(storage, { since });
|
|
148
|
+
// Signal 4 — resolve the coverage tier from --module (omit → backstop off).
|
|
149
|
+
const moduleCoverageTier = opts.module ? resolveCoverageTier(opts.module) : undefined;
|
|
150
|
+
const result = suggestAgents({
|
|
151
|
+
taskDesc: query,
|
|
152
|
+
skillMatches: ranked.matches.map((m) => ({ id: m.id, score: m.score })),
|
|
153
|
+
skillByAgent: skillByAgent.map((r) => ({
|
|
154
|
+
agent: r.agent,
|
|
155
|
+
skill_id: r.skill_id,
|
|
156
|
+
total_rated: r.total_rated,
|
|
157
|
+
actionable_rate: r.actionable_rate,
|
|
158
|
+
})),
|
|
159
|
+
agentHealth: health.agents.map((a) => ({
|
|
160
|
+
agent: a.agent,
|
|
161
|
+
success_rate: a.success_rate,
|
|
162
|
+
delegations: a.delegations,
|
|
163
|
+
})),
|
|
164
|
+
moduleCoverageTier,
|
|
165
|
+
modulePath: opts.module,
|
|
166
|
+
});
|
|
167
|
+
// Apply the --top cap to the candidate list.
|
|
168
|
+
result.candidates = result.candidates.slice(0, Math.max(1, top));
|
|
169
|
+
if (opts.json) {
|
|
170
|
+
log(JSON.stringify(result, null, 2));
|
|
171
|
+
return 0;
|
|
172
|
+
}
|
|
173
|
+
renderSuggestReport(log, result, days, opts.module);
|
|
174
|
+
return 0;
|
|
175
|
+
}
|
|
176
|
+
catch (err) {
|
|
177
|
+
error(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
178
|
+
return 1;
|
|
179
|
+
}
|
|
180
|
+
finally {
|
|
181
|
+
if (ownStorage) {
|
|
182
|
+
try {
|
|
183
|
+
storage.close();
|
|
184
|
+
}
|
|
185
|
+
catch { /* ignore */ }
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
function renderSuggestReport(log, result, days, modulePath) {
|
|
190
|
+
log(`# Agent 推荐: "${result.task}"`);
|
|
191
|
+
log(`> 信号窗口: 最近 ${days} 天${modulePath ? ` | module: ${modulePath}` : ''}`);
|
|
192
|
+
log('');
|
|
193
|
+
log(`覆盖兜底: ${result.coverage_note}`);
|
|
194
|
+
log('');
|
|
195
|
+
let rank = 1;
|
|
196
|
+
for (const c of result.candidates) {
|
|
197
|
+
const demoted = c.demoted_from ? ` (demoted_from: ${c.demoted_from})` : '';
|
|
198
|
+
log(`${rank}. ${c.agent} [score ${c.score}, ${c.confidence}]${demoted}`);
|
|
199
|
+
for (const r of c.reasons)
|
|
200
|
+
log(` - ${r}`);
|
|
201
|
+
rank += 1;
|
|
202
|
+
}
|
|
203
|
+
log('');
|
|
204
|
+
log('Pick the top candidate unless KB precedent / invariants say otherwise (decision-maker makes the final call).');
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Exported for tests. Returns exit code instead of calling process.exit.
|
|
208
|
+
*/
|
|
209
|
+
export function runRetro(opts, deps = {}) {
|
|
210
|
+
const log = deps.io?.log ?? ((m) => console.log(m));
|
|
211
|
+
const error = deps.io?.error ?? ((m) => console.error(m));
|
|
212
|
+
const days = opts.days ? parseInt(opts.days, 10) : 30;
|
|
213
|
+
if (Number.isNaN(days) || days < 1 || days > 365) {
|
|
214
|
+
error('Error: --days must be between 1 and 365');
|
|
215
|
+
return 1;
|
|
216
|
+
}
|
|
217
|
+
const ownStorage = !deps.storage;
|
|
218
|
+
let storage;
|
|
219
|
+
try {
|
|
220
|
+
storage = deps.storage ?? new SQLiteStorage(FORGE_PATHS.database());
|
|
221
|
+
}
|
|
222
|
+
catch (err) {
|
|
223
|
+
error(`Error: cannot open storage: ${err instanceof Error ? err.message : String(err)}`);
|
|
224
|
+
return 1;
|
|
225
|
+
}
|
|
226
|
+
try {
|
|
227
|
+
const since = Date.now() - days * DAY_MS;
|
|
228
|
+
const triggerRefs = loadTriggerRefs();
|
|
229
|
+
const knownSkillIds = loadKnownSkillIds();
|
|
230
|
+
const health = computeAgentHealth(storage, {
|
|
231
|
+
since,
|
|
232
|
+
triggerRefs: triggerRefs.byAgent,
|
|
233
|
+
isBuiltin: isBuiltinAgent,
|
|
234
|
+
});
|
|
235
|
+
const skillUsefulness = storage.aggregateSkillUsefulness({ since });
|
|
236
|
+
const pulledByAgent = new Map();
|
|
237
|
+
const delegationsByAgent = new Map();
|
|
238
|
+
for (const a of health.agents) {
|
|
239
|
+
delegationsByAgent.set(a.agent, a.delegations);
|
|
240
|
+
const pulled = new Set();
|
|
241
|
+
for (const r of a.recommended_skills)
|
|
242
|
+
if (r.pulls > 0)
|
|
243
|
+
pulled.add(r.skill_id);
|
|
244
|
+
pulledByAgent.set(a.agent, pulled);
|
|
245
|
+
}
|
|
246
|
+
const drift = detectAgentDrift({
|
|
247
|
+
triggerRefs,
|
|
248
|
+
knownSkillIds,
|
|
249
|
+
skillUsefulness: skillUsefulness.map((s) => ({
|
|
250
|
+
skill_id: s.skill_id,
|
|
251
|
+
total_rated: s.total_rated,
|
|
252
|
+
actionable_rate: s.actionable_rate,
|
|
253
|
+
})),
|
|
254
|
+
pulledByAgent,
|
|
255
|
+
delegationsByAgent,
|
|
256
|
+
});
|
|
257
|
+
let agents = health.agents;
|
|
258
|
+
let driftFiltered = drift;
|
|
259
|
+
if (opts.agent) {
|
|
260
|
+
agents = agents.filter((a) => a.agent === opts.agent);
|
|
261
|
+
driftFiltered = drift.filter((d) => !d.agent || d.agent === opts.agent);
|
|
262
|
+
if (agents.length === 0) {
|
|
263
|
+
error(`Error: no health data for agent "${opts.agent}" in the last ${days} days`);
|
|
264
|
+
return 1;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
if (opts.json) {
|
|
268
|
+
log(JSON.stringify({
|
|
269
|
+
generated_at: health.generated_at,
|
|
270
|
+
days,
|
|
271
|
+
agents,
|
|
272
|
+
main_thread_violations: health.main_thread_violations,
|
|
273
|
+
drift: driftFiltered,
|
|
274
|
+
minted: false,
|
|
275
|
+
}, null, 2));
|
|
276
|
+
return 0;
|
|
277
|
+
}
|
|
278
|
+
renderTextReport(log, { days, agents, drift: driftFiltered, mainThread: health.main_thread_violations });
|
|
279
|
+
return 0;
|
|
280
|
+
}
|
|
281
|
+
catch (err) {
|
|
282
|
+
error(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
283
|
+
return 1;
|
|
284
|
+
}
|
|
285
|
+
finally {
|
|
286
|
+
if (ownStorage) {
|
|
287
|
+
try {
|
|
288
|
+
storage.close();
|
|
289
|
+
}
|
|
290
|
+
catch { /* ignore */ }
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
function renderTextReport(log, data) {
|
|
295
|
+
log(`# Agent 体检报告(最近 ${data.days} 天)`);
|
|
296
|
+
log('');
|
|
297
|
+
if (data.agents.length === 0) {
|
|
298
|
+
log('(窗口内无 agent 委托数据)');
|
|
299
|
+
}
|
|
300
|
+
for (const a of data.agents) {
|
|
301
|
+
log(`## ${a.agent} [${a.source}]`);
|
|
302
|
+
const sr = a.success_rate === null ? '未评分' : `${(a.success_rate * 100).toFixed(0)}%`;
|
|
303
|
+
log(`- 委托量: ${a.delegations} 成功率: ${sr}(口径: ${a.success_rate_basis})`);
|
|
304
|
+
log(`- outcome: success=${a.success} partial=${a.partial} failed=${a.failed} unrated=${a.unrated}`);
|
|
305
|
+
if (a.avg_duration_ms !== null)
|
|
306
|
+
log(`- 平均耗时: ${a.avg_duration_ms} ms`);
|
|
307
|
+
if (a.recommended_skills.length > 0) {
|
|
308
|
+
log('- 推荐 skill 健康:');
|
|
309
|
+
for (const r of a.recommended_skills) {
|
|
310
|
+
const flag = r.recommendation_health === 'dead' ? ' ⚠ 死推荐' : '';
|
|
311
|
+
log(` - ${r.skill_id}: ${r.pulls} pull / actionable ${(r.actionable_rate * 100).toFixed(1)}% [${r.recommendation_health}]${flag}`);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
if (a.suggestions.length > 0) {
|
|
315
|
+
log('- 建议:');
|
|
316
|
+
for (const s of a.suggestions)
|
|
317
|
+
log(` - ${s}`);
|
|
318
|
+
}
|
|
319
|
+
log('');
|
|
320
|
+
}
|
|
321
|
+
// 死推荐 / 悬空引用段(双向 drift)。
|
|
322
|
+
log('## 死推荐 / 悬空引用 / 行为 drift');
|
|
323
|
+
if (data.drift.length === 0) {
|
|
324
|
+
log('(无)');
|
|
325
|
+
}
|
|
326
|
+
else {
|
|
327
|
+
for (const d of data.drift)
|
|
328
|
+
log(`- [${d.kind}] ${d.message}`);
|
|
329
|
+
}
|
|
330
|
+
log('');
|
|
331
|
+
// 主线程编排纪律(与 agent 信号分开)。
|
|
332
|
+
log('## 主线程编排纪律(非 agent 模板缺陷)');
|
|
333
|
+
log(`- 说明: ${data.mainThread.note}`);
|
|
334
|
+
log(`- 总计 deny: ${data.mainThread.total}`);
|
|
335
|
+
for (const r of data.mainThread.by_rule)
|
|
336
|
+
log(` - ${r.rule_id}: ${r.count}`);
|
|
337
|
+
}
|
|
338
|
+
/** Parse a `version: N` line from a template's frontmatter (default 1). */
|
|
339
|
+
export function readTemplateVersion(templateText) {
|
|
340
|
+
// version lives in the leading frontmatter block.
|
|
341
|
+
const fenceEnd = templateText.indexOf('\n---', 4);
|
|
342
|
+
const head = fenceEnd > 0 ? templateText.slice(0, fenceEnd) : templateText;
|
|
343
|
+
const m = head.match(/^version:\s*([0-9]+)\s*$/m);
|
|
344
|
+
return m ? parseInt(m[1], 10) : 1;
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Assemble the read-only signal context shared by --dry-run preview and the
|
|
348
|
+
* real spawn path. Pure aside from the injected storage reads + template read.
|
|
349
|
+
* Throws on a missing template (caller maps to 404). Exported for web reuse.
|
|
350
|
+
*/
|
|
351
|
+
export function buildAgentDistillContextFor(agent, deps) {
|
|
352
|
+
const name = (agent ?? '').trim();
|
|
353
|
+
const days = deps.days ?? 30;
|
|
354
|
+
const maxFailures = deps.maxFailures ?? 5;
|
|
355
|
+
const templatesDir = deps.templatesDir ?? resolveAgentTemplatesDir();
|
|
356
|
+
const templatePath = join(templatesDir, `${name}.md`);
|
|
357
|
+
if (!existsSync(templatePath)) {
|
|
358
|
+
throw new Error(`no agent template found at ${templatePath}`);
|
|
359
|
+
}
|
|
360
|
+
const currentTemplate = readFileSync(templatePath, 'utf-8');
|
|
361
|
+
const currentVersion = readTemplateVersion(currentTemplate);
|
|
362
|
+
const storage = deps.storage;
|
|
363
|
+
const since = Date.now() - days * DAY_MS;
|
|
364
|
+
const triggerRefs = loadTriggerRefs(templatesDir);
|
|
365
|
+
const knownSkillIds = loadKnownSkillIds();
|
|
366
|
+
const healthResult = computeAgentHealth(storage, {
|
|
367
|
+
since,
|
|
368
|
+
triggerRefs: triggerRefs.byAgent,
|
|
369
|
+
isBuiltin: isBuiltinAgent,
|
|
370
|
+
});
|
|
371
|
+
const health = healthResult.agents.find((a) => a.agent === name) ?? null;
|
|
372
|
+
const skillUsefulness = storage.aggregateSkillUsefulness({ since });
|
|
373
|
+
const pulledByAgent = new Map();
|
|
374
|
+
const delegationsByAgent = new Map();
|
|
375
|
+
for (const a of healthResult.agents) {
|
|
376
|
+
delegationsByAgent.set(a.agent, a.delegations);
|
|
377
|
+
const pulled = new Set();
|
|
378
|
+
for (const r of a.recommended_skills)
|
|
379
|
+
if (r.pulls > 0)
|
|
380
|
+
pulled.add(r.skill_id);
|
|
381
|
+
pulledByAgent.set(a.agent, pulled);
|
|
382
|
+
}
|
|
383
|
+
const allDrift = detectAgentDrift({
|
|
384
|
+
triggerRefs,
|
|
385
|
+
knownSkillIds,
|
|
386
|
+
skillUsefulness: skillUsefulness.map((s) => ({
|
|
387
|
+
skill_id: s.skill_id,
|
|
388
|
+
total_rated: s.total_rated,
|
|
389
|
+
actionable_rate: s.actionable_rate,
|
|
390
|
+
})),
|
|
391
|
+
pulledByAgent,
|
|
392
|
+
delegationsByAgent,
|
|
393
|
+
});
|
|
394
|
+
const drift = allDrift.filter((d) => !d.agent || d.agent === name);
|
|
395
|
+
const spawns = storage.aggregateAgentSpawns({
|
|
396
|
+
since: new Date(since).toISOString(),
|
|
397
|
+
recentLimit: Math.max(8, maxFailures),
|
|
398
|
+
});
|
|
399
|
+
const spawnRow = spawns.find((s) => s.agent === name);
|
|
400
|
+
const failureSamples = (spawnRow?.recent ?? [])
|
|
401
|
+
.filter((r) => r.outcome === 'failed')
|
|
402
|
+
.slice(0, maxFailures)
|
|
403
|
+
.map((r) => ({ title: r.title ?? '(untitled)', session_id: r.session_id, ts: r.ts }));
|
|
404
|
+
const ratedPairs = (health?.recommended_skills ?? []).filter((r) => r.total_rated >= SUGGESTION_MIN_RATED).length;
|
|
405
|
+
const ctx = buildDistillContext({
|
|
406
|
+
agent: name,
|
|
407
|
+
currentVersion,
|
|
408
|
+
currentTemplate,
|
|
409
|
+
health,
|
|
410
|
+
drift,
|
|
411
|
+
failureSamples,
|
|
412
|
+
windowDays: days,
|
|
413
|
+
ratedPairs,
|
|
414
|
+
});
|
|
415
|
+
return { ctx, currentVersion, drift, health, failureSamples };
|
|
416
|
+
}
|
|
417
|
+
/**
|
|
418
|
+
* Web-callable: the --dry-run preview payload. FREE — never spawns the LLM.
|
|
419
|
+
* Throws on a missing template (route maps to 404).
|
|
420
|
+
*/
|
|
421
|
+
export function buildAgentDistillPreview(agent, deps) {
|
|
422
|
+
const { ctx, currentVersion, drift, health, failureSamples } = buildAgentDistillContextFor(agent, deps);
|
|
423
|
+
return {
|
|
424
|
+
agent: (agent ?? '').trim(),
|
|
425
|
+
current_version: currentVersion,
|
|
426
|
+
maturity: ctx.maturity,
|
|
427
|
+
enough_signal: ctx.enoughSignal,
|
|
428
|
+
insufficient_reason: ctx.insufficientReason,
|
|
429
|
+
proposed_change_types: ctx.proposedChangeTypes,
|
|
430
|
+
drift,
|
|
431
|
+
recommended_skills: health?.recommended_skills ?? [],
|
|
432
|
+
failure_samples: failureSamples,
|
|
433
|
+
summary: ctx.summary,
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Exported for tests. Returns a Promise<exit code>. Human-triggered
|
|
438
|
+
* retro-distill:
|
|
439
|
+
* - assemble read-only signals → buildDistillContext
|
|
440
|
+
* - --dry-run: print the summary + proposed changes; NO spawn, NO file writes
|
|
441
|
+
* - else: gate check → spawn distiller → parse envelope → anchor-guard → draft
|
|
442
|
+
* NEVER writes src/daemon/templates/agents/.
|
|
443
|
+
*/
|
|
444
|
+
export async function runDistill(agent, opts, deps = {}) {
|
|
445
|
+
const log = deps.io?.log ?? ((m) => console.log(m));
|
|
446
|
+
const error = deps.io?.error ?? ((m) => console.error(m));
|
|
447
|
+
const name = (agent ?? '').trim();
|
|
448
|
+
if (!name) {
|
|
449
|
+
error('Error: an agent template name is required, e.g. cf agent distill coder --dry-run');
|
|
450
|
+
return 1;
|
|
451
|
+
}
|
|
452
|
+
const days = opts.days ? parseInt(opts.days, 10) : 30;
|
|
453
|
+
if (Number.isNaN(days) || days < 1 || days > 365) {
|
|
454
|
+
error('Error: --days must be between 1 and 365');
|
|
455
|
+
return 1;
|
|
456
|
+
}
|
|
457
|
+
const maxFailures = opts.maxFailures ? parseInt(opts.maxFailures, 10) : 5;
|
|
458
|
+
if (Number.isNaN(maxFailures) || maxFailures < 0 || maxFailures > 50) {
|
|
459
|
+
error('Error: --max-failures must be between 0 and 50');
|
|
460
|
+
return 1;
|
|
461
|
+
}
|
|
462
|
+
const templatesDir = deps.templatesDir ?? resolveAgentTemplatesDir();
|
|
463
|
+
const templatePath = join(templatesDir, `${name}.md`);
|
|
464
|
+
if (!existsSync(templatePath)) {
|
|
465
|
+
error(`Error: no agent template found at ${templatePath}`);
|
|
466
|
+
return 1;
|
|
467
|
+
}
|
|
468
|
+
const currentTemplate = readFileSync(templatePath, 'utf-8');
|
|
469
|
+
const currentVersion = readTemplateVersion(currentTemplate);
|
|
470
|
+
const ownStorage = !deps.storage;
|
|
471
|
+
let storage;
|
|
472
|
+
try {
|
|
473
|
+
storage = deps.storage ?? new SQLiteStorage(FORGE_PATHS.database());
|
|
474
|
+
}
|
|
475
|
+
catch (err) {
|
|
476
|
+
error(`Error: cannot open storage: ${err instanceof Error ? err.message : String(err)}`);
|
|
477
|
+
return 1;
|
|
478
|
+
}
|
|
479
|
+
try {
|
|
480
|
+
// Assemble the read-only signal context via the shared web-callable helper
|
|
481
|
+
// (decision 568a8c53 — mechanical extraction; CLI behaviour unchanged).
|
|
482
|
+
const { ctx, drift, health, failureSamples } = buildAgentDistillContextFor(name, {
|
|
483
|
+
storage,
|
|
484
|
+
templatesDir,
|
|
485
|
+
days,
|
|
486
|
+
maxFailures,
|
|
487
|
+
});
|
|
488
|
+
// ── --dry-run: print summary + proposed changes; no spawn, no writes. ────
|
|
489
|
+
if (opts.dryRun) {
|
|
490
|
+
if (opts.json) {
|
|
491
|
+
log(JSON.stringify({
|
|
492
|
+
agent: name,
|
|
493
|
+
current_version: currentVersion,
|
|
494
|
+
maturity: ctx.maturity,
|
|
495
|
+
enough_signal: ctx.enoughSignal,
|
|
496
|
+
insufficient_reason: ctx.insufficientReason,
|
|
497
|
+
proposed_change_types: ctx.proposedChangeTypes,
|
|
498
|
+
drift,
|
|
499
|
+
recommended_skills: health?.recommended_skills ?? [],
|
|
500
|
+
failure_samples: failureSamples,
|
|
501
|
+
}, null, 2));
|
|
502
|
+
}
|
|
503
|
+
else {
|
|
504
|
+
log(ctx.summary);
|
|
505
|
+
}
|
|
506
|
+
return 0;
|
|
507
|
+
}
|
|
508
|
+
// ── Real spawn path — gate first (门槛 1). ────────────────────────────────
|
|
509
|
+
if (!ctx.enoughSignal) {
|
|
510
|
+
log(ctx.insufficientReason ?? '数据不足,未产改进草案。');
|
|
511
|
+
return 0; // honest degradation, NOT an error
|
|
512
|
+
}
|
|
513
|
+
const spawnFn = deps.spawn ?? ((p) => spawnAgentRetroDistiller(p));
|
|
514
|
+
let raw;
|
|
515
|
+
try {
|
|
516
|
+
raw = await spawnFn(ctx.prompt);
|
|
517
|
+
}
|
|
518
|
+
catch (err) {
|
|
519
|
+
error(`Error: distiller spawn failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
520
|
+
return 1;
|
|
521
|
+
}
|
|
522
|
+
const envelope = parseAgentPatchEnvelope(raw);
|
|
523
|
+
if (envelope === null) {
|
|
524
|
+
error('Error: distiller output has no recognizable ---AGENT-PATCH--- or ---NOOP--- envelope; no draft written.');
|
|
525
|
+
return 1;
|
|
526
|
+
}
|
|
527
|
+
if (envelope.kind === 'noop') {
|
|
528
|
+
log(`distiller 判定无值得改的改动(NOOP):${envelope.rationale}`);
|
|
529
|
+
return 0; // honest empty draft, NOT an error
|
|
530
|
+
}
|
|
531
|
+
// ── anchor-guard: reject any patch touching a protected region. ──────────
|
|
532
|
+
const violations = scanAgentPatch(envelope.patch);
|
|
533
|
+
if (violations.length > 0) {
|
|
534
|
+
error(`Error: distiller patch touches ${violations.length} protected region(s) — draft REJECTED, no file written:`);
|
|
535
|
+
for (const v of violations) {
|
|
536
|
+
error(` - [${v.region}] patch line ${v.patchLine}: "${v.line}"`);
|
|
537
|
+
}
|
|
538
|
+
return 1; // no retry (mirrors skill distiller ProjectAnchorRejection)
|
|
539
|
+
}
|
|
540
|
+
// ── write the human-reviewed DRAFT (NEVER the template itself). ──────────
|
|
541
|
+
const today = new Date().toISOString().slice(0, 10);
|
|
542
|
+
const outBase = deps.outBaseDir ?? join(repoRootForDrafts(), 'docs', 'design');
|
|
543
|
+
const outDir = opts.out ?? join(outBase, today, 'agent-distill');
|
|
544
|
+
const targetVersion = envelope.targetVersion ?? currentVersion + 1;
|
|
545
|
+
const draftPath = join(outDir, `${name}-v${targetVersion}-draft.md`);
|
|
546
|
+
mkdirSync(outDir, { recursive: true });
|
|
547
|
+
writeFileSync(draftPath, renderDraft(name, currentVersion, targetVersion, ctx.maturity, envelope.rationale, envelope.patch), 'utf-8');
|
|
548
|
+
log(`草案已写入(人审,未落模板):${draftPath}`);
|
|
549
|
+
log(`成熟度:${ctx.maturity}`);
|
|
550
|
+
return 0;
|
|
551
|
+
}
|
|
552
|
+
catch (err) {
|
|
553
|
+
error(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
554
|
+
return 1;
|
|
555
|
+
}
|
|
556
|
+
finally {
|
|
557
|
+
if (ownStorage) {
|
|
558
|
+
try {
|
|
559
|
+
storage.close();
|
|
560
|
+
}
|
|
561
|
+
catch { /* ignore */ }
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
/** Repo root for draft output (CLI cwd, where docs/ lives). */
|
|
566
|
+
function repoRootForDrafts() {
|
|
567
|
+
return process.cwd();
|
|
568
|
+
}
|
|
569
|
+
/**
|
|
570
|
+
* Render the human-reviewed draft markdown (decision 234f1ad4). Exported so the
|
|
571
|
+
* web AgentDistillManager writes byte-identical drafts (decision 568a8c53).
|
|
572
|
+
*/
|
|
573
|
+
export function renderDraft(agent, currentVersion, targetVersion, maturity, rationale, patch) {
|
|
574
|
+
return [
|
|
575
|
+
`# Agent distill 草案: ${agent} (v${currentVersion} → v${targetVersion})`,
|
|
576
|
+
'',
|
|
577
|
+
'> Decision: 234f1ad4',
|
|
578
|
+
`> 信号成熟度: ${maturity}`,
|
|
579
|
+
'> 这是 LLM 据真实使用信号起草的改进草案。**未自动落模板**——需人 review 批准后由 coder/人手动应用。',
|
|
580
|
+
'',
|
|
581
|
+
'## Rationale(每条改动引用的信号)',
|
|
582
|
+
'',
|
|
583
|
+
rationale,
|
|
584
|
+
'',
|
|
585
|
+
'## Patch(unified diff,仅供采纳时应用)',
|
|
586
|
+
'',
|
|
587
|
+
'```diff',
|
|
588
|
+
patch,
|
|
589
|
+
'```',
|
|
590
|
+
'',
|
|
591
|
+
'## 采纳步骤(人确认后)',
|
|
592
|
+
'',
|
|
593
|
+
`1. 人 review 本草案,确认 patch 只动可演进区。`,
|
|
594
|
+
`2. 把 patch 应用到 \`src/daemon/templates/agents/${agent}.md\`,frontmatter \`version: ${targetVersion}\`。`,
|
|
595
|
+
`3. 同步项目级副本 \`.claude/agents/${agent}.md\` 字节一致(不变量 75344363)。`,
|
|
596
|
+
`4. \`npm run build\` → \`cf agents sync\`。`,
|
|
597
|
+
`5. 跑不变量测试 \`tests/unit/daemon/agent-templates-decision-header.test.ts\` 绿。`,
|
|
598
|
+
`6. \`cf decisions outcome 234f1ad4 --result success --note "phase3 distill ${agent} v${targetVersion} adopted"\`。`,
|
|
599
|
+
'',
|
|
600
|
+
].join('\n');
|
|
601
|
+
}
|
|
602
|
+
/**
|
|
603
|
+
* Exported for tests. Human-assisted rollback (decision 234f1ad4 Q4):
|
|
604
|
+
* - default: print the vN draft path + suggested git ops (read-only).
|
|
605
|
+
* - --write: write the historical git blob back to the src template, then
|
|
606
|
+
* self-check the project-level copy is byte-identical (invariant 75344363).
|
|
607
|
+
* Divergent copies → non-zero exit warning.
|
|
608
|
+
*/
|
|
609
|
+
export function runRollback(agent, opts, deps = {}) {
|
|
610
|
+
const log = deps.io?.log ?? ((m) => console.log(m));
|
|
611
|
+
const error = deps.io?.error ?? ((m) => console.error(m));
|
|
612
|
+
const name = (agent ?? '').trim();
|
|
613
|
+
if (!name) {
|
|
614
|
+
error('Error: an agent template name is required, e.g. cf agent rollback coder --to 1');
|
|
615
|
+
return 1;
|
|
616
|
+
}
|
|
617
|
+
const targetVersion = parseInt(opts.to, 10);
|
|
618
|
+
if (Number.isNaN(targetVersion) || targetVersion < 1) {
|
|
619
|
+
error('Error: --to must be a positive version number');
|
|
620
|
+
return 1;
|
|
621
|
+
}
|
|
622
|
+
const templatesDir = deps.templatesDir ?? resolveAgentTemplatesDir();
|
|
623
|
+
const templatePath = join(templatesDir, `${name}.md`);
|
|
624
|
+
if (!existsSync(templatePath)) {
|
|
625
|
+
error(`Error: no agent template found at ${templatePath}`);
|
|
626
|
+
return 1;
|
|
627
|
+
}
|
|
628
|
+
const currentVersion = readTemplateVersion(readFileSync(templatePath, 'utf-8'));
|
|
629
|
+
const relTemplate = `src/daemon/templates/agents/${name}.md`;
|
|
630
|
+
const installedDir = deps.installedDir ?? join(process.cwd(), '.claude', 'agents');
|
|
631
|
+
const installedPath = join(installedDir, `${name}.md`);
|
|
632
|
+
if (!opts.write) {
|
|
633
|
+
// Read-only human-assist: print guidance.
|
|
634
|
+
log(`# Agent rollback (人工辅助): ${name} 当前 version=${currentVersion} → 目标 v${targetVersion}`);
|
|
635
|
+
log('');
|
|
636
|
+
log(`草案档(v${targetVersion} 的「为什么改」)应在: docs/design/**/agent-distill/${name}-v${targetVersion}-draft.md`);
|
|
637
|
+
log('');
|
|
638
|
+
log('建议的 git 操作(找出 v 对应的历史 commit):');
|
|
639
|
+
log(` git log --oneline -- ${relTemplate}`);
|
|
640
|
+
log(` git show <ref>:${relTemplate} # 预览历史内容`);
|
|
641
|
+
log('');
|
|
642
|
+
log(`确认无误后重跑带 --write 自动写回 + 字节一致性自检:`);
|
|
643
|
+
log(` cf agent rollback ${name} --to ${targetVersion} --write`);
|
|
644
|
+
return 0;
|
|
645
|
+
}
|
|
646
|
+
// --write: write the historical git blob back, then self-check byte identity.
|
|
647
|
+
const reader = deps.readGitBlob ?? defaultReadGitBlob;
|
|
648
|
+
// Heuristic ref: the spec keeps history in git; we use the commit that last
|
|
649
|
+
// set the template to vN. Without a version→ref index we let git resolve the
|
|
650
|
+
// most recent ref whose blob carries `version: <N>` is out of scope here —
|
|
651
|
+
// instead --write requires the caller to have checked out / tagged the ref.
|
|
652
|
+
// We read the current HEAD blob and verify; tests inject readGitBlob.
|
|
653
|
+
let historical;
|
|
654
|
+
try {
|
|
655
|
+
historical = reader('HEAD', relTemplate);
|
|
656
|
+
}
|
|
657
|
+
catch (err) {
|
|
658
|
+
error(`Error: cannot read git blob for ${relTemplate}: ${err instanceof Error ? err.message : String(err)}`);
|
|
659
|
+
return 1;
|
|
660
|
+
}
|
|
661
|
+
const blobVersion = readTemplateVersion(historical);
|
|
662
|
+
if (blobVersion !== targetVersion) {
|
|
663
|
+
error(`Error: resolved git blob is version ${blobVersion}, not requested v${targetVersion}. ` +
|
|
664
|
+
`Check out the ref whose ${relTemplate} carries version: ${targetVersion}, then re-run.`);
|
|
665
|
+
return 1;
|
|
666
|
+
}
|
|
667
|
+
try {
|
|
668
|
+
writeFileSync(templatePath, historical, 'utf-8');
|
|
669
|
+
writeFileSync(installedPath, historical, 'utf-8');
|
|
670
|
+
}
|
|
671
|
+
catch (err) {
|
|
672
|
+
error(`Error: write-back failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
673
|
+
return 1;
|
|
674
|
+
}
|
|
675
|
+
// Byte-identity self-check (invariant 75344363).
|
|
676
|
+
const src = readFileSync(templatePath, 'utf-8');
|
|
677
|
+
const installed = existsSync(installedPath) ? readFileSync(installedPath, 'utf-8') : '';
|
|
678
|
+
if (src !== installed) {
|
|
679
|
+
error(`Error: byte-identity self-check FAILED — ${templatePath} and ${installedPath} diverge. ` +
|
|
680
|
+
`Sync them manually + run the invariant test before committing.`);
|
|
681
|
+
return 1;
|
|
682
|
+
}
|
|
683
|
+
log(`已写回 v${targetVersion} 并自检通过:src 模板与项目级副本字节一致。`);
|
|
684
|
+
log(`后续: npm run build → cf agents sync → 跑不变量测试。`);
|
|
685
|
+
return 0;
|
|
686
|
+
}
|
|
687
|
+
function defaultReadGitBlob(ref, path) {
|
|
688
|
+
return execFileSync('git', ['show', `${ref}:${path}`], { encoding: 'utf-8' });
|
|
689
|
+
}
|
|
690
|
+
//# sourceMappingURL=agent.js.map
|