cc-codeconductor 0.5.0 → 1.1.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/README.md +387 -150
- package/dist/cli/errors.d.ts +65 -0
- package/dist/core/compilation/compile-checker.d.ts +53 -0
- package/dist/core/config/codeconductor-config.d.ts +42 -0
- package/dist/core/config/config-loader.d.ts +11 -0
- package/dist/core/filesystem/credential-guard.d.ts +18 -0
- package/dist/core/goal/goal-planner.d.ts +8 -0
- package/dist/core/goal/goal-state.d.ts +15 -0
- package/dist/core/loop/git-stats.d.ts +13 -0
- package/dist/core/loop/loop-engine.d.ts +82 -0
- package/dist/core/memory/episodic-store.d.ts +6 -0
- package/dist/core/memory/operational-state.d.ts +6 -0
- package/dist/core/orchestrator/runtime-orchestrator.d.ts +25 -0
- package/dist/core/planner/product-planner.d.ts +18 -0
- package/dist/core/presets/package-paths.d.ts +4 -0
- package/dist/core/product-graph/graph-store.d.ts +11 -0
- package/dist/core/product-graph/paths.d.ts +18 -0
- package/dist/core/verification/verification-runner.d.ts +57 -0
- package/dist/domain/loop/loop-state.d.ts +74 -0
- package/dist/domain/product/entities.d.ts +11 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +24165 -15800
- package/dist/library.js +2744 -0
- package/dist/utils/result.d.ts +36 -0
- package/dist/validation/schemas.d.ts +4006 -0
- package/package.json +18 -2
- package/policy.yml +12 -11
- package/presets/agy/AGENTS.md +14 -5
- package/presets/agy/gates/pre-commit/GATE.md +137 -0
- package/presets/agy/skills/backlog/SKILL.md +91 -0
- package/presets/agy/skills/cc-fix/SKILL.md +2 -2
- package/presets/agy/skills/cc-tdd-cycle/SKILL.md +11 -0
- package/presets/agy/skills/openspec/SKILL.md +5 -1
- package/presets/agy/skills/security-ai-llm/SKILL.md +43 -0
- package/presets/agy/skills/security-blue-team/SKILL.md +43 -0
- package/presets/agy/skills/security-cloud/SKILL.md +43 -0
- package/presets/agy/skills/security-crypto/SKILL.md +43 -0
- package/presets/agy/skills/security-exploit-dev/SKILL.md +45 -0
- package/presets/agy/skills/security-grc/SKILL.md +43 -0
- package/presets/agy/skills/security-incident-response/SKILL.md +45 -0
- package/presets/agy/skills/security-log-analysis/SKILL.md +43 -0
- package/presets/agy/skills/security-malware-analysis/SKILL.md +44 -0
- package/presets/agy/skills/security-mobile/SKILL.md +43 -0
- package/presets/agy/skills/security-network/SKILL.md +43 -0
- package/presets/agy/skills/security-ot-ics/SKILL.md +43 -0
- package/presets/agy/skills/security-recon/SKILL.md +45 -0
- package/presets/agy/skills/security-red-team/SKILL.md +44 -0
- package/presets/agy/skills/security-reverse-engineering/SKILL.md +44 -0
- package/presets/agy/skills/security-soc-automation/SKILL.md +43 -0
- package/presets/agy/skills/security-threat-hunting/SKILL.md +43 -0
- package/presets/agy/skills/security-vuln-assessment/SKILL.md +45 -0
- package/presets/agy/skills/security-web/SKILL.md +44 -0
- package/presets/agy/workflows/cc-api-contract.md +12 -0
- package/presets/agy/workflows/cc-ask.md +56 -0
- package/presets/agy/workflows/cc-backlog.md +69 -0
- package/presets/agy/workflows/cc-clarify.md +33 -0
- package/presets/agy/workflows/cc-council.md +31 -7
- package/presets/agy/workflows/cc-db-migration.md +22 -9
- package/presets/agy/workflows/cc-explore.md +37 -0
- package/presets/agy/workflows/cc-feature.md +41 -19
- package/presets/agy/workflows/cc-fix.md +50 -23
- package/presets/agy/workflows/cc-handoff.md +42 -0
- package/presets/agy/workflows/cc-iterative.md +128 -0
- package/presets/agy/workflows/cc-openspec.md +16 -1
- package/presets/agy/workflows/cc-pagespeed.md +12 -0
- package/presets/agy/workflows/cc-prototype.md +39 -0
- package/presets/agy/workflows/cc-refactor.md +12 -0
- package/presets/agy/workflows/cc-review.md +12 -0
- package/presets/agy/workflows/cc-scorecard.md +12 -0
- package/presets/agy/workflows/cc-security.md +180 -0
- package/presets/agy/workflows/cc-tdd-cycle.md +24 -0
- package/presets/agy/workflows/cc-test-plan.md +12 -0
- package/presets/agy/workflows/cc-triage.md +35 -0
- package/presets/claude/CLAUDE.md +68 -0
- package/presets/claude/commands/cc/api-contract.md +12 -0
- package/presets/claude/commands/cc/ask.md +56 -0
- package/presets/claude/commands/cc/backlog.md +104 -0
- package/presets/claude/commands/cc/clarify.md +32 -0
- package/presets/claude/commands/cc/council.md +87 -0
- package/presets/claude/commands/cc/db-migration.md +22 -9
- package/presets/claude/commands/cc/explore.md +36 -0
- package/presets/claude/commands/cc/feature.md +49 -22
- package/presets/claude/commands/cc/fix.md +74 -20
- package/presets/claude/commands/cc/handoff.md +44 -0
- package/presets/claude/commands/cc/iterative.md +132 -0
- package/presets/claude/commands/cc/openspec.md +41 -1
- package/presets/claude/commands/cc/pagespeed.md +12 -0
- package/presets/claude/commands/cc/prototype.md +38 -0
- package/presets/claude/commands/cc/refactor.md +152 -1
- package/presets/claude/commands/cc/review.md +78 -16
- package/presets/claude/commands/cc/scorecard.md +12 -0
- package/presets/claude/commands/cc/security.md +179 -0
- package/presets/claude/commands/cc/tdd-cycle.md +53 -3
- package/presets/claude/commands/cc/test-plan.md +12 -0
- package/presets/claude/commands/cc/triage.md +34 -0
- package/presets/claude/gates/pre-commit/GATE.md +137 -0
- package/presets/claude/settings.json +8 -46
- package/presets/claude/skills/backlog/SKILL.md +91 -0
- package/presets/claude/skills/openspec/SKILL.md +5 -1
- package/presets/claude/skills/security/SKILL.md +382 -0
- package/presets/claude/skills/security-ai-llm/SKILL.md +43 -0
- package/presets/claude/skills/security-blue-team/SKILL.md +43 -0
- package/presets/claude/skills/security-cloud/SKILL.md +43 -0
- package/presets/claude/skills/security-crypto/SKILL.md +43 -0
- package/presets/claude/skills/security-exploit-dev/SKILL.md +45 -0
- package/presets/claude/skills/security-grc/SKILL.md +43 -0
- package/presets/claude/skills/security-incident-response/SKILL.md +45 -0
- package/presets/claude/skills/security-log-analysis/SKILL.md +43 -0
- package/presets/claude/skills/security-malware-analysis/SKILL.md +44 -0
- package/presets/claude/skills/security-mobile/SKILL.md +43 -0
- package/presets/claude/skills/security-network/SKILL.md +43 -0
- package/presets/claude/skills/security-ot-ics/SKILL.md +43 -0
- package/presets/claude/skills/security-recon/SKILL.md +45 -0
- package/presets/claude/skills/security-red-team/SKILL.md +44 -0
- package/presets/claude/skills/security-reverse-engineering/SKILL.md +44 -0
- package/presets/claude/skills/security-soc-automation/SKILL.md +43 -0
- package/presets/claude/skills/security-threat-hunting/SKILL.md +43 -0
- package/presets/claude/skills/security-vuln-assessment/SKILL.md +45 -0
- package/presets/claude/skills/security-web/SKILL.md +44 -0
- package/presets/codex/AGENTS.md +6 -6
- package/presets/codex/commands/cc-ask.md +56 -0
- package/presets/codex/gates/pre-commit/GATE.md +137 -0
- package/presets/cursor/AGENTS.md +8 -8
- package/presets/cursor/agents/business-agent.md +44 -0
- package/presets/cursor/agents/continuous-architect.md +37 -0
- package/presets/cursor/agents/docs.md +1 -0
- package/presets/cursor/agents/goal-planner.md +1 -1
- package/presets/cursor/agents/impact-analyst.md +43 -0
- package/presets/cursor/agents/orchestrator.md +6 -6
- package/presets/cursor/commands/cc/api-contract.md +12 -0
- package/presets/cursor/commands/cc/ask.md +56 -0
- package/presets/cursor/commands/cc/backlog.md +105 -0
- package/presets/cursor/commands/cc/clarify.md +32 -0
- package/presets/cursor/commands/cc/council.md +87 -0
- package/presets/cursor/commands/cc/db-migration.md +22 -9
- package/presets/cursor/commands/cc/explore.md +36 -0
- package/presets/cursor/commands/cc/feature.md +41 -19
- package/presets/cursor/commands/cc/fix.md +47 -20
- package/presets/cursor/commands/cc/handoff.md +41 -0
- package/presets/cursor/commands/cc/iterative.md +133 -0
- package/presets/cursor/commands/cc/openspec.md +38 -8
- package/presets/cursor/commands/cc/pagespeed.md +12 -0
- package/presets/cursor/commands/cc/prototype.md +38 -0
- package/presets/cursor/commands/cc/refactor.md +12 -0
- package/presets/cursor/commands/cc/review.md +12 -0
- package/presets/cursor/commands/cc/scorecard.md +12 -0
- package/presets/cursor/commands/cc/security.md +179 -0
- package/presets/cursor/commands/cc/tdd-cycle.md +24 -0
- package/presets/cursor/commands/cc/test-plan.md +12 -0
- package/presets/cursor/commands/cc/triage.md +34 -0
- package/presets/cursor/gates/pre-commit/GATE.md +137 -0
- package/presets/cursor/rules/orchestration.mdc +1 -1
- package/presets/cursor/skills/backlog/SKILL.md +91 -0
- package/presets/cursor/skills/openspec/SKILL.md +5 -1
- package/presets/cursor/skills/security-ai-llm/SKILL.md +43 -0
- package/presets/cursor/skills/security-blue-team/SKILL.md +43 -0
- package/presets/cursor/skills/security-cloud/SKILL.md +43 -0
- package/presets/cursor/skills/security-crypto/SKILL.md +43 -0
- package/presets/cursor/skills/security-exploit-dev/SKILL.md +45 -0
- package/presets/cursor/skills/security-grc/SKILL.md +43 -0
- package/presets/cursor/skills/security-incident-response/SKILL.md +45 -0
- package/presets/cursor/skills/security-log-analysis/SKILL.md +43 -0
- package/presets/cursor/skills/security-malware-analysis/SKILL.md +44 -0
- package/presets/cursor/skills/security-mobile/SKILL.md +43 -0
- package/presets/cursor/skills/security-network/SKILL.md +43 -0
- package/presets/cursor/skills/security-ot-ics/SKILL.md +43 -0
- package/presets/cursor/skills/security-recon/SKILL.md +45 -0
- package/presets/cursor/skills/security-red-team/SKILL.md +44 -0
- package/presets/cursor/skills/security-reverse-engineering/SKILL.md +44 -0
- package/presets/cursor/skills/security-soc-automation/SKILL.md +43 -0
- package/presets/cursor/skills/security-threat-hunting/SKILL.md +43 -0
- package/presets/cursor/skills/security-vuln-assessment/SKILL.md +45 -0
- package/presets/cursor/skills/security-web/SKILL.md +44 -0
- package/presets/opencode/agents/architect.md +22 -1
- package/presets/opencode/agents/complexity-auditor.md +16 -1
- package/presets/opencode/agents/contract-builder.md +17 -1
- package/presets/opencode/agents/devil.md +158 -0
- package/presets/opencode/agents/docs.md +19 -1
- package/presets/opencode/agents/goal-planner.md +32 -2
- package/presets/opencode/agents/implementer.md +32 -2
- package/presets/opencode/agents/orchestrator.md +79 -12
- package/presets/opencode/agents/planner.md +61 -0
- package/presets/opencode/agents/repo-explorer.md +16 -0
- package/presets/opencode/agents/reviewer.md +33 -3
- package/presets/opencode/agents/security-reviewer.md +31 -1
- package/presets/opencode/agents/task-coach.md +69 -1
- package/presets/opencode/agents/tester.md +18 -1
- package/presets/opencode/commands/cc-api-contract.md +12 -0
- package/presets/opencode/commands/cc-ask.md +56 -0
- package/presets/opencode/commands/cc-backlog.md +68 -0
- package/presets/opencode/commands/cc-clarify.md +31 -0
- package/presets/opencode/commands/cc-council.md +87 -0
- package/presets/opencode/commands/cc-db-migration.md +22 -9
- package/presets/opencode/commands/cc-explore.md +35 -0
- package/presets/opencode/commands/cc-feature.md +41 -19
- package/presets/opencode/commands/cc-fix.md +50 -23
- package/presets/opencode/commands/cc-handoff.md +40 -0
- package/presets/opencode/commands/cc-iterative.md +127 -0
- package/presets/opencode/commands/cc-openspec.md +16 -1
- package/presets/opencode/commands/cc-pagespeed.md +12 -0
- package/presets/opencode/commands/cc-prototype.md +37 -0
- package/presets/opencode/commands/cc-refactor.md +12 -0
- package/presets/opencode/commands/cc-review.md +12 -0
- package/presets/opencode/commands/cc-scorecard.md +12 -0
- package/presets/opencode/commands/cc-security.md +179 -0
- package/presets/opencode/commands/cc-tdd-cycle.md +24 -0
- package/presets/opencode/commands/cc-test-plan.md +12 -0
- package/presets/opencode/commands/cc-triage.md +33 -0
- package/presets/opencode/gates/pre-commit/GATE.md +137 -0
- package/presets/opencode/prompts/v0.1.0/DEPRECATED.md +11 -0
- package/presets/opencode/prompts/v0.2.0/DEPRECATED.md +11 -0
- package/presets/opencode/prompts/v0.3.0/DEPRECATED.md +11 -0
- package/presets/opencode/prompts/v0.4.0/DEPRECATED.md +11 -0
- package/presets/opencode/prompts/v0.5.0/goal-planner.md +1 -1
- package/presets/opencode/prompts/v0.5.0/orchestrator.md +6 -6
- package/presets/opencode/prompts/v0.6.0/implementer.md +35 -0
- package/presets/opencode/prompts/v0.6.0/planner.md +36 -0
- package/presets/opencode/prompts/v0.6.0/reviewer.md +40 -0
- package/presets/opencode/prompts/v1.0.0/README.md +47 -0
- package/presets/opencode/prompts/v1.0.0/architect.md +259 -0
- package/presets/opencode/prompts/v1.0.0/complexity-auditor.md +116 -0
- package/presets/opencode/prompts/v1.0.0/contract-builder.md +120 -0
- package/presets/opencode/prompts/v1.0.0/devil.md +169 -0
- package/presets/opencode/prompts/v1.0.0/docs.md +229 -0
- package/presets/opencode/prompts/v1.0.0/goal-planner.md +123 -0
- package/presets/opencode/prompts/v1.0.0/implementer.md +228 -0
- package/presets/opencode/prompts/v1.0.0/orchestrator.md +474 -0
- package/presets/opencode/prompts/v1.0.0/planner.md +72 -0
- package/presets/opencode/prompts/v1.0.0/repo-explorer.md +147 -0
- package/presets/opencode/prompts/v1.0.0/reviewer.md +295 -0
- package/presets/opencode/prompts/v1.0.0/security-reviewer.md +170 -0
- package/presets/opencode/prompts/v1.0.0/task-coach.md +235 -0
- package/presets/opencode/prompts/v1.0.0/tester.md +298 -0
- package/presets/opencode/skills/backlog/SKILL.md +91 -0
- package/presets/opencode/skills/openspec/SKILL.md +5 -1
- package/presets/opencode/skills/security-ai-llm/SKILL.md +43 -0
- package/presets/opencode/skills/security-blue-team/SKILL.md +43 -0
- package/presets/opencode/skills/security-cloud/SKILL.md +43 -0
- package/presets/opencode/skills/security-crypto/SKILL.md +43 -0
- package/presets/opencode/skills/security-exploit-dev/SKILL.md +45 -0
- package/presets/opencode/skills/security-grc/SKILL.md +43 -0
- package/presets/opencode/skills/security-incident-response/SKILL.md +45 -0
- package/presets/opencode/skills/security-log-analysis/SKILL.md +43 -0
- package/presets/opencode/skills/security-malware-analysis/SKILL.md +44 -0
- package/presets/opencode/skills/security-mobile/SKILL.md +43 -0
- package/presets/opencode/skills/security-network/SKILL.md +43 -0
- package/presets/opencode/skills/security-ot-ics/SKILL.md +43 -0
- package/presets/opencode/skills/security-recon/SKILL.md +45 -0
- package/presets/opencode/skills/security-red-team/SKILL.md +44 -0
- package/presets/opencode/skills/security-reverse-engineering/SKILL.md +44 -0
- package/presets/opencode/skills/security-soc-automation/SKILL.md +43 -0
- package/presets/opencode/skills/security-threat-hunting/SKILL.md +43 -0
- package/presets/opencode/skills/security-vuln-assessment/SKILL.md +45 -0
- package/presets/opencode/skills/security-web/SKILL.md +44 -0
- package/presets/seo-hotel/settings.json +0 -17
- package/src/presets/council/council.yml +12 -0
- package/src/presets/manifests/agy.yml +2 -2
- package/src/presets/manifests/claude.yml +2 -2
- package/src/presets/manifests/codex.yml +2 -2
- package/src/presets/manifests/cursor.yml +2 -2
- package/src/presets/manifests/gemini.yml +2 -2
- package/src/presets/manifests/opencode.yml +2 -2
- package/src/presets/models/agy.yml +93 -66
- package/src/presets/models/claude.yml +79 -53
- package/src/presets/models/codex.yml +79 -54
- package/src/presets/models/cursor.yml +72 -58
- package/src/presets/models/gemini.yml +79 -53
- package/src/presets/models/opencode.yml +72 -46
package/dist/library.js
ADDED
|
@@ -0,0 +1,2744 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __export = (target, all) => {
|
|
3
|
+
for (var name in all)
|
|
4
|
+
__defProp(target, name, {
|
|
5
|
+
get: all[name],
|
|
6
|
+
enumerable: true,
|
|
7
|
+
configurable: true,
|
|
8
|
+
set: (newValue) => all[name] = () => newValue
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
12
|
+
|
|
13
|
+
// src/validation/schemas.ts
|
|
14
|
+
import { z } from "zod";
|
|
15
|
+
function validateCouncilSpec(data) {
|
|
16
|
+
return CouncilSpecSchema.parse(data);
|
|
17
|
+
}
|
|
18
|
+
function validateProjectProfile(data) {
|
|
19
|
+
return ProjectProfileSchema.parse(data);
|
|
20
|
+
}
|
|
21
|
+
function validateConfig(data) {
|
|
22
|
+
return CodeConductorConfigSchema.parse(data);
|
|
23
|
+
}
|
|
24
|
+
function validateRunnerTarget(data) {
|
|
25
|
+
return RunnerTargetSchema.parse(data);
|
|
26
|
+
}
|
|
27
|
+
function validateModelConfig(data) {
|
|
28
|
+
return ModelConfigSchema.parse(data);
|
|
29
|
+
}
|
|
30
|
+
function validateAgentContract(data) {
|
|
31
|
+
return AgentContractSchema.parse(data);
|
|
32
|
+
}
|
|
33
|
+
function validateCouncilVerdictInput(data) {
|
|
34
|
+
return CouncilVerdictInputSchema.parse(data);
|
|
35
|
+
}
|
|
36
|
+
function validateConsensusConfig(data) {
|
|
37
|
+
return ConsensusConfigSchema.parse(data);
|
|
38
|
+
}
|
|
39
|
+
function validateCouncilVerdict(data) {
|
|
40
|
+
return CouncilVerdictSchema.parse(data);
|
|
41
|
+
}
|
|
42
|
+
function validateClaudeAgentFile(data) {
|
|
43
|
+
return ClaudeAgentFileSchema.parse(data);
|
|
44
|
+
}
|
|
45
|
+
function validateOpenCodeAgentFile(data) {
|
|
46
|
+
return OpenCodeAgentFileSchema.parse(data);
|
|
47
|
+
}
|
|
48
|
+
function validateGoalGraph(data) {
|
|
49
|
+
return GoalGraphSchema.parse(data);
|
|
50
|
+
}
|
|
51
|
+
function validateMemoryPointer(data) {
|
|
52
|
+
return MemoryPointerSchema.parse(data);
|
|
53
|
+
}
|
|
54
|
+
function validateMemoryIndex(data) {
|
|
55
|
+
return MemoryIndexSchema.parse(data);
|
|
56
|
+
}
|
|
57
|
+
function validateBacklogDocument(data) {
|
|
58
|
+
return BacklogDocumentSchema.parse(data);
|
|
59
|
+
}
|
|
60
|
+
function validateOpenspecState(data) {
|
|
61
|
+
return OpenspecStateSchema.parse(data);
|
|
62
|
+
}
|
|
63
|
+
function validateScorecardRecord(data) {
|
|
64
|
+
return ScorecardRecordSchema.parse(data);
|
|
65
|
+
}
|
|
66
|
+
function validateTaskOutcome(data) {
|
|
67
|
+
return TaskOutcomeSchema.parse(data);
|
|
68
|
+
}
|
|
69
|
+
function validateHarnessCatalog(data) {
|
|
70
|
+
return HarnessCatalogSchema.parse(data);
|
|
71
|
+
}
|
|
72
|
+
function validateHarnessOverlay(data) {
|
|
73
|
+
return HarnessOverlaySchema.parse(data);
|
|
74
|
+
}
|
|
75
|
+
function validateHarnessExperiment(data) {
|
|
76
|
+
return HarnessExperimentSchema.parse(data);
|
|
77
|
+
}
|
|
78
|
+
function validateHarnessSuite(data) {
|
|
79
|
+
return HarnessSuiteSchema.parse(data);
|
|
80
|
+
}
|
|
81
|
+
function validateCommandEnvelope(data) {
|
|
82
|
+
return CommandEnvelopeSchema.parse(data);
|
|
83
|
+
}
|
|
84
|
+
function validateWorkflowProfile(data) {
|
|
85
|
+
return WorkflowProfileSchema.parse(data);
|
|
86
|
+
}
|
|
87
|
+
function validateExecutionContext(data) {
|
|
88
|
+
return ExecutionContextSchema.parse(data);
|
|
89
|
+
}
|
|
90
|
+
function validatePlannerOutput(data) {
|
|
91
|
+
return PlannerOutputSchema.parse(data);
|
|
92
|
+
}
|
|
93
|
+
function validateAgentOutput(data) {
|
|
94
|
+
return AgentOutputSchema.parse(data);
|
|
95
|
+
}
|
|
96
|
+
function validateImplementerOutput(data) {
|
|
97
|
+
return ImplementerOutputSchema.parse(data);
|
|
98
|
+
}
|
|
99
|
+
function validateReviewerOutput(data) {
|
|
100
|
+
return ReviewerOutputSchema.parse(data);
|
|
101
|
+
}
|
|
102
|
+
function validateProductGraph(data) {
|
|
103
|
+
return ProductGraphSchema.parse(data);
|
|
104
|
+
}
|
|
105
|
+
function validateKnowledgeEntity(data) {
|
|
106
|
+
return KnowledgeEntitySchema.parse(data);
|
|
107
|
+
}
|
|
108
|
+
function validateDecision(data) {
|
|
109
|
+
return DecisionSchema.parse(data);
|
|
110
|
+
}
|
|
111
|
+
function validateEvidence(data) {
|
|
112
|
+
return EvidenceSchema.parse(data);
|
|
113
|
+
}
|
|
114
|
+
function validateCanonicalTaskCard(data) {
|
|
115
|
+
return CanonicalTaskCardSchema.parse(data);
|
|
116
|
+
}
|
|
117
|
+
function validateProductEvent(data) {
|
|
118
|
+
return ProductEventSchema.parse(data);
|
|
119
|
+
}
|
|
120
|
+
var CouncilAgentSpecSchema, CouncilSpecSchema, ProjectProfileSchema, CompileCheckConfigSchema, LoopConfigSchema, CodeConductorConfigSchema, RunnerTargetSchema, InstallStrategySchema, ManifestEntrySchema, InstallManifestSchema, ToolProviderNamesSchema, PermissionProviderNamesSchema, ModelConfigSchema, ContractTargetSchema, ContractFormatSchema, AgentContractSchema, CouncilFindingSchema, CouncilVerdictInputSchema, ConsensusConfigSchema, CouncilVerdictSchema, ClaudeAgentFileSchema, OpenCodeAgentFileSchema, SentryStackFrameSchema, SentryWebhookSchema, MemoryPointerSchema, MemoryIndexSchema, GoalTaskSchema, GoalGraphSchema, ConfidenceLevelSchema, ProductNodeTypeSchema, GraphRelationSchema, KnowledgeEntitySchema, DecisionSchema, EvidenceSchema, CanonicalTaskCardStatusSchema, CanonicalTaskCardSchema, ProductGraphNodeSchema, ProductGraphEdgeSchema, ProductGraphSchema, ProductMetaSchema, ProductEventTypeSchema, ProductEventSchema, OperationalStateSchema, StrategicMemorySchema, ImpactReportSchema, BusinessReviewOutputSchema, VerificationReportSchema, BacklogStatusSchema, BacklogTypeSchema, BacklogPrioritySchema, BacklogGlobalSchema, BacklogItemSchema, BacklogDocumentSchema, OpenspecTaskCardPhaseSchema, OpenspecTaskCardStatusSchema, OpenspecTaskCardSchema, OpenspecStateSchema, WorkflowCommandSchema, CcepOutputFormatSchema, CommandEnvelopeSchema, WorkflowPhaseSchema, WorkflowRiskRuleSchema, WorkflowProfileSchema, ExecutionContextSchema, PlannerOutputSchema, AgentArtifactSchema, AgentOutputSchema, ImplementerTestsSchema, ImplementerOutputSchema, ReviewAxisSchema, ReviewFindingSchema, ReviewerOutputSchema, TechnicalPlanOutputSchema, ScorecardVerdictSchema, ScorecardCriterionIdSchema, ScorecardCriterionSchema, ScorecardRecordSchema, TaskOutcomeSourceSchema, TaskOutcomeStatusSchema, TaskOutcomeSchema, HarnessComponentIdSchema, HarnessComponentLayerSchema, HarnessToggleKindSchema, HarnessCatalogEntrySchema, HarnessCatalogSchema, HarnessOverlaySchema, HarnessExperimentSchema, HarnessSuiteTaskSchema, HarnessSuiteSchema, EvaluationIndexSchema, ExecutionProfileNameSchema, ExecutionProfileSchema;
|
|
121
|
+
var init_schemas = __esm(() => {
|
|
122
|
+
CouncilAgentSpecSchema = z.object({
|
|
123
|
+
id: z.string(),
|
|
124
|
+
role: z.string(),
|
|
125
|
+
context: z.enum(["repo-readonly", "prompt-only"]),
|
|
126
|
+
modelHint: z.enum([
|
|
127
|
+
"strong-reasoning",
|
|
128
|
+
"security-reasoning",
|
|
129
|
+
"balanced",
|
|
130
|
+
"practical-coding",
|
|
131
|
+
"analytical",
|
|
132
|
+
"adversarial"
|
|
133
|
+
]),
|
|
134
|
+
focus: z.array(z.string())
|
|
135
|
+
});
|
|
136
|
+
CouncilSpecSchema = z.object({
|
|
137
|
+
name: z.string(),
|
|
138
|
+
version: z.string(),
|
|
139
|
+
description: z.string(),
|
|
140
|
+
outputContract: z.string(),
|
|
141
|
+
agents: z.array(CouncilAgentSpecSchema).min(1).refine((agents) => new Set(agents.map((a) => a.id.trim().toLowerCase())).size === agents.length, { message: "council agent ids must be unique" })
|
|
142
|
+
});
|
|
143
|
+
ProjectProfileSchema = z.object({
|
|
144
|
+
rootDir: z.string(),
|
|
145
|
+
languages: z.array(z.string()),
|
|
146
|
+
runtimes: z.array(z.string()),
|
|
147
|
+
packageManagers: z.array(z.string()),
|
|
148
|
+
frameworks: z.array(z.string()),
|
|
149
|
+
signals: z.array(z.string()),
|
|
150
|
+
confidence: z.enum(["low", "medium", "high"])
|
|
151
|
+
});
|
|
152
|
+
CompileCheckConfigSchema = z.object({
|
|
153
|
+
enabled: z.boolean(),
|
|
154
|
+
command: z.string().optional(),
|
|
155
|
+
timeoutMs: z.number().positive().optional()
|
|
156
|
+
});
|
|
157
|
+
LoopConfigSchema = z.object({
|
|
158
|
+
enabled: z.boolean().optional().default(true),
|
|
159
|
+
maxIterations: z.number().int().positive().optional().default(3),
|
|
160
|
+
maxTokenBudget: z.number().nonnegative().optional().default(0),
|
|
161
|
+
compaction: z.object({
|
|
162
|
+
enabled: z.boolean().optional().default(true),
|
|
163
|
+
historyFile: z.string().optional()
|
|
164
|
+
}).optional()
|
|
165
|
+
});
|
|
166
|
+
CodeConductorConfigSchema = z.object({
|
|
167
|
+
version: z.string(),
|
|
168
|
+
project: z.object({
|
|
169
|
+
name: z.string(),
|
|
170
|
+
profile: z.string().optional()
|
|
171
|
+
}),
|
|
172
|
+
defaults: z.object({
|
|
173
|
+
target: z.enum(["opencode", "claude", "codex", "gemini", "cursor", "agy"]),
|
|
174
|
+
overwrite: z.boolean(),
|
|
175
|
+
locale: z.enum(["en", "es"]).optional().default("en")
|
|
176
|
+
}),
|
|
177
|
+
presets: z.object({
|
|
178
|
+
council: z.object({
|
|
179
|
+
enabled: z.boolean(),
|
|
180
|
+
version: z.string()
|
|
181
|
+
})
|
|
182
|
+
}),
|
|
183
|
+
safety: z.object({
|
|
184
|
+
destructiveCommands: z.array(z.string()),
|
|
185
|
+
secretPatterns: z.array(z.string()),
|
|
186
|
+
compileCheck: CompileCheckConfigSchema.optional()
|
|
187
|
+
}),
|
|
188
|
+
loop: LoopConfigSchema.optional()
|
|
189
|
+
});
|
|
190
|
+
RunnerTargetSchema = z.enum([
|
|
191
|
+
"opencode",
|
|
192
|
+
"claude",
|
|
193
|
+
"codex",
|
|
194
|
+
"gemini",
|
|
195
|
+
"cursor",
|
|
196
|
+
"agy",
|
|
197
|
+
"all"
|
|
198
|
+
]);
|
|
199
|
+
InstallStrategySchema = z.enum([
|
|
200
|
+
"overwrite",
|
|
201
|
+
"append",
|
|
202
|
+
"merge-json",
|
|
203
|
+
"merge-managed",
|
|
204
|
+
"skip"
|
|
205
|
+
]);
|
|
206
|
+
ManifestEntrySchema = z.object({
|
|
207
|
+
src: z.string(),
|
|
208
|
+
dest: z.string(),
|
|
209
|
+
strategy: InstallStrategySchema,
|
|
210
|
+
globalStrategy: InstallStrategySchema.optional(),
|
|
211
|
+
template: z.boolean().optional()
|
|
212
|
+
});
|
|
213
|
+
InstallManifestSchema = z.object({
|
|
214
|
+
target: z.enum(["opencode", "claude", "codex", "gemini", "cursor", "agy"]),
|
|
215
|
+
entries: z.array(ManifestEntrySchema)
|
|
216
|
+
});
|
|
217
|
+
ToolProviderNamesSchema = z.record(z.string(), z.string());
|
|
218
|
+
PermissionProviderNamesSchema = z.record(z.string(), z.string());
|
|
219
|
+
ModelConfigSchema = z.object({
|
|
220
|
+
target: z.enum(["opencode", "claude", "codex", "gemini", "cursor", "agy"]),
|
|
221
|
+
agents: z.record(z.string(), z.object({
|
|
222
|
+
claude: z.string().optional(),
|
|
223
|
+
opencode: z.string().optional(),
|
|
224
|
+
codex: z.string().optional(),
|
|
225
|
+
gemini: z.string().optional(),
|
|
226
|
+
cursor: z.string().optional(),
|
|
227
|
+
agy: z.string().optional(),
|
|
228
|
+
grok: z.string().optional()
|
|
229
|
+
})),
|
|
230
|
+
tools: z.record(z.string(), ToolProviderNamesSchema).optional(),
|
|
231
|
+
permissions: PermissionProviderNamesSchema.optional()
|
|
232
|
+
});
|
|
233
|
+
ContractTargetSchema = z.enum([
|
|
234
|
+
"claude",
|
|
235
|
+
"opencode",
|
|
236
|
+
"codex",
|
|
237
|
+
"gemini",
|
|
238
|
+
"cursor",
|
|
239
|
+
"agy"
|
|
240
|
+
]);
|
|
241
|
+
ContractFormatSchema = z.object({
|
|
242
|
+
target: ContractTargetSchema,
|
|
243
|
+
options: z.record(z.unknown()).optional()
|
|
244
|
+
});
|
|
245
|
+
AgentContractSchema = z.object({
|
|
246
|
+
council: CouncilSpecSchema,
|
|
247
|
+
targets: z.array(ContractFormatSchema),
|
|
248
|
+
contractVersion: z.string(),
|
|
249
|
+
renderHints: z.record(ContractTargetSchema, z.record(z.unknown())).optional()
|
|
250
|
+
});
|
|
251
|
+
CouncilFindingSchema = z.object({
|
|
252
|
+
category: z.string(),
|
|
253
|
+
severity: z.enum(["info", "warning", "critical"]),
|
|
254
|
+
message: z.string(),
|
|
255
|
+
agentId: z.string()
|
|
256
|
+
});
|
|
257
|
+
CouncilVerdictInputSchema = z.object({
|
|
258
|
+
agentId: z.string().min(1).refine((id) => id.trim().length > 0),
|
|
259
|
+
agentRole: z.string(),
|
|
260
|
+
status: z.enum(["APPROVED", "REJECTED", "ABSTAIN"]),
|
|
261
|
+
securityVeto: z.boolean(),
|
|
262
|
+
complianceVeto: z.boolean().optional(),
|
|
263
|
+
confidence: z.number().min(0).max(1),
|
|
264
|
+
findings: z.array(CouncilFindingSchema),
|
|
265
|
+
summary: z.string()
|
|
266
|
+
});
|
|
267
|
+
ConsensusConfigSchema = z.object({
|
|
268
|
+
algorithm: z.enum(["majority", "unanimous"]),
|
|
269
|
+
allowSecurityVeto: z.boolean(),
|
|
270
|
+
allowComplianceVeto: z.boolean().optional(),
|
|
271
|
+
expectedAgentIds: z.array(z.string().min(1).refine((id) => id.trim().length > 0)).min(1).refine((ids) => new Set(ids.map((id) => id.trim().toLowerCase())).size === ids.length).optional(),
|
|
272
|
+
quorum: z.number().int().positive().optional(),
|
|
273
|
+
criticalFindingsPolicy: z.enum(["escalate", "reject", "ignore"]).optional()
|
|
274
|
+
}).refine((config) => config.algorithm !== "unanimous" || config.expectedAgentIds !== undefined, {
|
|
275
|
+
message: "unanimous consensus requires a non-empty expectedAgentIds roster",
|
|
276
|
+
path: ["expectedAgentIds"]
|
|
277
|
+
}).refine((config) => !config.allowSecurityVeto || config.expectedAgentIds === undefined || config.expectedAgentIds.some((id) => id.toLowerCase().includes("security")), {
|
|
278
|
+
message: "allowSecurityVeto requires at least one security agent in expectedAgentIds",
|
|
279
|
+
path: ["expectedAgentIds"]
|
|
280
|
+
});
|
|
281
|
+
CouncilVerdictSchema = z.object({
|
|
282
|
+
status: z.enum(["APPROVED", "REJECTED", "ESCALATED"]),
|
|
283
|
+
totalAgents: z.number(),
|
|
284
|
+
approvedCount: z.number(),
|
|
285
|
+
rejectedCount: z.number(),
|
|
286
|
+
abstainedCount: z.number(),
|
|
287
|
+
vetoApplied: z.boolean(),
|
|
288
|
+
complianceVetoApplied: z.boolean().optional(),
|
|
289
|
+
vetoByAgentId: z.string().optional(),
|
|
290
|
+
averageConfidence: z.number().min(0).max(1).optional(),
|
|
291
|
+
findings: z.array(CouncilFindingSchema),
|
|
292
|
+
summary: z.string(),
|
|
293
|
+
individualVerdicts: z.array(CouncilVerdictInputSchema)
|
|
294
|
+
});
|
|
295
|
+
ClaudeAgentFileSchema = z.object({
|
|
296
|
+
path: z.string().startsWith(".claude/"),
|
|
297
|
+
content: z.string(),
|
|
298
|
+
overwrite: z.boolean()
|
|
299
|
+
});
|
|
300
|
+
OpenCodeAgentFileSchema = z.object({
|
|
301
|
+
path: z.string().startsWith(".opencode/"),
|
|
302
|
+
content: z.string(),
|
|
303
|
+
overwrite: z.boolean()
|
|
304
|
+
});
|
|
305
|
+
SentryStackFrameSchema = z.object({
|
|
306
|
+
filename: z.string(),
|
|
307
|
+
function: z.string(),
|
|
308
|
+
lineNo: z.number(),
|
|
309
|
+
colNo: z.number().optional(),
|
|
310
|
+
context: z.array(z.string())
|
|
311
|
+
});
|
|
312
|
+
SentryWebhookSchema = z.object({
|
|
313
|
+
issueId: z.string(),
|
|
314
|
+
title: z.string(),
|
|
315
|
+
culprit: z.string(),
|
|
316
|
+
filename: z.string().optional(),
|
|
317
|
+
stackTrace: z.array(SentryStackFrameSchema),
|
|
318
|
+
environment: z.string().optional(),
|
|
319
|
+
release: z.string().optional()
|
|
320
|
+
});
|
|
321
|
+
MemoryPointerSchema = z.object({
|
|
322
|
+
topic_key: z.string().min(1).max(128),
|
|
323
|
+
id: z.number().int().positive(),
|
|
324
|
+
file: z.string().min(1),
|
|
325
|
+
summary: z.string().min(1).max(200),
|
|
326
|
+
timestamp: z.string().datetime(),
|
|
327
|
+
tags: z.array(z.string().max(64)).max(10).optional().default([])
|
|
328
|
+
});
|
|
329
|
+
MemoryIndexSchema = z.object({
|
|
330
|
+
version: z.literal(1),
|
|
331
|
+
pointers: z.array(MemoryPointerSchema)
|
|
332
|
+
});
|
|
333
|
+
GoalTaskSchema = z.object({
|
|
334
|
+
id: z.string(),
|
|
335
|
+
title: z.string(),
|
|
336
|
+
type: z.enum(["feature", "fix", "refactor", "test", "docs"]),
|
|
337
|
+
risk: z.enum(["low", "medium", "high"]),
|
|
338
|
+
status: z.enum(["pending", "in-progress", "done", "blocked"]),
|
|
339
|
+
depends_on: z.array(z.string()).optional().default([]),
|
|
340
|
+
acceptance_criteria: z.array(z.string()),
|
|
341
|
+
blocked_reason: z.string().optional(),
|
|
342
|
+
context_scope: z.enum(["isolated", "continuation", "full"]).optional().default("isolated")
|
|
343
|
+
});
|
|
344
|
+
GoalGraphSchema = z.object({
|
|
345
|
+
objective: z.string(),
|
|
346
|
+
tasks: z.array(GoalTaskSchema),
|
|
347
|
+
created_at: z.string()
|
|
348
|
+
});
|
|
349
|
+
ConfidenceLevelSchema = z.enum(["low", "medium", "high"]);
|
|
350
|
+
ProductNodeTypeSchema = z.enum([
|
|
351
|
+
"product",
|
|
352
|
+
"domain",
|
|
353
|
+
"capability",
|
|
354
|
+
"requirement",
|
|
355
|
+
"decision",
|
|
356
|
+
"component",
|
|
357
|
+
"flow",
|
|
358
|
+
"contract",
|
|
359
|
+
"metric",
|
|
360
|
+
"risk",
|
|
361
|
+
"task",
|
|
362
|
+
"evidence"
|
|
363
|
+
]);
|
|
364
|
+
GraphRelationSchema = z.enum([
|
|
365
|
+
"implements",
|
|
366
|
+
"depends_on",
|
|
367
|
+
"documents",
|
|
368
|
+
"affects",
|
|
369
|
+
"evidences",
|
|
370
|
+
"blocks",
|
|
371
|
+
"contains"
|
|
372
|
+
]);
|
|
373
|
+
KnowledgeEntitySchema = z.object({
|
|
374
|
+
type: ProductNodeTypeSchema,
|
|
375
|
+
id: z.string(),
|
|
376
|
+
name: z.string(),
|
|
377
|
+
source: z.string(),
|
|
378
|
+
version: z.string().optional(),
|
|
379
|
+
confidence: ConfidenceLevelSchema,
|
|
380
|
+
relations: z.array(z.object({
|
|
381
|
+
targetId: z.string(),
|
|
382
|
+
relation: GraphRelationSchema
|
|
383
|
+
})).default([]),
|
|
384
|
+
data: z.record(z.string(), z.unknown()).optional().default({})
|
|
385
|
+
});
|
|
386
|
+
DecisionSchema = z.object({
|
|
387
|
+
id: z.string(),
|
|
388
|
+
context: z.string(),
|
|
389
|
+
alternatives: z.array(z.string()).default([]),
|
|
390
|
+
chosenOption: z.string(),
|
|
391
|
+
rationale: z.string(),
|
|
392
|
+
consequences: z.array(z.string()).default([]),
|
|
393
|
+
date: z.string(),
|
|
394
|
+
linkedTasks: z.array(z.string()).default([]),
|
|
395
|
+
linkedComponents: z.array(z.string()).default([]),
|
|
396
|
+
source: z.string().optional()
|
|
397
|
+
});
|
|
398
|
+
EvidenceSchema = z.object({
|
|
399
|
+
id: z.string(),
|
|
400
|
+
source: z.string(),
|
|
401
|
+
type: z.string(),
|
|
402
|
+
timestamp: z.string(),
|
|
403
|
+
relatedTask: z.string().optional(),
|
|
404
|
+
relatedDecision: z.string().optional(),
|
|
405
|
+
confidence: z.number().min(0).max(1),
|
|
406
|
+
checksum: z.string().optional(),
|
|
407
|
+
summary: z.string().optional(),
|
|
408
|
+
data: z.record(z.string(), z.unknown()).optional()
|
|
409
|
+
});
|
|
410
|
+
CanonicalTaskCardStatusSchema = z.enum([
|
|
411
|
+
"draft",
|
|
412
|
+
"ready",
|
|
413
|
+
"in-progress",
|
|
414
|
+
"review",
|
|
415
|
+
"done",
|
|
416
|
+
"blocked"
|
|
417
|
+
]);
|
|
418
|
+
CanonicalTaskCardSchema = z.object({
|
|
419
|
+
id: z.string(),
|
|
420
|
+
title: z.string(),
|
|
421
|
+
objective: z.string(),
|
|
422
|
+
context: z.string(),
|
|
423
|
+
acceptanceCriteria: z.array(z.string()),
|
|
424
|
+
dependencies: z.array(z.string()).default([]),
|
|
425
|
+
constraints: z.array(z.string()).default([]),
|
|
426
|
+
risk: z.enum(["low", "medium", "high"]),
|
|
427
|
+
targetFiles: z.array(z.string()).default([]),
|
|
428
|
+
agentType: z.string(),
|
|
429
|
+
evidenceRequired: z.array(z.string()).default([]),
|
|
430
|
+
status: CanonicalTaskCardStatusSchema,
|
|
431
|
+
type: z.enum(["feature", "fix", "refactor", "review", "docs", "test"]),
|
|
432
|
+
linkedCapabilities: z.array(z.string()).default([]),
|
|
433
|
+
boundaries: z.array(z.string()).default([]),
|
|
434
|
+
requiresHumanReview: z.boolean().optional(),
|
|
435
|
+
requiresTests: z.boolean().optional(),
|
|
436
|
+
contextScope: z.enum(["isolated", "continuation", "full"]).optional(),
|
|
437
|
+
actualBehavior: z.string().optional(),
|
|
438
|
+
expectedBehavior: z.string().optional(),
|
|
439
|
+
reproductionSteps: z.array(z.string()).optional(),
|
|
440
|
+
domain: z.string().optional(),
|
|
441
|
+
authorization: z.string().optional()
|
|
442
|
+
});
|
|
443
|
+
ProductGraphNodeSchema = z.object({
|
|
444
|
+
id: z.string(),
|
|
445
|
+
type: ProductNodeTypeSchema,
|
|
446
|
+
name: z.string(),
|
|
447
|
+
data: z.record(z.string(), z.unknown()).default({}),
|
|
448
|
+
source: z.string().optional(),
|
|
449
|
+
confidence: ConfidenceLevelSchema.optional(),
|
|
450
|
+
version: z.string().optional()
|
|
451
|
+
});
|
|
452
|
+
ProductGraphEdgeSchema = z.object({
|
|
453
|
+
from: z.string(),
|
|
454
|
+
to: z.string(),
|
|
455
|
+
relation: GraphRelationSchema
|
|
456
|
+
});
|
|
457
|
+
ProductGraphSchema = z.object({
|
|
458
|
+
version: z.literal(1),
|
|
459
|
+
productId: z.string(),
|
|
460
|
+
productName: z.string(),
|
|
461
|
+
nodes: z.array(ProductGraphNodeSchema),
|
|
462
|
+
edges: z.array(ProductGraphEdgeSchema),
|
|
463
|
+
updatedAt: z.string()
|
|
464
|
+
});
|
|
465
|
+
ProductMetaSchema = z.object({
|
|
466
|
+
version: z.literal(1),
|
|
467
|
+
graphVersion: z.string(),
|
|
468
|
+
lastIngestAt: z.string().optional(),
|
|
469
|
+
sourceHashes: z.record(z.string(), z.string()).default({})
|
|
470
|
+
});
|
|
471
|
+
ProductEventTypeSchema = z.enum([
|
|
472
|
+
"task.started",
|
|
473
|
+
"task.completed",
|
|
474
|
+
"decision.recorded",
|
|
475
|
+
"evidence.added",
|
|
476
|
+
"ingest.completed",
|
|
477
|
+
"goal.updated",
|
|
478
|
+
"blocker.detected",
|
|
479
|
+
"verification.completed",
|
|
480
|
+
"feedback.processed"
|
|
481
|
+
]);
|
|
482
|
+
ProductEventSchema = z.object({
|
|
483
|
+
id: z.string(),
|
|
484
|
+
type: ProductEventTypeSchema,
|
|
485
|
+
timestamp: z.string(),
|
|
486
|
+
payload: z.record(z.string(), z.unknown()).default({})
|
|
487
|
+
});
|
|
488
|
+
OperationalStateSchema = z.object({
|
|
489
|
+
version: z.literal(1),
|
|
490
|
+
activeAgents: z.array(z.string()).default([]),
|
|
491
|
+
activeTaskIds: z.array(z.string()).default([]),
|
|
492
|
+
blockers: z.array(z.object({
|
|
493
|
+
taskId: z.string(),
|
|
494
|
+
reason: z.string(),
|
|
495
|
+
since: z.string()
|
|
496
|
+
})).default([]),
|
|
497
|
+
sprintFocus: z.string().optional(),
|
|
498
|
+
updatedAt: z.string()
|
|
499
|
+
});
|
|
500
|
+
StrategicMemorySchema = z.object({
|
|
501
|
+
version: z.literal(1),
|
|
502
|
+
kpis: z.array(z.object({
|
|
503
|
+
name: z.string(),
|
|
504
|
+
target: z.string(),
|
|
505
|
+
current: z.string().optional()
|
|
506
|
+
})).default([]),
|
|
507
|
+
quarterlyFocus: z.string().optional(),
|
|
508
|
+
tradeoffs: z.array(z.string()).default([]),
|
|
509
|
+
updatedAt: z.string()
|
|
510
|
+
});
|
|
511
|
+
ImpactReportSchema = z.object({
|
|
512
|
+
target: z.string(),
|
|
513
|
+
brokenEndpoints: z.array(z.string()).default([]),
|
|
514
|
+
brokenContracts: z.array(z.string()).default([]),
|
|
515
|
+
affectedTests: z.array(z.string()).default([]),
|
|
516
|
+
affectedFlows: z.array(z.string()).default([]),
|
|
517
|
+
affectedComponents: z.array(z.string()).default([]),
|
|
518
|
+
summary: z.string()
|
|
519
|
+
});
|
|
520
|
+
BusinessReviewOutputSchema = z.object({
|
|
521
|
+
status: z.enum(["proceed", "defer", "reject"]),
|
|
522
|
+
roiEstimate: z.string().optional(),
|
|
523
|
+
userImpact: z.string().optional(),
|
|
524
|
+
eliminationRisk: z.string().optional(),
|
|
525
|
+
questions: z.array(z.string()).default([]),
|
|
526
|
+
confidence: z.number().min(0).max(1)
|
|
527
|
+
});
|
|
528
|
+
VerificationReportSchema = z.object({
|
|
529
|
+
taskId: z.string(),
|
|
530
|
+
passed: z.boolean(),
|
|
531
|
+
checks: z.array(z.object({
|
|
532
|
+
name: z.string(),
|
|
533
|
+
passed: z.boolean(),
|
|
534
|
+
message: z.string()
|
|
535
|
+
})),
|
|
536
|
+
evidenceIds: z.array(z.string()).default([]),
|
|
537
|
+
confidence: z.number().min(0).max(1)
|
|
538
|
+
});
|
|
539
|
+
BacklogStatusSchema = z.enum([
|
|
540
|
+
"TODO",
|
|
541
|
+
"READY",
|
|
542
|
+
"PLANNED",
|
|
543
|
+
"IN_PROGRESS",
|
|
544
|
+
"BLOCKED",
|
|
545
|
+
"REVIEW",
|
|
546
|
+
"DONE"
|
|
547
|
+
]);
|
|
548
|
+
BacklogTypeSchema = z.enum(["feature", "bug", "refactor", "tech-debt"]);
|
|
549
|
+
BacklogPrioritySchema = z.enum(["P0", "P1", "P2", "P3"]);
|
|
550
|
+
BacklogGlobalSchema = z.object({
|
|
551
|
+
product: z.string().min(1),
|
|
552
|
+
strategy: z.string().min(1),
|
|
553
|
+
policy: z.string().min(1),
|
|
554
|
+
reviewRequired: z.boolean(),
|
|
555
|
+
tddRequired: z.boolean()
|
|
556
|
+
});
|
|
557
|
+
BacklogItemSchema = z.object({
|
|
558
|
+
id: z.string().regex(/^BC-\d{3,}$/),
|
|
559
|
+
title: z.string().min(1),
|
|
560
|
+
priority: BacklogPrioritySchema,
|
|
561
|
+
status: BacklogStatusSchema,
|
|
562
|
+
type: BacklogTypeSchema,
|
|
563
|
+
owner: z.string().optional(),
|
|
564
|
+
dependencies: z.array(z.string()).default([]),
|
|
565
|
+
description: z.string().min(1),
|
|
566
|
+
scope: z.string().min(1),
|
|
567
|
+
outOfScope: z.string().default(""),
|
|
568
|
+
businessValue: z.string().optional(),
|
|
569
|
+
acceptanceCriteria: z.array(z.string().min(1)).min(1),
|
|
570
|
+
risks: z.string().optional(),
|
|
571
|
+
progress: z.number().int().min(0).max(100),
|
|
572
|
+
branch: z.string().optional(),
|
|
573
|
+
reviewer: z.string().optional(),
|
|
574
|
+
lastUpdate: z.string().optional()
|
|
575
|
+
});
|
|
576
|
+
BacklogDocumentSchema = z.object({
|
|
577
|
+
global: BacklogGlobalSchema,
|
|
578
|
+
items: z.array(BacklogItemSchema),
|
|
579
|
+
archive: z.array(BacklogItemSchema).default([])
|
|
580
|
+
});
|
|
581
|
+
OpenspecTaskCardPhaseSchema = z.enum([
|
|
582
|
+
"discover",
|
|
583
|
+
"design",
|
|
584
|
+
"implement",
|
|
585
|
+
"test",
|
|
586
|
+
"review"
|
|
587
|
+
]);
|
|
588
|
+
OpenspecTaskCardStatusSchema = z.enum(["pending", "doing", "blocked", "done"]);
|
|
589
|
+
OpenspecTaskCardSchema = z.object({
|
|
590
|
+
id: z.string(),
|
|
591
|
+
backlogId: z.string(),
|
|
592
|
+
phase: OpenspecTaskCardPhaseSchema,
|
|
593
|
+
title: z.string(),
|
|
594
|
+
prompt: z.string(),
|
|
595
|
+
agent: z.string(),
|
|
596
|
+
modelHint: z.string().optional(),
|
|
597
|
+
dependsOn: z.array(z.string()).default([]),
|
|
598
|
+
acceptanceCriteria: z.array(z.string()),
|
|
599
|
+
status: OpenspecTaskCardStatusSchema,
|
|
600
|
+
itemHash: z.string().optional()
|
|
601
|
+
});
|
|
602
|
+
OpenspecStateSchema = z.object({
|
|
603
|
+
version: z.literal(1),
|
|
604
|
+
activeItemId: z.string().optional(),
|
|
605
|
+
taskCards: z.array(OpenspecTaskCardSchema).default([]),
|
|
606
|
+
lastScanHash: z.string().optional(),
|
|
607
|
+
lastScanAt: z.string().optional(),
|
|
608
|
+
changePaths: z.record(z.string(), z.string()).optional().default({}),
|
|
609
|
+
itemSnapshots: z.record(z.string(), z.string()).optional().default({})
|
|
610
|
+
});
|
|
611
|
+
WorkflowCommandSchema = z.enum([
|
|
612
|
+
"feature",
|
|
613
|
+
"fix",
|
|
614
|
+
"refactor",
|
|
615
|
+
"review",
|
|
616
|
+
"test-plan",
|
|
617
|
+
"tdd-cycle",
|
|
618
|
+
"api-contract",
|
|
619
|
+
"db-migration",
|
|
620
|
+
"pagespeed",
|
|
621
|
+
"openspec",
|
|
622
|
+
"backlog",
|
|
623
|
+
"scorecard",
|
|
624
|
+
"council",
|
|
625
|
+
"iterative",
|
|
626
|
+
"explore",
|
|
627
|
+
"triage",
|
|
628
|
+
"prototype",
|
|
629
|
+
"handoff",
|
|
630
|
+
"clarify",
|
|
631
|
+
"security"
|
|
632
|
+
]);
|
|
633
|
+
CcepOutputFormatSchema = z.enum(["taskcard", "plan", "verdict"]);
|
|
634
|
+
CommandEnvelopeSchema = z.object({
|
|
635
|
+
protocolVersion: z.literal("ccep-1"),
|
|
636
|
+
command: WorkflowCommandSchema,
|
|
637
|
+
userRequest: z.string(),
|
|
638
|
+
projectId: z.string(),
|
|
639
|
+
repoContext: z.object({
|
|
640
|
+
domain: z.string().optional(),
|
|
641
|
+
stack: z.array(z.string()),
|
|
642
|
+
existingModules: z.array(z.string()).default([]),
|
|
643
|
+
architecture: z.string().optional()
|
|
644
|
+
}),
|
|
645
|
+
constraints: z.object({
|
|
646
|
+
outputFormat: CcepOutputFormatSchema,
|
|
647
|
+
needConfirmation: z.boolean(),
|
|
648
|
+
riskThreshold: z.enum(["low", "medium", "high"])
|
|
649
|
+
}),
|
|
650
|
+
executionPolicy: z.object({
|
|
651
|
+
modelMode: z.literal("structured"),
|
|
652
|
+
maxVariance: z.literal("low")
|
|
653
|
+
})
|
|
654
|
+
});
|
|
655
|
+
WorkflowPhaseSchema = z.object({
|
|
656
|
+
id: z.string(),
|
|
657
|
+
agent: z.string().optional(),
|
|
658
|
+
agents: z.array(z.string()).optional(),
|
|
659
|
+
skill: z.string().optional(),
|
|
660
|
+
type: z.string().optional(),
|
|
661
|
+
outputSchema: z.string().optional(),
|
|
662
|
+
stopGate: z.string().optional(),
|
|
663
|
+
dependsOn: z.array(z.string()).optional(),
|
|
664
|
+
requires: z.string().optional(),
|
|
665
|
+
parallelWith: z.array(z.string()).optional()
|
|
666
|
+
});
|
|
667
|
+
WorkflowRiskRuleSchema = z.object({
|
|
668
|
+
when: z.object({
|
|
669
|
+
risk: z.union([
|
|
670
|
+
z.enum(["low", "medium", "high"]),
|
|
671
|
+
z.array(z.enum(["low", "medium", "high"]))
|
|
672
|
+
])
|
|
673
|
+
}),
|
|
674
|
+
then: z.array(z.string())
|
|
675
|
+
});
|
|
676
|
+
WorkflowProfileSchema = z.object({
|
|
677
|
+
id: z.string(),
|
|
678
|
+
version: z.number().int().positive(),
|
|
679
|
+
command: WorkflowCommandSchema,
|
|
680
|
+
taskCard: z.object({
|
|
681
|
+
type: z.string(),
|
|
682
|
+
requiredFields: z.array(z.string()),
|
|
683
|
+
optionalFields: z.array(z.string()).optional()
|
|
684
|
+
}).optional(),
|
|
685
|
+
intakeSchema: z.string().optional(),
|
|
686
|
+
phases: z.array(WorkflowPhaseSchema),
|
|
687
|
+
routing: z.object({
|
|
688
|
+
default: z.array(z.string()),
|
|
689
|
+
riskRules: z.array(WorkflowRiskRuleSchema).optional()
|
|
690
|
+
}),
|
|
691
|
+
confirmationGate: z.object({
|
|
692
|
+
stopOnHighRisk: z.boolean(),
|
|
693
|
+
stopOnQuestions: z.boolean()
|
|
694
|
+
})
|
|
695
|
+
}).refine((profile) => profile.id === profile.command, {
|
|
696
|
+
message: "Workflow profile id must match command"
|
|
697
|
+
});
|
|
698
|
+
ExecutionContextSchema = z.object({
|
|
699
|
+
envelope: CommandEnvelopeSchema,
|
|
700
|
+
profile: WorkflowProfileSchema,
|
|
701
|
+
intent: z.object({
|
|
702
|
+
type: WorkflowCommandSchema,
|
|
703
|
+
goal: z.string(),
|
|
704
|
+
domain: z.string().optional(),
|
|
705
|
+
entity: z.string().optional(),
|
|
706
|
+
operation: z.string().optional()
|
|
707
|
+
}),
|
|
708
|
+
project: z.object({
|
|
709
|
+
name: z.string(),
|
|
710
|
+
rootDir: z.string(),
|
|
711
|
+
stack: z.array(z.string()).optional()
|
|
712
|
+
}),
|
|
713
|
+
knowledge: z.record(z.string(), z.unknown()).default({}),
|
|
714
|
+
ast: z.object({
|
|
715
|
+
source: z.enum(["detect", "graphify", "manual", "product-graph"]),
|
|
716
|
+
confidence: z.enum(["low", "medium", "high"]),
|
|
717
|
+
domains: z.array(z.unknown()).optional(),
|
|
718
|
+
rules: z.array(z.string()).optional()
|
|
719
|
+
}),
|
|
720
|
+
policies: z.object({
|
|
721
|
+
architecture: z.string(),
|
|
722
|
+
testing: z.string(),
|
|
723
|
+
documentation: z.string(),
|
|
724
|
+
breakingChanges: z.string()
|
|
725
|
+
}),
|
|
726
|
+
currentPhase: z.string().optional(),
|
|
727
|
+
outputSchema: z.string()
|
|
728
|
+
});
|
|
729
|
+
PlannerOutputSchema = z.object({
|
|
730
|
+
status: z.enum(["success", "needs_clarification"]),
|
|
731
|
+
confidence: z.number().min(0).max(1),
|
|
732
|
+
goal: z.string(),
|
|
733
|
+
assumptions: z.array(z.string()),
|
|
734
|
+
risks: z.array(z.object({
|
|
735
|
+
type: z.string(),
|
|
736
|
+
description: z.string(),
|
|
737
|
+
severity: z.enum(["low", "medium", "high"])
|
|
738
|
+
})),
|
|
739
|
+
tasks: z.array(z.object({
|
|
740
|
+
id: z.string(),
|
|
741
|
+
title: z.string(),
|
|
742
|
+
priority: z.string(),
|
|
743
|
+
estimate: z.string(),
|
|
744
|
+
dependencies: z.array(z.string())
|
|
745
|
+
})),
|
|
746
|
+
questionsForUser: z.array(z.string()),
|
|
747
|
+
needsConfirmation: z.boolean()
|
|
748
|
+
});
|
|
749
|
+
AgentArtifactSchema = z.object({
|
|
750
|
+
type: z.string(),
|
|
751
|
+
path: z.string().optional(),
|
|
752
|
+
content: z.string().optional()
|
|
753
|
+
});
|
|
754
|
+
AgentOutputSchema = z.object({
|
|
755
|
+
status: z.enum(["success", "failure", "blocked", "needs_clarification"]),
|
|
756
|
+
confidence: z.number().min(0).max(1),
|
|
757
|
+
warnings: z.array(z.string()).default([]),
|
|
758
|
+
artifacts: z.array(AgentArtifactSchema).default([]),
|
|
759
|
+
next_actions: z.array(z.string()).default([])
|
|
760
|
+
});
|
|
761
|
+
ImplementerTestsSchema = z.object({
|
|
762
|
+
runner: z.string(),
|
|
763
|
+
result: z.enum(["passed", "failed"]),
|
|
764
|
+
failedTests: z.array(z.string()).optional()
|
|
765
|
+
});
|
|
766
|
+
ImplementerOutputSchema = AgentOutputSchema.extend({
|
|
767
|
+
status: z.enum(["success", "failure", "blocked"]),
|
|
768
|
+
filesChanged: z.array(z.object({
|
|
769
|
+
path: z.string(),
|
|
770
|
+
summary: z.string()
|
|
771
|
+
})).default([]),
|
|
772
|
+
tests: ImplementerTestsSchema.optional()
|
|
773
|
+
});
|
|
774
|
+
ReviewAxisSchema = z.enum([
|
|
775
|
+
"complexity",
|
|
776
|
+
"cost",
|
|
777
|
+
"performance",
|
|
778
|
+
"maintainability",
|
|
779
|
+
"security",
|
|
780
|
+
"scalability",
|
|
781
|
+
"style"
|
|
782
|
+
]);
|
|
783
|
+
ReviewFindingSchema = z.object({
|
|
784
|
+
severity: z.enum(["CRITICAL", "WARNING", "SUGGESTION"]),
|
|
785
|
+
message: z.string(),
|
|
786
|
+
axis: z.union([ReviewAxisSchema, z.string()]),
|
|
787
|
+
path: z.string().optional(),
|
|
788
|
+
line: z.number().int().optional()
|
|
789
|
+
});
|
|
790
|
+
ReviewerOutputSchema = z.object({
|
|
791
|
+
status: z.enum(["pass", "fail"]),
|
|
792
|
+
confidence: z.number().min(0).max(1),
|
|
793
|
+
verdict: z.enum(["approved", "approved_with_warnings", "blocked"]),
|
|
794
|
+
warnings: z.array(z.string()).default([]),
|
|
795
|
+
findings: z.array(ReviewFindingSchema).default([]),
|
|
796
|
+
artifacts: z.array(AgentArtifactSchema).default([]),
|
|
797
|
+
next_actions: z.array(z.string()).default([])
|
|
798
|
+
});
|
|
799
|
+
TechnicalPlanOutputSchema = z.object({
|
|
800
|
+
approach: z.string(),
|
|
801
|
+
filesAffected: z.array(z.string()).default([]),
|
|
802
|
+
risks: z.array(z.string()).default([]),
|
|
803
|
+
openQuestions: z.array(z.string()).optional()
|
|
804
|
+
});
|
|
805
|
+
ScorecardVerdictSchema = z.enum(["PASS", "REVISE", "REJECT"]);
|
|
806
|
+
ScorecardCriterionIdSchema = z.enum([
|
|
807
|
+
"acceptance",
|
|
808
|
+
"minimal_diff",
|
|
809
|
+
"tests",
|
|
810
|
+
"regressions",
|
|
811
|
+
"conventions",
|
|
812
|
+
"documentation",
|
|
813
|
+
"context_discipline",
|
|
814
|
+
"cc_gain"
|
|
815
|
+
]);
|
|
816
|
+
ScorecardCriterionSchema = z.object({
|
|
817
|
+
id: ScorecardCriterionIdSchema,
|
|
818
|
+
label: z.string(),
|
|
819
|
+
weight: z.number().min(0).max(1),
|
|
820
|
+
score: z.number().int().min(0).max(3),
|
|
821
|
+
notes: z.string().optional(),
|
|
822
|
+
autoSuggested: z.boolean().optional()
|
|
823
|
+
});
|
|
824
|
+
ScorecardRecordSchema = z.object({
|
|
825
|
+
id: z.string(),
|
|
826
|
+
taskId: z.string(),
|
|
827
|
+
agent: z.string(),
|
|
828
|
+
model: z.string().optional(),
|
|
829
|
+
contractVersion: z.string(),
|
|
830
|
+
evaluator: z.string().optional(),
|
|
831
|
+
criteria: z.array(ScorecardCriterionSchema),
|
|
832
|
+
weightedScore: z.number(),
|
|
833
|
+
verdict: ScorecardVerdictSchema,
|
|
834
|
+
findings: z.array(z.string()).optional().default([]),
|
|
835
|
+
createdAt: z.string(),
|
|
836
|
+
backlogId: z.string().optional(),
|
|
837
|
+
source: z.enum(["openspec", "review", "manual", "pipeline"]).optional()
|
|
838
|
+
});
|
|
839
|
+
TaskOutcomeSourceSchema = z.enum(["openspec", "review", "manual", "pipeline"]);
|
|
840
|
+
TaskOutcomeStatusSchema = z.enum([
|
|
841
|
+
"phase_done",
|
|
842
|
+
"phase_failed",
|
|
843
|
+
"pass",
|
|
844
|
+
"revise",
|
|
845
|
+
"reject"
|
|
846
|
+
]);
|
|
847
|
+
TaskOutcomeSchema = z.object({
|
|
848
|
+
id: z.string(),
|
|
849
|
+
taskId: z.string(),
|
|
850
|
+
source: TaskOutcomeSourceSchema,
|
|
851
|
+
agent: z.string(),
|
|
852
|
+
model: z.string(),
|
|
853
|
+
contractVersion: z.string(),
|
|
854
|
+
timestamp: z.string(),
|
|
855
|
+
status: TaskOutcomeStatusSchema.optional(),
|
|
856
|
+
verdict: ScorecardVerdictSchema.optional(),
|
|
857
|
+
weightedScore: z.number().optional(),
|
|
858
|
+
taskCardId: z.string().optional(),
|
|
859
|
+
backlogId: z.string().optional(),
|
|
860
|
+
phase: z.string().optional(),
|
|
861
|
+
scorecardId: z.string().optional(),
|
|
862
|
+
tokensIn: z.number().optional(),
|
|
863
|
+
tokensOut: z.number().optional(),
|
|
864
|
+
costUsd: z.number().optional(),
|
|
865
|
+
durationMs: z.number().optional(),
|
|
866
|
+
experimentId: z.string().optional(),
|
|
867
|
+
variantId: z.string().optional(),
|
|
868
|
+
suiteTaskId: z.string().optional(),
|
|
869
|
+
harnessFingerprint: z.string().optional(),
|
|
870
|
+
disabledComponents: z.array(z.string()).optional()
|
|
871
|
+
});
|
|
872
|
+
HarnessComponentIdSchema = z.enum([
|
|
873
|
+
"wayfinding",
|
|
874
|
+
"intake",
|
|
875
|
+
"design",
|
|
876
|
+
"test_first",
|
|
877
|
+
"review",
|
|
878
|
+
"docs",
|
|
879
|
+
"confirmation_gates",
|
|
880
|
+
"compile_loop",
|
|
881
|
+
"council",
|
|
882
|
+
"product_graph"
|
|
883
|
+
]);
|
|
884
|
+
HarnessComponentLayerSchema = z.enum([
|
|
885
|
+
"phase",
|
|
886
|
+
"gate",
|
|
887
|
+
"loop",
|
|
888
|
+
"knowledge",
|
|
889
|
+
"council"
|
|
890
|
+
]);
|
|
891
|
+
HarnessToggleKindSchema = z.enum([
|
|
892
|
+
"ccep_phase",
|
|
893
|
+
"ccep_gates",
|
|
894
|
+
"config_loop",
|
|
895
|
+
"config_council",
|
|
896
|
+
"product_graph"
|
|
897
|
+
]);
|
|
898
|
+
HarnessCatalogEntrySchema = z.object({
|
|
899
|
+
id: HarnessComponentIdSchema,
|
|
900
|
+
layer: HarnessComponentLayerSchema,
|
|
901
|
+
label: z.string(),
|
|
902
|
+
defaultOn: z.boolean().default(true),
|
|
903
|
+
toggle: z.object({
|
|
904
|
+
kind: HarnessToggleKindSchema,
|
|
905
|
+
phaseId: z.string().optional()
|
|
906
|
+
})
|
|
907
|
+
});
|
|
908
|
+
HarnessCatalogSchema = z.object({
|
|
909
|
+
version: z.literal(1),
|
|
910
|
+
components: z.array(HarnessCatalogEntrySchema).min(1)
|
|
911
|
+
});
|
|
912
|
+
HarnessOverlaySchema = z.object({
|
|
913
|
+
experimentId: z.string().optional(),
|
|
914
|
+
variantId: z.string(),
|
|
915
|
+
disabledComponents: z.array(HarnessComponentIdSchema),
|
|
916
|
+
disableProductGraph: z.boolean().optional().default(false),
|
|
917
|
+
contractVersion: z.string().optional(),
|
|
918
|
+
ccepProfile: z.string().optional().default("feature")
|
|
919
|
+
});
|
|
920
|
+
HarnessExperimentSchema = z.object({
|
|
921
|
+
id: z.string(),
|
|
922
|
+
suiteId: z.string(),
|
|
923
|
+
createdAt: z.string(),
|
|
924
|
+
contractVersion: z.string(),
|
|
925
|
+
components: z.array(HarnessComponentIdSchema),
|
|
926
|
+
variants: z.array(z.string()).min(1),
|
|
927
|
+
suiteTaskIds: z.array(z.string()),
|
|
928
|
+
suitePath: z.string().optional()
|
|
929
|
+
});
|
|
930
|
+
HarnessSuiteTaskSchema = z.object({
|
|
931
|
+
id: z.string(),
|
|
932
|
+
title: z.string(),
|
|
933
|
+
type: z.enum(["feature", "fix", "refactor"]),
|
|
934
|
+
risk: z.enum(["low", "medium", "high"]).default("low"),
|
|
935
|
+
prompt: z.string(),
|
|
936
|
+
scope: z.string(),
|
|
937
|
+
acceptanceCriteria: z.array(z.string()).min(1),
|
|
938
|
+
testCommand: z.string().optional()
|
|
939
|
+
});
|
|
940
|
+
HarnessSuiteSchema = z.object({
|
|
941
|
+
id: z.string(),
|
|
942
|
+
version: z.number().int().positive(),
|
|
943
|
+
fixtureDir: z.string().optional(),
|
|
944
|
+
tasks: z.array(HarnessSuiteTaskSchema).min(1)
|
|
945
|
+
});
|
|
946
|
+
EvaluationIndexSchema = z.object({
|
|
947
|
+
version: z.literal(1),
|
|
948
|
+
lastOutcomeId: z.string().optional()
|
|
949
|
+
});
|
|
950
|
+
ExecutionProfileNameSchema = z.enum(["balanced", "quality", "economical"]);
|
|
951
|
+
ExecutionProfileSchema = z.object({
|
|
952
|
+
profile: ExecutionProfileNameSchema.default("balanced"),
|
|
953
|
+
target: z.enum(["opencode", "claude", "codex", "gemini", "cursor", "agy"]).optional(),
|
|
954
|
+
overrides: z.record(z.string(), z.string()).optional().default({}),
|
|
955
|
+
subagentPolicy: z.object({
|
|
956
|
+
orchestrator: z.enum(["primary", "delegate"]).optional(),
|
|
957
|
+
testerReviewer: z.enum(["primary", "delegate"]).optional()
|
|
958
|
+
}).optional()
|
|
959
|
+
});
|
|
960
|
+
});
|
|
961
|
+
|
|
962
|
+
// src/utils/result.ts
|
|
963
|
+
function ok(data) {
|
|
964
|
+
return { success: true, data };
|
|
965
|
+
}
|
|
966
|
+
function err(error) {
|
|
967
|
+
return { success: false, error };
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
// src/core/goal/goal-state.ts
|
|
971
|
+
var exports_goal_state = {};
|
|
972
|
+
__export(exports_goal_state, {
|
|
973
|
+
writeGoal: () => writeGoal,
|
|
974
|
+
markTaskBlocked: () => markTaskBlocked,
|
|
975
|
+
loadGoal: () => loadGoal
|
|
976
|
+
});
|
|
977
|
+
import { mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
|
|
978
|
+
import { resolve } from "node:path";
|
|
979
|
+
import { parse, stringify } from "yaml";
|
|
980
|
+
function validateGoalGraph2(graph) {
|
|
981
|
+
const ids = new Set(graph.tasks.map((t) => t.id));
|
|
982
|
+
if (ids.size !== graph.tasks.length) {
|
|
983
|
+
return err(new Error("Duplicate task IDs in goal graph"));
|
|
984
|
+
}
|
|
985
|
+
for (const task of graph.tasks) {
|
|
986
|
+
for (const dep of task.depends_on ?? []) {
|
|
987
|
+
if (!ids.has(dep)) {
|
|
988
|
+
return err(new Error(`Task "${task.id}" depends on unknown task "${dep}"`));
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
const visited = new Set;
|
|
993
|
+
const inStack = new Set;
|
|
994
|
+
function dfs(taskId) {
|
|
995
|
+
if (inStack.has(taskId))
|
|
996
|
+
return true;
|
|
997
|
+
if (visited.has(taskId))
|
|
998
|
+
return false;
|
|
999
|
+
visited.add(taskId);
|
|
1000
|
+
inStack.add(taskId);
|
|
1001
|
+
const task = graph.tasks.find((t) => t.id === taskId);
|
|
1002
|
+
if (task) {
|
|
1003
|
+
for (const dep of task.depends_on ?? []) {
|
|
1004
|
+
if (dfs(dep))
|
|
1005
|
+
return true;
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
inStack.delete(taskId);
|
|
1009
|
+
return false;
|
|
1010
|
+
}
|
|
1011
|
+
for (const task of graph.tasks) {
|
|
1012
|
+
if (dfs(task.id)) {
|
|
1013
|
+
return err(new Error(`Cycle detected involving task "${task.id}"`));
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
return ok(graph);
|
|
1017
|
+
}
|
|
1018
|
+
async function writeGoal(projectRoot, graph) {
|
|
1019
|
+
const validation = validateGoalGraph2(graph);
|
|
1020
|
+
if (!validation.success)
|
|
1021
|
+
return validation;
|
|
1022
|
+
const dir = resolve(projectRoot, ".codeconductor");
|
|
1023
|
+
await mkdir2(dir, { recursive: true });
|
|
1024
|
+
const yaml = stringify(graph);
|
|
1025
|
+
await writeFile2(resolve(dir, "current-goal.yml"), yaml, "utf-8");
|
|
1026
|
+
return ok(undefined);
|
|
1027
|
+
}
|
|
1028
|
+
async function loadGoal(projectRoot) {
|
|
1029
|
+
try {
|
|
1030
|
+
const filePath = resolve(projectRoot, GOAL_FILE);
|
|
1031
|
+
const content = await readFile2(filePath, "utf-8");
|
|
1032
|
+
const data = parse(content);
|
|
1033
|
+
const validated = GoalGraphSchema.parse(data);
|
|
1034
|
+
return validateGoalGraph2(validated);
|
|
1035
|
+
} catch (e) {
|
|
1036
|
+
return err(e instanceof Error ? e : new Error(String(e)));
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
async function markTaskBlocked(projectRoot, taskId, reason) {
|
|
1040
|
+
const loadResult = await loadGoal(projectRoot);
|
|
1041
|
+
if (!loadResult.success)
|
|
1042
|
+
return loadResult;
|
|
1043
|
+
const graph = loadResult.data;
|
|
1044
|
+
const task = graph.tasks.find((t) => t.id === taskId);
|
|
1045
|
+
if (!task) {
|
|
1046
|
+
return err(new Error(`Task "${taskId}" not found in goal graph`));
|
|
1047
|
+
}
|
|
1048
|
+
task.status = "blocked";
|
|
1049
|
+
task.blocked_reason = reason;
|
|
1050
|
+
return writeGoal(projectRoot, graph);
|
|
1051
|
+
}
|
|
1052
|
+
var GOAL_FILE = ".codeconductor/current-goal.yml";
|
|
1053
|
+
var init_goal_state = __esm(() => {
|
|
1054
|
+
init_schemas();
|
|
1055
|
+
});
|
|
1056
|
+
|
|
1057
|
+
// src/core/product-graph/graph-store.ts
|
|
1058
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
1059
|
+
init_schemas();
|
|
1060
|
+
|
|
1061
|
+
// src/core/product-graph/paths.ts
|
|
1062
|
+
import { join } from "node:path";
|
|
1063
|
+
var PRODUCT_DIR = ".codeconductor";
|
|
1064
|
+
var PRODUCT_GRAPH_FILE = "product-graph.json";
|
|
1065
|
+
var EVENTS_FILE = "events.jsonl";
|
|
1066
|
+
var OPERATIONAL_STATE_FILE = "operational-state.json";
|
|
1067
|
+
var EVIDENCE_DIR = "evidence";
|
|
1068
|
+
function productGraphPath(projectRoot) {
|
|
1069
|
+
return join(projectRoot, PRODUCT_DIR, PRODUCT_GRAPH_FILE);
|
|
1070
|
+
}
|
|
1071
|
+
function eventsPath(projectRoot) {
|
|
1072
|
+
return join(projectRoot, PRODUCT_DIR, EVENTS_FILE);
|
|
1073
|
+
}
|
|
1074
|
+
function operationalStatePath(projectRoot) {
|
|
1075
|
+
return join(projectRoot, PRODUCT_DIR, OPERATIONAL_STATE_FILE);
|
|
1076
|
+
}
|
|
1077
|
+
function evidenceDir(projectRoot) {
|
|
1078
|
+
return join(projectRoot, PRODUCT_DIR, EVIDENCE_DIR);
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
// src/core/product-graph/graph-store.ts
|
|
1082
|
+
async function loadGraph(projectRoot) {
|
|
1083
|
+
try {
|
|
1084
|
+
const raw = await readFile(productGraphPath(projectRoot), "utf-8");
|
|
1085
|
+
return ok(ProductGraphSchema.parse(JSON.parse(raw)));
|
|
1086
|
+
} catch (e) {
|
|
1087
|
+
if (e.code === "ENOENT") {
|
|
1088
|
+
return err(new Error("Product graph not found. Run `cc ingest` first."));
|
|
1089
|
+
}
|
|
1090
|
+
return err(e instanceof Error ? e : new Error(String(e)));
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
function queryNodes(graph, type, textFilter) {
|
|
1094
|
+
let nodes = graph.nodes;
|
|
1095
|
+
if (type) {
|
|
1096
|
+
nodes = nodes.filter((n) => n.type === type);
|
|
1097
|
+
}
|
|
1098
|
+
if (textFilter) {
|
|
1099
|
+
const q = textFilter.toLowerCase();
|
|
1100
|
+
nodes = nodes.filter((n) => n.name.toLowerCase().includes(q) || n.id.toLowerCase().includes(q) || JSON.stringify(n.data).toLowerCase().includes(q));
|
|
1101
|
+
}
|
|
1102
|
+
return nodes;
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
// src/core/planner/product-planner.ts
|
|
1106
|
+
var RISK_TO_AGENT = {
|
|
1107
|
+
low: "implementer",
|
|
1108
|
+
medium: "architect",
|
|
1109
|
+
high: "task-coach"
|
|
1110
|
+
};
|
|
1111
|
+
function inferAgentType(task) {
|
|
1112
|
+
if (task.type === "test")
|
|
1113
|
+
return "tester";
|
|
1114
|
+
if (task.type === "docs")
|
|
1115
|
+
return "docs";
|
|
1116
|
+
if (task.risk === "high" && task.type === "feature")
|
|
1117
|
+
return "architect";
|
|
1118
|
+
return RISK_TO_AGENT[task.risk] ?? "implementer";
|
|
1119
|
+
}
|
|
1120
|
+
function inferTargetFiles(task, graph) {
|
|
1121
|
+
if (!graph)
|
|
1122
|
+
return [];
|
|
1123
|
+
const keywords = task.title.toLowerCase().split(/\s+/);
|
|
1124
|
+
const components = queryNodes(graph, "component");
|
|
1125
|
+
const matched = [];
|
|
1126
|
+
for (const node of components) {
|
|
1127
|
+
const path = node.data.path;
|
|
1128
|
+
if (!path)
|
|
1129
|
+
continue;
|
|
1130
|
+
const nameLower = node.name.toLowerCase();
|
|
1131
|
+
if (keywords.some((k) => nameLower.includes(k) || path.toLowerCase().includes(k))) {
|
|
1132
|
+
matched.push(path);
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
return matched.slice(0, 10);
|
|
1136
|
+
}
|
|
1137
|
+
function inferEvidenceRequired(task) {
|
|
1138
|
+
const base = ["acceptance_criteria_met"];
|
|
1139
|
+
if (task.type === "test" || task.risk !== "low") {
|
|
1140
|
+
base.push("tests_passed");
|
|
1141
|
+
}
|
|
1142
|
+
if (task.risk === "high") {
|
|
1143
|
+
base.push("review_approved");
|
|
1144
|
+
}
|
|
1145
|
+
return base;
|
|
1146
|
+
}
|
|
1147
|
+
function enrichGoalWithProduct(graph, productGraph) {
|
|
1148
|
+
const enrichedTasks = graph.tasks.map((task) => ({
|
|
1149
|
+
...task,
|
|
1150
|
+
targetFiles: inferTargetFiles(task, productGraph),
|
|
1151
|
+
agentType: inferAgentType(task),
|
|
1152
|
+
evidenceRequired: inferEvidenceRequired(task)
|
|
1153
|
+
}));
|
|
1154
|
+
return { ...graph, enrichedTasks };
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
// src/core/orchestrator/runtime-orchestrator.ts
|
|
1158
|
+
init_goal_state();
|
|
1159
|
+
|
|
1160
|
+
// src/core/memory/episodic-store.ts
|
|
1161
|
+
init_schemas();
|
|
1162
|
+
import { appendFile, mkdir as mkdir3, readFile as readFile3 } from "node:fs/promises";
|
|
1163
|
+
import { resolve as resolve2 } from "node:path";
|
|
1164
|
+
async function appendEvent(projectRoot, event) {
|
|
1165
|
+
try {
|
|
1166
|
+
const full = ProductEventSchema.parse({
|
|
1167
|
+
...event,
|
|
1168
|
+
id: event.id ?? `evt-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`
|
|
1169
|
+
});
|
|
1170
|
+
const path = eventsPath(projectRoot);
|
|
1171
|
+
await mkdir3(resolve2(projectRoot, ".codeconductor"), { recursive: true });
|
|
1172
|
+
await appendFile(path, JSON.stringify(full) + `
|
|
1173
|
+
`, "utf-8");
|
|
1174
|
+
return ok(full);
|
|
1175
|
+
} catch (e) {
|
|
1176
|
+
return err(e instanceof Error ? e : new Error(String(e)));
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
// src/core/memory/operational-state.ts
|
|
1181
|
+
init_schemas();
|
|
1182
|
+
import { mkdir as mkdir4, readFile as readFile4, writeFile as writeFile3 } from "node:fs/promises";
|
|
1183
|
+
import { resolve as resolve3 } from "node:path";
|
|
1184
|
+
async function loadOperationalState(projectRoot) {
|
|
1185
|
+
try {
|
|
1186
|
+
const raw = await readFile4(operationalStatePath(projectRoot), "utf-8");
|
|
1187
|
+
return ok(OperationalStateSchema.parse(JSON.parse(raw)));
|
|
1188
|
+
} catch (e) {
|
|
1189
|
+
if (e.code === "ENOENT") {
|
|
1190
|
+
return ok({
|
|
1191
|
+
version: 1,
|
|
1192
|
+
activeAgents: [],
|
|
1193
|
+
activeTaskIds: [],
|
|
1194
|
+
blockers: [],
|
|
1195
|
+
updatedAt: new Date().toISOString()
|
|
1196
|
+
});
|
|
1197
|
+
}
|
|
1198
|
+
return err(e instanceof Error ? e : new Error(String(e)));
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
async function saveOperationalState(projectRoot, state) {
|
|
1202
|
+
try {
|
|
1203
|
+
const validated = OperationalStateSchema.parse({
|
|
1204
|
+
...state,
|
|
1205
|
+
updatedAt: new Date().toISOString()
|
|
1206
|
+
});
|
|
1207
|
+
const path = operationalStatePath(projectRoot);
|
|
1208
|
+
await mkdir4(resolve3(projectRoot, ".codeconductor"), { recursive: true });
|
|
1209
|
+
await writeFile3(path, JSON.stringify(validated, null, 2), "utf-8");
|
|
1210
|
+
return ok(undefined);
|
|
1211
|
+
} catch (e) {
|
|
1212
|
+
return err(e instanceof Error ? e : new Error(String(e)));
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
async function setActiveTask(projectRoot, taskId, agent) {
|
|
1216
|
+
const load = await loadOperationalState(projectRoot);
|
|
1217
|
+
if (!load.success)
|
|
1218
|
+
return load;
|
|
1219
|
+
const state = load.data;
|
|
1220
|
+
if (!state.activeTaskIds.includes(taskId)) {
|
|
1221
|
+
state.activeTaskIds.push(taskId);
|
|
1222
|
+
}
|
|
1223
|
+
if (agent && !state.activeAgents.includes(agent)) {
|
|
1224
|
+
state.activeAgents.push(agent);
|
|
1225
|
+
}
|
|
1226
|
+
return saveOperationalState(projectRoot, state);
|
|
1227
|
+
}
|
|
1228
|
+
async function clearActiveTask(projectRoot, taskId) {
|
|
1229
|
+
const load = await loadOperationalState(projectRoot);
|
|
1230
|
+
if (!load.success)
|
|
1231
|
+
return load;
|
|
1232
|
+
const state = load.data;
|
|
1233
|
+
state.activeTaskIds = state.activeTaskIds.filter((id) => id !== taskId);
|
|
1234
|
+
state.blockers = state.blockers.filter((b) => b.taskId !== taskId);
|
|
1235
|
+
return saveOperationalState(projectRoot, state);
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
// src/core/verification/verification-runner.ts
|
|
1239
|
+
init_schemas();
|
|
1240
|
+
import { existsSync } from "node:fs";
|
|
1241
|
+
import { readFile as readFile6 } from "node:fs/promises";
|
|
1242
|
+
import { dirname, join as join2, resolve as resolve5 } from "node:path";
|
|
1243
|
+
|
|
1244
|
+
// src/core/config/config-loader.ts
|
|
1245
|
+
import { readFile as readFile5 } from "node:fs/promises";
|
|
1246
|
+
import { resolve as resolve4 } from "node:path";
|
|
1247
|
+
import { parse as parse2 } from "yaml";
|
|
1248
|
+
|
|
1249
|
+
// src/cli/errors.ts
|
|
1250
|
+
var ExitCode = {
|
|
1251
|
+
SUCCESS: 0,
|
|
1252
|
+
VALIDATION_ERROR: 1,
|
|
1253
|
+
UNSAFE_OPERATION: 2,
|
|
1254
|
+
UNSUPPORTED_PROJECT: 3,
|
|
1255
|
+
CONFIG_CONFLICT: 4,
|
|
1256
|
+
CREDENTIAL_LEAK: 5
|
|
1257
|
+
};
|
|
1258
|
+
|
|
1259
|
+
class CliError extends Error {
|
|
1260
|
+
code;
|
|
1261
|
+
details;
|
|
1262
|
+
constructor(message, code, details) {
|
|
1263
|
+
super(message);
|
|
1264
|
+
this.code = code;
|
|
1265
|
+
this.details = details;
|
|
1266
|
+
this.name = "CliError";
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
class ValidationError extends CliError {
|
|
1271
|
+
constructor(message, details) {
|
|
1272
|
+
super(message, ExitCode.VALIDATION_ERROR, details);
|
|
1273
|
+
this.name = "ValidationError";
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1277
|
+
// src/core/config/config-loader.ts
|
|
1278
|
+
init_schemas();
|
|
1279
|
+
var CONFIG_FILE = ".codeconductor/config.yml";
|
|
1280
|
+
async function loadConfig(projectRoot) {
|
|
1281
|
+
try {
|
|
1282
|
+
const configPath = resolve4(projectRoot, CONFIG_FILE);
|
|
1283
|
+
const content = await readFile5(configPath, "utf-8");
|
|
1284
|
+
const data = parse2(content);
|
|
1285
|
+
if (!data) {
|
|
1286
|
+
return err(new ValidationError("Empty config file"));
|
|
1287
|
+
}
|
|
1288
|
+
const validated = validateConfig(data);
|
|
1289
|
+
return ok(validated);
|
|
1290
|
+
} catch (error) {
|
|
1291
|
+
if (error instanceof ValidationError) {
|
|
1292
|
+
return err(error);
|
|
1293
|
+
}
|
|
1294
|
+
if (error.code === "ENOENT") {
|
|
1295
|
+
return err(new ValidationError("Config file not found. Run `codeconductor init` first."));
|
|
1296
|
+
}
|
|
1297
|
+
return err(new ValidationError("Failed to load config", error));
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
// src/core/compilation/compile-checker.ts
|
|
1302
|
+
var DEFAULT_COMMAND = "tsc --noEmit";
|
|
1303
|
+
var DEFAULT_TIMEOUT_MS = 120000;
|
|
1304
|
+
function tokenizeCommand(cmd) {
|
|
1305
|
+
const tokens = [];
|
|
1306
|
+
let current = "";
|
|
1307
|
+
let inSingle = false;
|
|
1308
|
+
let inDouble = false;
|
|
1309
|
+
for (let i = 0;i < cmd.length; i++) {
|
|
1310
|
+
const ch = cmd[i];
|
|
1311
|
+
if (inSingle) {
|
|
1312
|
+
if (ch === "'") {
|
|
1313
|
+
inSingle = false;
|
|
1314
|
+
} else {
|
|
1315
|
+
current += ch;
|
|
1316
|
+
}
|
|
1317
|
+
} else if (inDouble) {
|
|
1318
|
+
if (ch === '"') {
|
|
1319
|
+
inDouble = false;
|
|
1320
|
+
} else {
|
|
1321
|
+
current += ch;
|
|
1322
|
+
}
|
|
1323
|
+
} else if (ch === "'") {
|
|
1324
|
+
inSingle = true;
|
|
1325
|
+
} else if (ch === '"') {
|
|
1326
|
+
inDouble = true;
|
|
1327
|
+
} else if (/\s/.test(ch)) {
|
|
1328
|
+
if (current) {
|
|
1329
|
+
tokens.push(current);
|
|
1330
|
+
current = "";
|
|
1331
|
+
}
|
|
1332
|
+
} else {
|
|
1333
|
+
current += ch;
|
|
1334
|
+
}
|
|
1335
|
+
}
|
|
1336
|
+
if (current)
|
|
1337
|
+
tokens.push(current);
|
|
1338
|
+
return tokens;
|
|
1339
|
+
}
|
|
1340
|
+
var ALLOWLISTED_ARGV_PREFIXES = [
|
|
1341
|
+
["tsc"],
|
|
1342
|
+
["bun", "run"],
|
|
1343
|
+
["bun", "test"],
|
|
1344
|
+
["npm", "test"],
|
|
1345
|
+
["npm", "run"],
|
|
1346
|
+
["npx", "tsc"],
|
|
1347
|
+
["pnpm", "test"],
|
|
1348
|
+
["pnpm", "run"],
|
|
1349
|
+
["yarn", "test"],
|
|
1350
|
+
["yarn", "run"]
|
|
1351
|
+
];
|
|
1352
|
+
function isAllowlistedCompileCommand(command) {
|
|
1353
|
+
const parts = Array.isArray(command) ? command : tokenizeCommand(command);
|
|
1354
|
+
if (parts.length === 0)
|
|
1355
|
+
return false;
|
|
1356
|
+
const bin = parts[0];
|
|
1357
|
+
if (bin.includes("/") || bin.includes("\\"))
|
|
1358
|
+
return false;
|
|
1359
|
+
return ALLOWLISTED_ARGV_PREFIXES.some((prefix) => parts.length >= prefix.length && prefix.every((token, i) => parts[i] === token));
|
|
1360
|
+
}
|
|
1361
|
+
function isAllowlistedTestCommand(command) {
|
|
1362
|
+
if (!isAllowlistedCompileCommand(command))
|
|
1363
|
+
return false;
|
|
1364
|
+
const parts = Array.isArray(command) ? command : tokenizeCommand(command);
|
|
1365
|
+
return parts.some((token) => token === "test" || token.startsWith("test:"));
|
|
1366
|
+
}
|
|
1367
|
+
function minimalChildEnv() {
|
|
1368
|
+
const env = {
|
|
1369
|
+
PATH: process.env.PATH ?? "",
|
|
1370
|
+
NODE_NO_WARNINGS: "1"
|
|
1371
|
+
};
|
|
1372
|
+
if (process.env.HOME)
|
|
1373
|
+
env.HOME = process.env.HOME;
|
|
1374
|
+
if (process.platform === "win32") {
|
|
1375
|
+
if (process.env.SystemRoot)
|
|
1376
|
+
env.SystemRoot = process.env.SystemRoot;
|
|
1377
|
+
if (process.env.USERPROFILE)
|
|
1378
|
+
env.USERPROFILE = process.env.USERPROFILE;
|
|
1379
|
+
}
|
|
1380
|
+
return env;
|
|
1381
|
+
}
|
|
1382
|
+
function parseTypeScriptErrors(stderr) {
|
|
1383
|
+
const errors = [];
|
|
1384
|
+
const tsRegex = /^(.+?)\((\d+)(?:,\s*(\d+))?\)\s*:\s*error\s+(TS\d+):\s*(.+)$/gm;
|
|
1385
|
+
let match;
|
|
1386
|
+
while ((match = tsRegex.exec(stderr)) !== null) {
|
|
1387
|
+
errors.push({
|
|
1388
|
+
file: match[1],
|
|
1389
|
+
line: parseInt(match[2], 10),
|
|
1390
|
+
column: match[3] ? parseInt(match[3], 10) : undefined,
|
|
1391
|
+
code: match[4],
|
|
1392
|
+
message: match[5],
|
|
1393
|
+
raw: match[0]
|
|
1394
|
+
});
|
|
1395
|
+
}
|
|
1396
|
+
return errors;
|
|
1397
|
+
}
|
|
1398
|
+
function parseEslintErrors(stderr) {
|
|
1399
|
+
const errors = [];
|
|
1400
|
+
const eslintRegex = /^(.+?):(\d+):(\d+):\s+(.+?)\s+(error|warning)(?:\s+(\S+))?\s*$/gm;
|
|
1401
|
+
let match;
|
|
1402
|
+
while ((match = eslintRegex.exec(stderr)) !== null) {
|
|
1403
|
+
errors.push({
|
|
1404
|
+
file: match[1],
|
|
1405
|
+
line: parseInt(match[2], 10),
|
|
1406
|
+
column: parseInt(match[3], 10),
|
|
1407
|
+
code: match[6],
|
|
1408
|
+
message: match[4],
|
|
1409
|
+
raw: match[0]
|
|
1410
|
+
});
|
|
1411
|
+
}
|
|
1412
|
+
return errors;
|
|
1413
|
+
}
|
|
1414
|
+
function parseGenericErrors(stderr) {
|
|
1415
|
+
const errors = [];
|
|
1416
|
+
const withPosRegex = /^(.+?):(\d+):(\d+):\s+(.+)$/gm;
|
|
1417
|
+
let match;
|
|
1418
|
+
while ((match = withPosRegex.exec(stderr)) !== null) {
|
|
1419
|
+
errors.push({
|
|
1420
|
+
file: match[1],
|
|
1421
|
+
line: parseInt(match[2], 10),
|
|
1422
|
+
column: parseInt(match[3], 10),
|
|
1423
|
+
code: "",
|
|
1424
|
+
message: match[4],
|
|
1425
|
+
raw: match[0]
|
|
1426
|
+
});
|
|
1427
|
+
}
|
|
1428
|
+
const withLineOnlyRegex = /^(.+?):\s+(\d+):\s+(.+)$/gm;
|
|
1429
|
+
while ((match = withLineOnlyRegex.exec(stderr)) !== null) {
|
|
1430
|
+
const already = errors.some((e) => e.file === match[1] && e.line === parseInt(match[2], 10));
|
|
1431
|
+
if (!already) {
|
|
1432
|
+
errors.push({
|
|
1433
|
+
file: match[1],
|
|
1434
|
+
line: parseInt(match[2], 10),
|
|
1435
|
+
code: "",
|
|
1436
|
+
message: match[3],
|
|
1437
|
+
raw: match[0]
|
|
1438
|
+
});
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1441
|
+
if (errors.length === 0) {
|
|
1442
|
+
const plainRegex = /^(.+?):\s+(.+)$/gm;
|
|
1443
|
+
while ((match = plainRegex.exec(stderr)) !== null) {
|
|
1444
|
+
errors.push({
|
|
1445
|
+
file: match[1],
|
|
1446
|
+
code: "",
|
|
1447
|
+
message: match[2],
|
|
1448
|
+
raw: match[0]
|
|
1449
|
+
});
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1452
|
+
return errors;
|
|
1453
|
+
}
|
|
1454
|
+
function parseCompileErrors(stderr) {
|
|
1455
|
+
if (!stderr || !stderr.trim())
|
|
1456
|
+
return [];
|
|
1457
|
+
const tsErrors = parseTypeScriptErrors(stderr);
|
|
1458
|
+
if (tsErrors.length > 0)
|
|
1459
|
+
return tsErrors;
|
|
1460
|
+
const eslintErrors = parseEslintErrors(stderr);
|
|
1461
|
+
if (eslintErrors.length > 0)
|
|
1462
|
+
return eslintErrors;
|
|
1463
|
+
return parseGenericErrors(stderr);
|
|
1464
|
+
}
|
|
1465
|
+
async function runCompileCheck(options) {
|
|
1466
|
+
const command = options?.command ?? DEFAULT_COMMAND;
|
|
1467
|
+
const cwd = options?.cwd ?? process.cwd();
|
|
1468
|
+
const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
1469
|
+
const startTime = performance.now();
|
|
1470
|
+
let timedOut = false;
|
|
1471
|
+
const parts = Array.isArray(command) ? command : tokenizeCommand(command);
|
|
1472
|
+
let proc;
|
|
1473
|
+
try {
|
|
1474
|
+
proc = Bun.spawn(parts, {
|
|
1475
|
+
cwd,
|
|
1476
|
+
stdout: "pipe",
|
|
1477
|
+
stderr: "pipe",
|
|
1478
|
+
env: minimalChildEnv(),
|
|
1479
|
+
detached: process.platform !== "win32"
|
|
1480
|
+
});
|
|
1481
|
+
} catch (err2) {
|
|
1482
|
+
const durationMs = performance.now() - startTime;
|
|
1483
|
+
return {
|
|
1484
|
+
success: false,
|
|
1485
|
+
exitCode: -1,
|
|
1486
|
+
stdout: "",
|
|
1487
|
+
stderr: String(err2),
|
|
1488
|
+
errors: [],
|
|
1489
|
+
durationMs,
|
|
1490
|
+
timedOut: false
|
|
1491
|
+
};
|
|
1492
|
+
}
|
|
1493
|
+
const collectOutput = (async () => {
|
|
1494
|
+
const stdoutStream = proc.stdout;
|
|
1495
|
+
const stderrStream = proc.stderr;
|
|
1496
|
+
const [stdout, stderr] = await Promise.all([
|
|
1497
|
+
new Response(stdoutStream).text(),
|
|
1498
|
+
new Response(stderrStream).text()
|
|
1499
|
+
]);
|
|
1500
|
+
return { stdout, stderr, exitCode: await proc.exited };
|
|
1501
|
+
})();
|
|
1502
|
+
collectOutput.catch(() => {});
|
|
1503
|
+
let timeoutId;
|
|
1504
|
+
const timeout = new Promise((resolve5) => {
|
|
1505
|
+
timeoutId = setTimeout(() => resolve5("timeout"), timeoutMs);
|
|
1506
|
+
});
|
|
1507
|
+
try {
|
|
1508
|
+
const outcome = await Promise.race([collectOutput, timeout]);
|
|
1509
|
+
if (outcome === "timeout") {
|
|
1510
|
+
timedOut = true;
|
|
1511
|
+
try {
|
|
1512
|
+
if (process.platform === "win32") {
|
|
1513
|
+
const taskkill = Bun.spawn(["taskkill", "/PID", String(proc.pid), "/T", "/F"], { stdout: "ignore", stderr: "ignore" });
|
|
1514
|
+
await taskkill.exited;
|
|
1515
|
+
} else {
|
|
1516
|
+
process.kill(-proc.pid, "SIGKILL");
|
|
1517
|
+
}
|
|
1518
|
+
} catch {
|
|
1519
|
+
try {
|
|
1520
|
+
proc.kill("SIGKILL");
|
|
1521
|
+
} catch {}
|
|
1522
|
+
}
|
|
1523
|
+
await proc.exited;
|
|
1524
|
+
return {
|
|
1525
|
+
success: false,
|
|
1526
|
+
exitCode: proc.exitCode ?? -1,
|
|
1527
|
+
stdout: "",
|
|
1528
|
+
stderr: `Compile check timed out after ${timeoutMs}ms`,
|
|
1529
|
+
errors: [],
|
|
1530
|
+
durationMs: performance.now() - startTime,
|
|
1531
|
+
timedOut
|
|
1532
|
+
};
|
|
1533
|
+
}
|
|
1534
|
+
return {
|
|
1535
|
+
success: outcome.exitCode === 0,
|
|
1536
|
+
exitCode: outcome.exitCode,
|
|
1537
|
+
stdout: outcome.stdout,
|
|
1538
|
+
stderr: outcome.stderr,
|
|
1539
|
+
errors: parseCompileErrors(outcome.stderr),
|
|
1540
|
+
durationMs: performance.now() - startTime,
|
|
1541
|
+
timedOut
|
|
1542
|
+
};
|
|
1543
|
+
} catch (err2) {
|
|
1544
|
+
return {
|
|
1545
|
+
success: false,
|
|
1546
|
+
exitCode: -1,
|
|
1547
|
+
stdout: "",
|
|
1548
|
+
stderr: String(err2),
|
|
1549
|
+
errors: [],
|
|
1550
|
+
durationMs: performance.now() - startTime,
|
|
1551
|
+
timedOut
|
|
1552
|
+
};
|
|
1553
|
+
} finally {
|
|
1554
|
+
clearTimeout(timeoutId);
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1557
|
+
// src/core/verification/verification-runner.ts
|
|
1558
|
+
import { mkdir as mkdir5, readdir, writeFile as writeFile4 } from "node:fs/promises";
|
|
1559
|
+
function isPassingEvidence(ev) {
|
|
1560
|
+
switch (ev.type) {
|
|
1561
|
+
case "verification":
|
|
1562
|
+
return ev.data?.passed === true;
|
|
1563
|
+
case "test": {
|
|
1564
|
+
const tests = ImplementerTestsSchema.safeParse(ev.data);
|
|
1565
|
+
return tests.success && tests.data.result === "passed";
|
|
1566
|
+
}
|
|
1567
|
+
case "review": {
|
|
1568
|
+
const review = ReviewerOutputSchema.safeParse(ev.data);
|
|
1569
|
+
return review.success && review.data.status === "pass" && review.data.verdict !== "blocked";
|
|
1570
|
+
}
|
|
1571
|
+
default:
|
|
1572
|
+
return false;
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
function evidenceFilePath(evDir, id) {
|
|
1576
|
+
const path = resolve5(evDir, `${id.replace(/[^A-Za-z0-9_-]/g, "_")}.json`);
|
|
1577
|
+
if (dirname(path) !== resolve5(evDir)) {
|
|
1578
|
+
return err(new Error(`Refusing to write evidence for "${id}" outside ${evDir}`));
|
|
1579
|
+
}
|
|
1580
|
+
return ok(path);
|
|
1581
|
+
}
|
|
1582
|
+
async function persistEvidence(projectRoot, evidence) {
|
|
1583
|
+
const evDir = evidenceDir(projectRoot);
|
|
1584
|
+
const evidencePath = evidenceFilePath(evDir, evidence.id);
|
|
1585
|
+
if (!evidencePath.success)
|
|
1586
|
+
return evidencePath;
|
|
1587
|
+
try {
|
|
1588
|
+
await mkdir5(evDir, { recursive: true });
|
|
1589
|
+
await writeFile4(evidencePath.data, JSON.stringify(evidence, null, 2), "utf-8");
|
|
1590
|
+
} catch (e) {
|
|
1591
|
+
return err(e instanceof Error ? e : new Error(String(e)));
|
|
1592
|
+
}
|
|
1593
|
+
return ok(undefined);
|
|
1594
|
+
}
|
|
1595
|
+
async function collectTaskEvidence(projectRoot, taskId) {
|
|
1596
|
+
const evDir = evidenceDir(projectRoot);
|
|
1597
|
+
const records = [];
|
|
1598
|
+
let invalid = 0;
|
|
1599
|
+
if (!existsSync(evDir))
|
|
1600
|
+
return ok({ records, invalid });
|
|
1601
|
+
let files;
|
|
1602
|
+
try {
|
|
1603
|
+
files = await readdir(evDir);
|
|
1604
|
+
} catch (e) {
|
|
1605
|
+
return err(e instanceof Error ? e : new Error(String(e)));
|
|
1606
|
+
}
|
|
1607
|
+
for (const file of files) {
|
|
1608
|
+
if (!file.endsWith(".json"))
|
|
1609
|
+
continue;
|
|
1610
|
+
try {
|
|
1611
|
+
const raw = await readFile6(join2(evDir, file), "utf-8");
|
|
1612
|
+
const ev = EvidenceSchema.parse(JSON.parse(raw));
|
|
1613
|
+
if (ev.relatedTask === taskId)
|
|
1614
|
+
records.push(ev);
|
|
1615
|
+
} catch {
|
|
1616
|
+
invalid++;
|
|
1617
|
+
}
|
|
1618
|
+
}
|
|
1619
|
+
return ok({ records, invalid });
|
|
1620
|
+
}
|
|
1621
|
+
async function validateEvidenceIds(projectRoot, taskId, evidenceIds) {
|
|
1622
|
+
const collected = await collectTaskEvidence(projectRoot, taskId);
|
|
1623
|
+
if (!collected.success)
|
|
1624
|
+
return collected;
|
|
1625
|
+
const owned = new Map(collected.data.records.map((ev) => [ev.id, ev]));
|
|
1626
|
+
let hasPassingVerification = false;
|
|
1627
|
+
for (const id of evidenceIds) {
|
|
1628
|
+
const record = owned.get(id);
|
|
1629
|
+
if (!record) {
|
|
1630
|
+
return err(new Error(`Evidence "${id}" is not a record of task ${taskId}`));
|
|
1631
|
+
}
|
|
1632
|
+
if (!isPassingEvidence(record)) {
|
|
1633
|
+
return err(new Error(`Evidence "${id}" does not record a passing result`));
|
|
1634
|
+
}
|
|
1635
|
+
if (record.type === "verification")
|
|
1636
|
+
hasPassingVerification = true;
|
|
1637
|
+
}
|
|
1638
|
+
if (!hasPassingVerification) {
|
|
1639
|
+
return err(new Error(`Task ${taskId} requires at least one passing verification evidence`));
|
|
1640
|
+
}
|
|
1641
|
+
return ok(undefined);
|
|
1642
|
+
}
|
|
1643
|
+
async function runVerification(projectRoot, taskId, goal, options) {
|
|
1644
|
+
const checks = [];
|
|
1645
|
+
const evidenceIds = [];
|
|
1646
|
+
let task;
|
|
1647
|
+
if (goal) {
|
|
1648
|
+
task = goal.tasks.find((t) => t.id === taskId);
|
|
1649
|
+
} else {
|
|
1650
|
+
const { loadGoal: loadGoal2 } = await Promise.resolve().then(() => (init_goal_state(), exports_goal_state));
|
|
1651
|
+
const g = await loadGoal2(projectRoot);
|
|
1652
|
+
if (!g.success)
|
|
1653
|
+
return g;
|
|
1654
|
+
task = g.data.tasks.find((t) => t.id === taskId);
|
|
1655
|
+
}
|
|
1656
|
+
if (!task) {
|
|
1657
|
+
return err(new Error(`Task ${taskId} not found in goal`));
|
|
1658
|
+
}
|
|
1659
|
+
const criteriaCount = task.acceptance_criteria.length;
|
|
1660
|
+
checks.push({
|
|
1661
|
+
name: "acceptance_criteria_defined",
|
|
1662
|
+
passed: criteriaCount > 0,
|
|
1663
|
+
message: criteriaCount > 0 ? `${criteriaCount} acceptance criteria defined` : "No acceptance criteria defined"
|
|
1664
|
+
});
|
|
1665
|
+
const configResult = await loadConfig(projectRoot);
|
|
1666
|
+
if (!configResult.success) {
|
|
1667
|
+
checks.push({
|
|
1668
|
+
name: "config_loaded",
|
|
1669
|
+
passed: false,
|
|
1670
|
+
message: `Cannot load config: ${configResult.error.message}`
|
|
1671
|
+
});
|
|
1672
|
+
} else {
|
|
1673
|
+
const compileCheck = configResult.data.safety.compileCheck;
|
|
1674
|
+
if (!compileCheck?.enabled) {
|
|
1675
|
+
checks.push({
|
|
1676
|
+
name: "compile_check",
|
|
1677
|
+
passed: true,
|
|
1678
|
+
message: "Compile check not enabled"
|
|
1679
|
+
});
|
|
1680
|
+
} else if (!compileCheck.command) {
|
|
1681
|
+
checks.push({
|
|
1682
|
+
name: "compile_check",
|
|
1683
|
+
passed: false,
|
|
1684
|
+
message: "Compile check enabled but no command configured"
|
|
1685
|
+
});
|
|
1686
|
+
} else if (!options?.allowCompileCheck && !isAllowlistedCompileCommand(compileCheck.command)) {
|
|
1687
|
+
checks.push({
|
|
1688
|
+
name: "compile_check",
|
|
1689
|
+
passed: false,
|
|
1690
|
+
message: "Compile check not executed: the command is not on the compile allowlist. Re-run with --allow-compile-check to trust it."
|
|
1691
|
+
});
|
|
1692
|
+
} else {
|
|
1693
|
+
const compile = await runCompileCheck({
|
|
1694
|
+
command: compileCheck.command,
|
|
1695
|
+
cwd: projectRoot,
|
|
1696
|
+
timeoutMs: compileCheck.timeoutMs
|
|
1697
|
+
});
|
|
1698
|
+
checks.push({
|
|
1699
|
+
name: "compile_check",
|
|
1700
|
+
passed: compile.success && !compile.timedOut,
|
|
1701
|
+
message: compile.timedOut ? `Compile check timed out: ${compileCheck.command}` : compile.success ? `Compile check passed: ${compileCheck.command}` : `Compile check failed (exit ${compile.exitCode}): ${compileCheck.command}`
|
|
1702
|
+
});
|
|
1703
|
+
}
|
|
1704
|
+
}
|
|
1705
|
+
const collected = await collectTaskEvidence(projectRoot, taskId);
|
|
1706
|
+
if (!collected.success)
|
|
1707
|
+
return collected;
|
|
1708
|
+
checks.push({
|
|
1709
|
+
name: "evidence_readable",
|
|
1710
|
+
passed: collected.data.invalid === 0,
|
|
1711
|
+
message: collected.data.invalid === 0 ? "All evidence records are readable" : `${collected.data.invalid} unreadable evidence record(s)`
|
|
1712
|
+
});
|
|
1713
|
+
const supporting = collected.data.records.filter((ev) => ev.type !== "verification" && isPassingEvidence(ev));
|
|
1714
|
+
evidenceIds.push(...supporting.map((ev) => ev.id));
|
|
1715
|
+
checks.push({
|
|
1716
|
+
name: "evidence_present",
|
|
1717
|
+
passed: supporting.length > 0 || task.risk === "low",
|
|
1718
|
+
message: supporting.length > 0 ? `${supporting.length} passing evidence record(s) for task` : task.risk === "low" ? "Low risk task — evidence optional" : "No passing evidence records found for task"
|
|
1719
|
+
});
|
|
1720
|
+
const passed = checks.every((c) => c.passed);
|
|
1721
|
+
const evidence = {
|
|
1722
|
+
id: `ev-verify-${taskId}-${Date.now()}`,
|
|
1723
|
+
source: "cc verify",
|
|
1724
|
+
type: "verification",
|
|
1725
|
+
timestamp: new Date().toISOString(),
|
|
1726
|
+
relatedTask: taskId,
|
|
1727
|
+
confidence: passed ? 0.9 : 0.3,
|
|
1728
|
+
summary: passed ? "Verification passed" : "Verification failed",
|
|
1729
|
+
data: { passed, checks }
|
|
1730
|
+
};
|
|
1731
|
+
const persisted = await persistEvidence(projectRoot, evidence);
|
|
1732
|
+
if (!persisted.success)
|
|
1733
|
+
return persisted;
|
|
1734
|
+
if (passed)
|
|
1735
|
+
evidenceIds.push(evidence.id);
|
|
1736
|
+
const event = await appendEvent(projectRoot, {
|
|
1737
|
+
type: "verification.completed",
|
|
1738
|
+
timestamp: new Date().toISOString(),
|
|
1739
|
+
payload: { taskId, passed, evidenceId: evidence.id }
|
|
1740
|
+
});
|
|
1741
|
+
if (!event.success)
|
|
1742
|
+
return event;
|
|
1743
|
+
return ok({ passed, checks, evidenceIds });
|
|
1744
|
+
}
|
|
1745
|
+
async function gateTaskCompletion(projectRoot, taskId, evidenceRequired, evidenceIds) {
|
|
1746
|
+
const collected = await collectTaskEvidence(projectRoot, taskId);
|
|
1747
|
+
if (!collected.success)
|
|
1748
|
+
return collected;
|
|
1749
|
+
if (collected.data.invalid > 0)
|
|
1750
|
+
return ok(false);
|
|
1751
|
+
const cited = evidenceIds ? new Set(evidenceIds) : undefined;
|
|
1752
|
+
const hasPassing = (type) => collected.data.records.some((ev) => (!cited || cited.has(ev.id)) && ev.type === type && isPassingEvidence(ev));
|
|
1753
|
+
for (const req of evidenceRequired) {
|
|
1754
|
+
switch (req) {
|
|
1755
|
+
case "acceptance_criteria_met":
|
|
1756
|
+
if (!hasPassing("verification"))
|
|
1757
|
+
return ok(false);
|
|
1758
|
+
break;
|
|
1759
|
+
case "tests_passed":
|
|
1760
|
+
if (!hasPassing("test"))
|
|
1761
|
+
return ok(false);
|
|
1762
|
+
break;
|
|
1763
|
+
case "review_approved":
|
|
1764
|
+
if (!hasPassing("review"))
|
|
1765
|
+
return ok(false);
|
|
1766
|
+
break;
|
|
1767
|
+
default:
|
|
1768
|
+
return ok(false);
|
|
1769
|
+
}
|
|
1770
|
+
}
|
|
1771
|
+
return ok(true);
|
|
1772
|
+
}
|
|
1773
|
+
var TDD_EVIDENCE_SOURCE = "cc verify";
|
|
1774
|
+
var TDD_CAPTURED_BY = "verification-runner";
|
|
1775
|
+
async function captureTddSuiteEvidence(projectRoot, taskId, options) {
|
|
1776
|
+
if (!options.allowCompileCheck && !isAllowlistedTestCommand(options.command)) {
|
|
1777
|
+
return err(new Error("TDD suite command is not on the test allowlist. Re-run with --allow-compile-check to trust it."));
|
|
1778
|
+
}
|
|
1779
|
+
const result = await runCompileCheck({
|
|
1780
|
+
command: options.command,
|
|
1781
|
+
cwd: projectRoot
|
|
1782
|
+
});
|
|
1783
|
+
const suitePassed = result.success && !result.timedOut && result.exitCode === 0;
|
|
1784
|
+
const suiteFailed = !result.timedOut && result.exitCode !== 0;
|
|
1785
|
+
const evidence = {
|
|
1786
|
+
id: `ev-tdd-${taskId}-${Date.now()}`,
|
|
1787
|
+
source: TDD_EVIDENCE_SOURCE,
|
|
1788
|
+
type: "tdd",
|
|
1789
|
+
timestamp: new Date().toISOString(),
|
|
1790
|
+
relatedTask: taskId,
|
|
1791
|
+
confidence: suitePassed || suiteFailed ? 0.9 : 0.3,
|
|
1792
|
+
summary: suitePassed ? "TDD suite passed" : suiteFailed ? "TDD suite failed" : "TDD suite inconclusive",
|
|
1793
|
+
data: {
|
|
1794
|
+
capturedBy: TDD_CAPTURED_BY,
|
|
1795
|
+
suiteFailed,
|
|
1796
|
+
suitePassed,
|
|
1797
|
+
exitCode: result.exitCode,
|
|
1798
|
+
timedOut: result.timedOut,
|
|
1799
|
+
command: options.command
|
|
1800
|
+
}
|
|
1801
|
+
};
|
|
1802
|
+
const persisted = await persistEvidence(projectRoot, evidence);
|
|
1803
|
+
if (!persisted.success)
|
|
1804
|
+
return persisted;
|
|
1805
|
+
const event = await appendEvent(projectRoot, {
|
|
1806
|
+
type: "verification.completed",
|
|
1807
|
+
timestamp: new Date().toISOString(),
|
|
1808
|
+
payload: {
|
|
1809
|
+
taskId,
|
|
1810
|
+
tdd: true,
|
|
1811
|
+
suiteFailed,
|
|
1812
|
+
suitePassed,
|
|
1813
|
+
evidenceId: evidence.id
|
|
1814
|
+
}
|
|
1815
|
+
});
|
|
1816
|
+
if (!event.success)
|
|
1817
|
+
return event;
|
|
1818
|
+
return ok({
|
|
1819
|
+
evidenceId: evidence.id,
|
|
1820
|
+
suiteFailed,
|
|
1821
|
+
suitePassed
|
|
1822
|
+
});
|
|
1823
|
+
}
|
|
1824
|
+
async function loadTddSuiteEvidence(projectRoot, taskId, evidenceId) {
|
|
1825
|
+
const evDir = evidenceDir(projectRoot);
|
|
1826
|
+
const path = evidenceFilePath(evDir, evidenceId);
|
|
1827
|
+
if (!path.success)
|
|
1828
|
+
return path;
|
|
1829
|
+
let raw;
|
|
1830
|
+
try {
|
|
1831
|
+
raw = await readFile6(path.data, "utf-8");
|
|
1832
|
+
} catch (e) {
|
|
1833
|
+
return err(e instanceof Error ? e : new Error(String(e)));
|
|
1834
|
+
}
|
|
1835
|
+
let ev;
|
|
1836
|
+
try {
|
|
1837
|
+
ev = EvidenceSchema.parse(JSON.parse(raw));
|
|
1838
|
+
} catch {
|
|
1839
|
+
return err(new Error(`Evidence "${evidenceId}" is not valid TDD evidence`));
|
|
1840
|
+
}
|
|
1841
|
+
if (ev.relatedTask !== taskId) {
|
|
1842
|
+
return err(new Error(`Evidence "${evidenceId}" is not a record of task ${taskId}`));
|
|
1843
|
+
}
|
|
1844
|
+
if (ev.type !== "tdd" || ev.source !== TDD_EVIDENCE_SOURCE) {
|
|
1845
|
+
return err(new Error(`Evidence "${evidenceId}" was not captured by the verification runner`));
|
|
1846
|
+
}
|
|
1847
|
+
const capturedBy = ev.data?.capturedBy;
|
|
1848
|
+
const suiteFailed = ev.data?.suiteFailed;
|
|
1849
|
+
const suitePassed = ev.data?.suitePassed;
|
|
1850
|
+
if (capturedBy !== TDD_CAPTURED_BY || typeof suiteFailed !== "boolean" || typeof suitePassed !== "boolean") {
|
|
1851
|
+
return err(new Error(`Evidence "${evidenceId}" was not captured by the verification runner`));
|
|
1852
|
+
}
|
|
1853
|
+
return ok({ capturedBy, suiteFailed, suitePassed });
|
|
1854
|
+
}
|
|
1855
|
+
|
|
1856
|
+
// src/core/orchestrator/runtime-orchestrator.ts
|
|
1857
|
+
async function rollbackTaskStatus(projectRoot, graph, task, previousStatus, previousState, cause) {
|
|
1858
|
+
task.status = previousStatus;
|
|
1859
|
+
const write = await writeGoal(projectRoot, graph);
|
|
1860
|
+
const restored = write.success ? await saveOperationalState(projectRoot, previousState) : write;
|
|
1861
|
+
return restored.success ? err(cause) : err(new Error(`${cause.message} (rollback failed: ${restored.error.message})`));
|
|
1862
|
+
}
|
|
1863
|
+
function getReadyTasks(graph) {
|
|
1864
|
+
const done = new Set(graph.tasks.filter((t) => t.status === "done").map((t) => t.id));
|
|
1865
|
+
const blocked = new Set(graph.tasks.filter((t) => t.status === "blocked").map((t) => t.id));
|
|
1866
|
+
return graph.tasks.filter((task) => {
|
|
1867
|
+
if (task.status !== "pending")
|
|
1868
|
+
return false;
|
|
1869
|
+
if (blocked.has(task.id))
|
|
1870
|
+
return false;
|
|
1871
|
+
const deps = task.depends_on ?? [];
|
|
1872
|
+
return deps.every((d) => done.has(d));
|
|
1873
|
+
});
|
|
1874
|
+
}
|
|
1875
|
+
function goalTaskToCanonicalCard(task, objective) {
|
|
1876
|
+
return {
|
|
1877
|
+
id: task.id,
|
|
1878
|
+
title: task.title,
|
|
1879
|
+
objective,
|
|
1880
|
+
context: `Task from goal graph: ${task.title}`,
|
|
1881
|
+
acceptanceCriteria: task.acceptance_criteria,
|
|
1882
|
+
dependencies: task.depends_on ?? [],
|
|
1883
|
+
constraints: [],
|
|
1884
|
+
risk: task.risk,
|
|
1885
|
+
targetFiles: task.targetFiles ?? [],
|
|
1886
|
+
agentType: task.agentType ?? "implementer",
|
|
1887
|
+
evidenceRequired: task.evidenceRequired ?? ["acceptance_criteria_met"],
|
|
1888
|
+
status: task.status === "in-progress" ? "in-progress" : task.status === "done" ? "done" : task.status === "blocked" ? "blocked" : "ready",
|
|
1889
|
+
type: task.type,
|
|
1890
|
+
linkedCapabilities: [],
|
|
1891
|
+
boundaries: []
|
|
1892
|
+
};
|
|
1893
|
+
}
|
|
1894
|
+
function buildTaskEnvelope(card, projectRoot, projectName) {
|
|
1895
|
+
const command = card.type === "fix" ? "fix" : card.type === "refactor" ? "refactor" : card.type === "test" ? "test-plan" : "feature";
|
|
1896
|
+
return {
|
|
1897
|
+
protocolVersion: "ccep-1",
|
|
1898
|
+
command,
|
|
1899
|
+
userRequest: `${card.title}: ${card.objective}`,
|
|
1900
|
+
projectId: projectName,
|
|
1901
|
+
repoContext: {
|
|
1902
|
+
stack: [],
|
|
1903
|
+
existingModules: card.targetFiles,
|
|
1904
|
+
domain: card.agentType
|
|
1905
|
+
},
|
|
1906
|
+
constraints: {
|
|
1907
|
+
outputFormat: "taskcard",
|
|
1908
|
+
needConfirmation: card.risk === "high",
|
|
1909
|
+
riskThreshold: card.risk
|
|
1910
|
+
},
|
|
1911
|
+
executionPolicy: {
|
|
1912
|
+
modelMode: "structured",
|
|
1913
|
+
maxVariance: "low"
|
|
1914
|
+
}
|
|
1915
|
+
};
|
|
1916
|
+
}
|
|
1917
|
+
async function getNextTask(projectRoot, projectName) {
|
|
1918
|
+
const goalResult = await loadGoal(projectRoot);
|
|
1919
|
+
if (!goalResult.success)
|
|
1920
|
+
return goalResult;
|
|
1921
|
+
const graphResult = await loadGraph(projectRoot);
|
|
1922
|
+
const productGraph = graphResult.success ? graphResult.data : undefined;
|
|
1923
|
+
const enriched = enrichGoalWithProduct(goalResult.data, productGraph);
|
|
1924
|
+
const ready = getReadyTasks(enriched);
|
|
1925
|
+
if (ready.length === 0) {
|
|
1926
|
+
return err(new Error("No ready tasks. All pending tasks have unmet dependencies or are blocked."));
|
|
1927
|
+
}
|
|
1928
|
+
const task = ready[0];
|
|
1929
|
+
const enrichedTask = enriched.enrichedTasks.find((t) => t.id === task.id);
|
|
1930
|
+
const card = goalTaskToCanonicalCard(enrichedTask, enriched.objective);
|
|
1931
|
+
const envelope = buildTaskEnvelope(card, projectRoot, projectName);
|
|
1932
|
+
return ok({
|
|
1933
|
+
task: card,
|
|
1934
|
+
envelope,
|
|
1935
|
+
readyCount: ready.length
|
|
1936
|
+
});
|
|
1937
|
+
}
|
|
1938
|
+
async function startTask(projectRoot, taskId, agent) {
|
|
1939
|
+
const goalResult = await loadGoal(projectRoot);
|
|
1940
|
+
if (!goalResult.success)
|
|
1941
|
+
return goalResult;
|
|
1942
|
+
const task = goalResult.data.tasks.find((t) => t.id === taskId);
|
|
1943
|
+
if (!task)
|
|
1944
|
+
return err(new Error(`Task ${taskId} not found`));
|
|
1945
|
+
if (task.status !== "pending") {
|
|
1946
|
+
return err(new Error(`Task ${taskId} is ${task.status}, expected pending`));
|
|
1947
|
+
}
|
|
1948
|
+
const stateBefore = await loadOperationalState(projectRoot);
|
|
1949
|
+
if (!stateBefore.success)
|
|
1950
|
+
return stateBefore;
|
|
1951
|
+
const previousState = stateBefore.data;
|
|
1952
|
+
const previousStatus = task.status;
|
|
1953
|
+
task.status = "in-progress";
|
|
1954
|
+
const write = await writeGoal(projectRoot, goalResult.data);
|
|
1955
|
+
if (!write.success)
|
|
1956
|
+
return write;
|
|
1957
|
+
const active = await setActiveTask(projectRoot, taskId, agent);
|
|
1958
|
+
if (!active.success) {
|
|
1959
|
+
return rollbackTaskStatus(projectRoot, goalResult.data, task, previousStatus, previousState, active.error);
|
|
1960
|
+
}
|
|
1961
|
+
const event = await appendEvent(projectRoot, {
|
|
1962
|
+
type: "task.started",
|
|
1963
|
+
timestamp: new Date().toISOString(),
|
|
1964
|
+
payload: { taskId, agent }
|
|
1965
|
+
});
|
|
1966
|
+
if (!event.success) {
|
|
1967
|
+
return rollbackTaskStatus(projectRoot, goalResult.data, task, previousStatus, previousState, event.error);
|
|
1968
|
+
}
|
|
1969
|
+
return ok(undefined);
|
|
1970
|
+
}
|
|
1971
|
+
async function completeTask(projectRoot, taskId, evidenceIds) {
|
|
1972
|
+
const goalResult = await loadGoal(projectRoot);
|
|
1973
|
+
if (!goalResult.success)
|
|
1974
|
+
return goalResult;
|
|
1975
|
+
const task = goalResult.data.tasks.find((t) => t.id === taskId);
|
|
1976
|
+
if (!task)
|
|
1977
|
+
return err(new Error(`Task ${taskId} not found`));
|
|
1978
|
+
if (task.status !== "in-progress") {
|
|
1979
|
+
return err(new Error(`Task ${taskId} is ${task.status}, expected in-progress`));
|
|
1980
|
+
}
|
|
1981
|
+
const done = new Set(goalResult.data.tasks.filter((t) => t.status === "done").map((t) => t.id));
|
|
1982
|
+
const unmet = (task.depends_on ?? []).filter((d) => !done.has(d));
|
|
1983
|
+
if (unmet.length > 0) {
|
|
1984
|
+
return err(new Error(`Task ${taskId} has unmet dependencies: ${unmet.join(", ")}`));
|
|
1985
|
+
}
|
|
1986
|
+
const activeState = await loadOperationalState(projectRoot);
|
|
1987
|
+
if (!activeState.success)
|
|
1988
|
+
return activeState;
|
|
1989
|
+
if (!activeState.data.activeTaskIds.includes(taskId)) {
|
|
1990
|
+
return err(new Error(`Task ${taskId} is not active. Start it before completing it.`));
|
|
1991
|
+
}
|
|
1992
|
+
if (!evidenceIds || evidenceIds.length === 0) {
|
|
1993
|
+
return err(new Error(`Task ${taskId} cannot be completed without verification evidence`));
|
|
1994
|
+
}
|
|
1995
|
+
const evidence = await validateEvidenceIds(projectRoot, taskId, evidenceIds);
|
|
1996
|
+
if (!evidence.success)
|
|
1997
|
+
return evidence;
|
|
1998
|
+
const gate = await gateTaskCompletion(projectRoot, taskId, inferEvidenceRequired(task), evidenceIds);
|
|
1999
|
+
if (!gate.success)
|
|
2000
|
+
return gate;
|
|
2001
|
+
if (!gate.data) {
|
|
2002
|
+
return err(new Error(`Task ${taskId} does not satisfy its completion evidence requirements`));
|
|
2003
|
+
}
|
|
2004
|
+
const previousState = activeState.data;
|
|
2005
|
+
const previousStatus = task.status;
|
|
2006
|
+
task.status = "done";
|
|
2007
|
+
const write = await writeGoal(projectRoot, goalResult.data);
|
|
2008
|
+
if (!write.success)
|
|
2009
|
+
return write;
|
|
2010
|
+
const cleared = await clearActiveTask(projectRoot, taskId);
|
|
2011
|
+
if (!cleared.success) {
|
|
2012
|
+
return rollbackTaskStatus(projectRoot, goalResult.data, task, previousStatus, previousState, cleared.error);
|
|
2013
|
+
}
|
|
2014
|
+
const event = await appendEvent(projectRoot, {
|
|
2015
|
+
type: "task.completed",
|
|
2016
|
+
timestamp: new Date().toISOString(),
|
|
2017
|
+
payload: { taskId, evidenceIds }
|
|
2018
|
+
});
|
|
2019
|
+
if (!event.success) {
|
|
2020
|
+
return rollbackTaskStatus(projectRoot, goalResult.data, task, previousStatus, previousState, event.error);
|
|
2021
|
+
}
|
|
2022
|
+
return ok(undefined);
|
|
2023
|
+
}
|
|
2024
|
+
function formatGoalStatus(graph) {
|
|
2025
|
+
const lines = [`Objective: ${graph.objective}`, ""];
|
|
2026
|
+
for (const task of graph.tasks) {
|
|
2027
|
+
const icon = task.status === "done" ? "✓" : task.status === "blocked" ? "✗" : task.status === "in-progress" ? "→" : "○";
|
|
2028
|
+
const deps = task.depends_on?.length ? ` (deps: ${task.depends_on.join(", ")})` : "";
|
|
2029
|
+
lines.push(`${icon} [${task.status}] ${task.id}: ${task.title}${deps}`);
|
|
2030
|
+
}
|
|
2031
|
+
return lines.join(`
|
|
2032
|
+
`);
|
|
2033
|
+
}
|
|
2034
|
+
// src/domain/loop/loop-state.ts
|
|
2035
|
+
function createInitialState(overrides) {
|
|
2036
|
+
return {
|
|
2037
|
+
phase: "IDLE",
|
|
2038
|
+
iteration: 0,
|
|
2039
|
+
maxIterations: 3,
|
|
2040
|
+
errors: [],
|
|
2041
|
+
errorHistory: [],
|
|
2042
|
+
tokenBudgetUsed: 0,
|
|
2043
|
+
maxTokenBudget: 0,
|
|
2044
|
+
...overrides
|
|
2045
|
+
};
|
|
2046
|
+
}
|
|
2047
|
+
function errorsEqual(a, b) {
|
|
2048
|
+
if (a.length !== b.length)
|
|
2049
|
+
return false;
|
|
2050
|
+
return a.every((ea, i) => ea.file === b[i].file && ea.code === b[i].code && ea.message === b[i].message && ea.line === b[i].line && ea.column === b[i].column);
|
|
2051
|
+
}
|
|
2052
|
+
function isStuckLoop(errorHistory) {
|
|
2053
|
+
if (errorHistory.length < 2)
|
|
2054
|
+
return false;
|
|
2055
|
+
const last = errorHistory[errorHistory.length - 1];
|
|
2056
|
+
const prev = errorHistory[errorHistory.length - 2];
|
|
2057
|
+
return errorsEqual(last, prev);
|
|
2058
|
+
}
|
|
2059
|
+
var VALID_TRANSITIONS = {
|
|
2060
|
+
IDLE: ["START", "ABORT"],
|
|
2061
|
+
RUNNING: ["CODE_GENERATED", "TOKEN_BUDGET_EXCEEDED", "ABORT"],
|
|
2062
|
+
CHECKING: ["COMPILE_CHECK_COMPLETED", "ABORT"],
|
|
2063
|
+
FEEDBACK: ["FEEDBACK_FORMATTED", "ABORT"],
|
|
2064
|
+
DONE: [],
|
|
2065
|
+
FAILED: [],
|
|
2066
|
+
ESCALATED: []
|
|
2067
|
+
};
|
|
2068
|
+
function loopStateMachine(state, action) {
|
|
2069
|
+
if (action.type === "ABORT") {
|
|
2070
|
+
if (state.phase === "DONE" || state.phase === "FAILED" || state.phase === "ESCALATED") {
|
|
2071
|
+
return { state, result: "TERMINATE" };
|
|
2072
|
+
}
|
|
2073
|
+
return {
|
|
2074
|
+
state: { ...state, phase: "FAILED" },
|
|
2075
|
+
result: "TERMINATE"
|
|
2076
|
+
};
|
|
2077
|
+
}
|
|
2078
|
+
if (state.phase === "DONE" || state.phase === "FAILED" || state.phase === "ESCALATED") {
|
|
2079
|
+
return { state, result: "TERMINATE" };
|
|
2080
|
+
}
|
|
2081
|
+
const allowed = VALID_TRANSITIONS[state.phase];
|
|
2082
|
+
if (!allowed || !allowed.includes(action.type)) {
|
|
2083
|
+
return { state, result: "TERMINATE" };
|
|
2084
|
+
}
|
|
2085
|
+
switch (state.phase) {
|
|
2086
|
+
case "IDLE": {
|
|
2087
|
+
if (action.type === "START") {
|
|
2088
|
+
return {
|
|
2089
|
+
state: { ...state, phase: "RUNNING", iteration: 1 },
|
|
2090
|
+
result: "CONTINUE"
|
|
2091
|
+
};
|
|
2092
|
+
}
|
|
2093
|
+
break;
|
|
2094
|
+
}
|
|
2095
|
+
case "RUNNING": {
|
|
2096
|
+
if (action.type === "CODE_GENERATED") {
|
|
2097
|
+
return {
|
|
2098
|
+
state: { ...state, phase: "CHECKING" },
|
|
2099
|
+
result: "CONTINUE"
|
|
2100
|
+
};
|
|
2101
|
+
}
|
|
2102
|
+
if (action.type === "TOKEN_BUDGET_EXCEEDED") {
|
|
2103
|
+
return {
|
|
2104
|
+
state: {
|
|
2105
|
+
...state,
|
|
2106
|
+
phase: "ESCALATED",
|
|
2107
|
+
tokenBudgetUsed: action.tokenUsage
|
|
2108
|
+
},
|
|
2109
|
+
result: "TERMINATE"
|
|
2110
|
+
};
|
|
2111
|
+
}
|
|
2112
|
+
break;
|
|
2113
|
+
}
|
|
2114
|
+
case "CHECKING": {
|
|
2115
|
+
if (action.type === "COMPILE_CHECK_COMPLETED") {
|
|
2116
|
+
const errors = action.errors;
|
|
2117
|
+
if (errors.length === 0) {
|
|
2118
|
+
return {
|
|
2119
|
+
state: {
|
|
2120
|
+
...state,
|
|
2121
|
+
phase: "DONE",
|
|
2122
|
+
errors: [],
|
|
2123
|
+
errorHistory: [...state.errorHistory, []]
|
|
2124
|
+
},
|
|
2125
|
+
result: "TERMINATE"
|
|
2126
|
+
};
|
|
2127
|
+
}
|
|
2128
|
+
const newHistory = [...state.errorHistory, errors];
|
|
2129
|
+
if (isStuckLoop(newHistory)) {
|
|
2130
|
+
return {
|
|
2131
|
+
state: {
|
|
2132
|
+
...state,
|
|
2133
|
+
phase: "ESCALATED",
|
|
2134
|
+
errors,
|
|
2135
|
+
errorHistory: newHistory
|
|
2136
|
+
},
|
|
2137
|
+
result: "TERMINATE"
|
|
2138
|
+
};
|
|
2139
|
+
}
|
|
2140
|
+
if (state.iteration >= state.maxIterations) {
|
|
2141
|
+
return {
|
|
2142
|
+
state: {
|
|
2143
|
+
...state,
|
|
2144
|
+
phase: "ESCALATED",
|
|
2145
|
+
errors,
|
|
2146
|
+
errorHistory: newHistory
|
|
2147
|
+
},
|
|
2148
|
+
result: "TERMINATE"
|
|
2149
|
+
};
|
|
2150
|
+
}
|
|
2151
|
+
return {
|
|
2152
|
+
state: {
|
|
2153
|
+
...state,
|
|
2154
|
+
phase: "FEEDBACK",
|
|
2155
|
+
errors,
|
|
2156
|
+
errorHistory: newHistory
|
|
2157
|
+
},
|
|
2158
|
+
result: "CONTINUE"
|
|
2159
|
+
};
|
|
2160
|
+
}
|
|
2161
|
+
break;
|
|
2162
|
+
}
|
|
2163
|
+
case "FEEDBACK": {
|
|
2164
|
+
if (action.type === "FEEDBACK_FORMATTED") {
|
|
2165
|
+
return {
|
|
2166
|
+
state: {
|
|
2167
|
+
...state,
|
|
2168
|
+
phase: "RUNNING",
|
|
2169
|
+
iteration: state.iteration + 1
|
|
2170
|
+
},
|
|
2171
|
+
result: "CONTINUE"
|
|
2172
|
+
};
|
|
2173
|
+
}
|
|
2174
|
+
break;
|
|
2175
|
+
}
|
|
2176
|
+
}
|
|
2177
|
+
return { state, result: "TERMINATE" };
|
|
2178
|
+
}
|
|
2179
|
+
function createInitialTddState() {
|
|
2180
|
+
return { phase: "RED", evidenceIds: [] };
|
|
2181
|
+
}
|
|
2182
|
+
function isRunnerTddEvidence(evidence) {
|
|
2183
|
+
return evidence.capturedBy === "verification-runner";
|
|
2184
|
+
}
|
|
2185
|
+
function tddCycleStateMachine(state, action) {
|
|
2186
|
+
if (action.type === "ABORT") {
|
|
2187
|
+
if (state.phase === "FAILED") {
|
|
2188
|
+
return { state, result: "TERMINATE" };
|
|
2189
|
+
}
|
|
2190
|
+
return { state: { ...state, phase: "FAILED" }, result: "TERMINATE" };
|
|
2191
|
+
}
|
|
2192
|
+
if (state.phase === "FAILED" || state.phase === "REFACTOR") {
|
|
2193
|
+
return { state, result: "TERMINATE" };
|
|
2194
|
+
}
|
|
2195
|
+
if (!isRunnerTddEvidence(action.evidence)) {
|
|
2196
|
+
return { state, result: "TERMINATE" };
|
|
2197
|
+
}
|
|
2198
|
+
if (state.phase === "RED") {
|
|
2199
|
+
if (action.evidence.suiteFailed && !action.evidence.suitePassed) {
|
|
2200
|
+
return {
|
|
2201
|
+
state: {
|
|
2202
|
+
phase: "GREEN",
|
|
2203
|
+
evidenceIds: [...state.evidenceIds, action.evidenceId]
|
|
2204
|
+
},
|
|
2205
|
+
result: "CONTINUE"
|
|
2206
|
+
};
|
|
2207
|
+
}
|
|
2208
|
+
return { state, result: "TERMINATE" };
|
|
2209
|
+
}
|
|
2210
|
+
if (state.phase === "GREEN") {
|
|
2211
|
+
if (action.evidence.suitePassed && !action.evidence.suiteFailed) {
|
|
2212
|
+
return {
|
|
2213
|
+
state: {
|
|
2214
|
+
phase: "REFACTOR",
|
|
2215
|
+
evidenceIds: [...state.evidenceIds, action.evidenceId]
|
|
2216
|
+
},
|
|
2217
|
+
result: "CONTINUE"
|
|
2218
|
+
};
|
|
2219
|
+
}
|
|
2220
|
+
return { state, result: "TERMINATE" };
|
|
2221
|
+
}
|
|
2222
|
+
return { state, result: "TERMINATE" };
|
|
2223
|
+
}
|
|
2224
|
+
|
|
2225
|
+
// src/core/loop/git-stats.ts
|
|
2226
|
+
import { execFile } from "node:child_process";
|
|
2227
|
+
import { promisify } from "node:util";
|
|
2228
|
+
var execFileAsync = promisify(execFile);
|
|
2229
|
+
var GIT_STATS_CACHE_TTL_MS = 3000;
|
|
2230
|
+
var cache;
|
|
2231
|
+
function countPorcelain(output) {
|
|
2232
|
+
return output.split(`
|
|
2233
|
+
`).filter((line) => line.trim().length > 0).length;
|
|
2234
|
+
}
|
|
2235
|
+
function countNumstat(output) {
|
|
2236
|
+
let total = 0;
|
|
2237
|
+
for (const line of output.split(`
|
|
2238
|
+
`)) {
|
|
2239
|
+
if (!line.trim())
|
|
2240
|
+
continue;
|
|
2241
|
+
const parts = line.split(/\s+/);
|
|
2242
|
+
const added = parseInt(parts[0] || "0", 10);
|
|
2243
|
+
const deleted = parseInt(parts[1] || "0", 10);
|
|
2244
|
+
if (!Number.isNaN(added))
|
|
2245
|
+
total += added;
|
|
2246
|
+
if (!Number.isNaN(deleted))
|
|
2247
|
+
total += deleted;
|
|
2248
|
+
}
|
|
2249
|
+
return total;
|
|
2250
|
+
}
|
|
2251
|
+
async function fetchGitChangeStats(cwd) {
|
|
2252
|
+
try {
|
|
2253
|
+
const [status, diff] = await Promise.all([
|
|
2254
|
+
execFileAsync("git", ["status", "--porcelain"], {
|
|
2255
|
+
cwd,
|
|
2256
|
+
encoding: "utf-8",
|
|
2257
|
+
timeout: 15000
|
|
2258
|
+
}),
|
|
2259
|
+
execFileAsync("git", ["diff", "--numstat"], {
|
|
2260
|
+
cwd,
|
|
2261
|
+
encoding: "utf-8",
|
|
2262
|
+
timeout: 15000
|
|
2263
|
+
})
|
|
2264
|
+
]);
|
|
2265
|
+
return {
|
|
2266
|
+
filesModified: countPorcelain(status.stdout),
|
|
2267
|
+
linesChanged: countNumstat(diff.stdout)
|
|
2268
|
+
};
|
|
2269
|
+
} catch {
|
|
2270
|
+
return { filesModified: 0, linesChanged: 0 };
|
|
2271
|
+
}
|
|
2272
|
+
}
|
|
2273
|
+
async function readGitChangeStats(cwd, options) {
|
|
2274
|
+
const now = options?.now ?? Date.now();
|
|
2275
|
+
const fetch = options?.fetch ?? fetchGitChangeStats;
|
|
2276
|
+
if (cache && cache.cwd === cwd && now - cache.at < GIT_STATS_CACHE_TTL_MS) {
|
|
2277
|
+
return cache.stats;
|
|
2278
|
+
}
|
|
2279
|
+
const stats = await fetch(cwd);
|
|
2280
|
+
cache = { cwd, at: now, stats };
|
|
2281
|
+
return stats;
|
|
2282
|
+
}
|
|
2283
|
+
|
|
2284
|
+
// src/core/loop/loop-engine.ts
|
|
2285
|
+
class LoopEngine {
|
|
2286
|
+
limits;
|
|
2287
|
+
startedAt;
|
|
2288
|
+
constructor(limits, gitStats, startedAt = Date.now()) {
|
|
2289
|
+
this.limits = limits;
|
|
2290
|
+
this.gitStats = gitStats ?? ((cwd) => readGitChangeStats(cwd));
|
|
2291
|
+
this.startedAt = startedAt;
|
|
2292
|
+
}
|
|
2293
|
+
gitStats;
|
|
2294
|
+
async evaluate(scope = "all") {
|
|
2295
|
+
const maxWall = this.limits.maxWallClockSeconds ?? 0;
|
|
2296
|
+
if (maxWall > 0) {
|
|
2297
|
+
const elapsedSeconds = (Date.now() - this.startedAt) / 1000;
|
|
2298
|
+
if (elapsedSeconds > maxWall) {
|
|
2299
|
+
return { kind: "timeout", elapsedSeconds, limit: maxWall };
|
|
2300
|
+
}
|
|
2301
|
+
}
|
|
2302
|
+
if (scope === "time")
|
|
2303
|
+
return null;
|
|
2304
|
+
const maxFiles = this.limits.maxFilesModified ?? 0;
|
|
2305
|
+
const maxLines = this.limits.maxLinesChanged ?? 0;
|
|
2306
|
+
if (maxFiles <= 0 && maxLines <= 0)
|
|
2307
|
+
return null;
|
|
2308
|
+
const stats = await this.gitStats(this.limits.cwd ?? process.cwd());
|
|
2309
|
+
if (maxFiles > 0 && stats.filesModified > maxFiles) {
|
|
2310
|
+
return { kind: "files", count: stats.filesModified, limit: maxFiles };
|
|
2311
|
+
}
|
|
2312
|
+
if (maxLines > 0 && stats.linesChanged > maxLines) {
|
|
2313
|
+
return { kind: "lines", count: stats.linesChanged, limit: maxLines };
|
|
2314
|
+
}
|
|
2315
|
+
return null;
|
|
2316
|
+
}
|
|
2317
|
+
}
|
|
2318
|
+
function formatFeedback(errors) {
|
|
2319
|
+
if (errors.length === 0)
|
|
2320
|
+
return "";
|
|
2321
|
+
const lines = [
|
|
2322
|
+
`The previous code generation produced ${errors.length} compilation error(s).`,
|
|
2323
|
+
"Please fix the following issues:",
|
|
2324
|
+
""
|
|
2325
|
+
];
|
|
2326
|
+
for (let i = 0;i < errors.length; i++) {
|
|
2327
|
+
const err3 = errors[i];
|
|
2328
|
+
const location = [err3.file, err3.line, err3.column].filter(Boolean).join(":");
|
|
2329
|
+
const codePart = err3.code ? ` [${err3.code}]` : "";
|
|
2330
|
+
lines.push(`${i + 1}. ${location}${codePart}: ${err3.message}`);
|
|
2331
|
+
lines.push(` Raw: ${err3.raw}`);
|
|
2332
|
+
lines.push("");
|
|
2333
|
+
}
|
|
2334
|
+
lines.push("Generate corrected code that resolves all errors above.");
|
|
2335
|
+
return lines.join(`
|
|
2336
|
+
`);
|
|
2337
|
+
}
|
|
2338
|
+
function logTransition(phase, action, iteration) {
|
|
2339
|
+
process.stderr.write(`[loop] ${new Date().toISOString()} phase=${phase} action=${action} iteration=${iteration}
|
|
2340
|
+
`);
|
|
2341
|
+
}
|
|
2342
|
+
async function runLoop(generateFn, compileCheckFn, config = {}, taskTitle = "compile-fix-loop", originalTask) {
|
|
2343
|
+
const maxIterations = config.maxIterations ?? 3;
|
|
2344
|
+
const maxTokenBudget = config.maxTokenBudget ?? 0;
|
|
2345
|
+
const engine = new LoopEngine({
|
|
2346
|
+
maxWallClockSeconds: config.maxWallClockSeconds ?? 0,
|
|
2347
|
+
maxFilesModified: config.maxFilesModified ?? 0,
|
|
2348
|
+
maxLinesChanged: config.maxLinesChanged ?? 0,
|
|
2349
|
+
cwd: config.cwd
|
|
2350
|
+
}, config.gitStats);
|
|
2351
|
+
let state = createInitialState({ maxIterations, maxTokenBudget });
|
|
2352
|
+
let totalErrors = 0;
|
|
2353
|
+
let feedbackText;
|
|
2354
|
+
let compileCheck;
|
|
2355
|
+
let compileCheckSkipReason;
|
|
2356
|
+
logTransition(state.phase, "INIT", state.iteration);
|
|
2357
|
+
const startResult = loopStateMachine(state, { type: "START" });
|
|
2358
|
+
state = startResult.state;
|
|
2359
|
+
logTransition(state.phase, "START", state.iteration);
|
|
2360
|
+
while (true) {
|
|
2361
|
+
const hit = await engine.evaluate();
|
|
2362
|
+
if (hit) {
|
|
2363
|
+
return guardrailResult(hit, state, totalErrors, taskTitle, originalTask);
|
|
2364
|
+
}
|
|
2365
|
+
switch (state.phase) {
|
|
2366
|
+
case "RUNNING": {
|
|
2367
|
+
logTransition(state.phase, "GENERATE", state.iteration);
|
|
2368
|
+
const genResult2 = await generateFn(feedbackText);
|
|
2369
|
+
feedbackText = undefined;
|
|
2370
|
+
const tokenUsage = genResult2 && typeof genResult2 === "object" && "tokenUsage" in genResult2 ? genResult2.tokenUsage : 0;
|
|
2371
|
+
const newBudgetUsed = state.tokenBudgetUsed + tokenUsage;
|
|
2372
|
+
if (state.maxTokenBudget > 0 && newBudgetUsed > state.maxTokenBudget) {
|
|
2373
|
+
const budgetResult = loopStateMachine(state, {
|
|
2374
|
+
type: "TOKEN_BUDGET_EXCEEDED",
|
|
2375
|
+
tokenUsage: newBudgetUsed
|
|
2376
|
+
});
|
|
2377
|
+
state = budgetResult.state;
|
|
2378
|
+
logTransition(state.phase, "TOKEN_BUDGET_EXCEEDED", state.iteration);
|
|
2379
|
+
break;
|
|
2380
|
+
}
|
|
2381
|
+
const updatedState = { ...state, tokenBudgetUsed: newBudgetUsed };
|
|
2382
|
+
const genResult = loopStateMachine(updatedState, { type: "CODE_GENERATED" });
|
|
2383
|
+
state = genResult.state;
|
|
2384
|
+
logTransition(state.phase, "CODE_GENERATED", state.iteration);
|
|
2385
|
+
break;
|
|
2386
|
+
}
|
|
2387
|
+
case "CHECKING": {
|
|
2388
|
+
logTransition(state.phase, "COMPILE_CHECK", state.iteration);
|
|
2389
|
+
const compileResult = await compileCheckFn();
|
|
2390
|
+
totalErrors += compileResult.errors.length;
|
|
2391
|
+
if (compileResult.skipped) {
|
|
2392
|
+
compileCheck = "skipped";
|
|
2393
|
+
compileCheckSkipReason = compileResult.skipReason;
|
|
2394
|
+
} else {
|
|
2395
|
+
compileCheck = "ran";
|
|
2396
|
+
}
|
|
2397
|
+
const checkResult = loopStateMachine(state, {
|
|
2398
|
+
type: "COMPILE_CHECK_COMPLETED",
|
|
2399
|
+
errors: compileResult.errors
|
|
2400
|
+
});
|
|
2401
|
+
state = checkResult.state;
|
|
2402
|
+
logTransition(state.phase, "COMPILE_CHECK_COMPLETED", state.iteration);
|
|
2403
|
+
break;
|
|
2404
|
+
}
|
|
2405
|
+
case "FEEDBACK": {
|
|
2406
|
+
logTransition(state.phase, "FORMAT_FEEDBACK", state.iteration);
|
|
2407
|
+
feedbackText = formatFeedback(state.errors);
|
|
2408
|
+
const fbResult = loopStateMachine(state, { type: "FEEDBACK_FORMATTED" });
|
|
2409
|
+
state = fbResult.state;
|
|
2410
|
+
logTransition(state.phase, "FEEDBACK_FORMATTED", state.iteration);
|
|
2411
|
+
break;
|
|
2412
|
+
}
|
|
2413
|
+
case "DONE": {
|
|
2414
|
+
logTransition(state.phase, "DONE", state.iteration);
|
|
2415
|
+
return {
|
|
2416
|
+
success: true,
|
|
2417
|
+
iterations: state.iteration,
|
|
2418
|
+
totalErrors,
|
|
2419
|
+
finalPhase: "DONE",
|
|
2420
|
+
errorHistory: state.errorHistory,
|
|
2421
|
+
compileCheck,
|
|
2422
|
+
compileCheckSkipReason
|
|
2423
|
+
};
|
|
2424
|
+
}
|
|
2425
|
+
case "ESCALATED": {
|
|
2426
|
+
logTransition(state.phase, "ESCALATED", state.iteration);
|
|
2427
|
+
const report = buildEscalationReport(taskTitle, state, originalTask);
|
|
2428
|
+
return {
|
|
2429
|
+
success: false,
|
|
2430
|
+
iterations: state.iteration,
|
|
2431
|
+
totalErrors,
|
|
2432
|
+
finalPhase: "ESCALATED",
|
|
2433
|
+
escalationReport: report,
|
|
2434
|
+
errorHistory: state.errorHistory,
|
|
2435
|
+
compileCheck,
|
|
2436
|
+
compileCheckSkipReason
|
|
2437
|
+
};
|
|
2438
|
+
}
|
|
2439
|
+
case "FAILED": {
|
|
2440
|
+
logTransition(state.phase, "FAILED", state.iteration);
|
|
2441
|
+
return {
|
|
2442
|
+
success: false,
|
|
2443
|
+
iterations: state.iteration,
|
|
2444
|
+
totalErrors,
|
|
2445
|
+
finalPhase: "FAILED",
|
|
2446
|
+
errorHistory: state.errorHistory,
|
|
2447
|
+
compileCheck,
|
|
2448
|
+
compileCheckSkipReason
|
|
2449
|
+
};
|
|
2450
|
+
}
|
|
2451
|
+
default: {
|
|
2452
|
+
logTransition(state.phase, "UNEXPECTED", state.iteration);
|
|
2453
|
+
return {
|
|
2454
|
+
success: false,
|
|
2455
|
+
iterations: state.iteration,
|
|
2456
|
+
totalErrors,
|
|
2457
|
+
finalPhase: state.phase,
|
|
2458
|
+
errorHistory: state.errorHistory,
|
|
2459
|
+
compileCheck,
|
|
2460
|
+
compileCheckSkipReason
|
|
2461
|
+
};
|
|
2462
|
+
}
|
|
2463
|
+
}
|
|
2464
|
+
}
|
|
2465
|
+
}
|
|
2466
|
+
function guardrailResult(hit, state, totalErrors, taskTitle, originalTask) {
|
|
2467
|
+
const attempted = hit.kind === "timeout" ? `Time limit exceeded: ${hit.elapsedSeconds.toFixed(1)}s elapsed (max: ${hit.limit}s)` : hit.kind === "files" ? `Files modified limit exceeded: ${hit.count} files modified (max: ${hit.limit})` : `Lines changed limit exceeded: ${hit.count} lines changed (max: ${hit.limit})`;
|
|
2468
|
+
const recommended = hit.kind === "timeout" ? `Operational guardrail triggered: maxWallClockSeconds limit (${hit.limit}s) exceeded. Increase limit or optimize execution time.` : hit.kind === "files" ? `Operational guardrail triggered: maxFilesModified limit (${hit.limit}) exceeded. Check for scope creep.` : `Operational guardrail triggered: maxLinesChanged limit (${hit.limit}) exceeded. Check for large diffs or unnecessary refactoring.`;
|
|
2469
|
+
const action = hit.kind === "timeout" ? "TIMEOUT_GUARDRAIL" : hit.kind === "files" ? "FILES_MODIFIED_GUARDRAIL" : "LINES_CHANGED_GUARDRAIL";
|
|
2470
|
+
logTransition(state.phase, action, state.iteration);
|
|
2471
|
+
return {
|
|
2472
|
+
success: false,
|
|
2473
|
+
iterations: state.iteration,
|
|
2474
|
+
totalErrors,
|
|
2475
|
+
finalPhase: "ESCALATED",
|
|
2476
|
+
errorHistory: state.errorHistory,
|
|
2477
|
+
escalationReport: {
|
|
2478
|
+
taskTitle,
|
|
2479
|
+
iterationsAttempted: state.iteration,
|
|
2480
|
+
errorHistory: state.errorHistory,
|
|
2481
|
+
attemptedFixes: [attempted],
|
|
2482
|
+
originalContext: originalTask ?? "No original task provided",
|
|
2483
|
+
recommendedAction: recommended
|
|
2484
|
+
}
|
|
2485
|
+
};
|
|
2486
|
+
}
|
|
2487
|
+
function buildEscalationReport(taskTitle, state, originalTask) {
|
|
2488
|
+
const attemptedFixes = [];
|
|
2489
|
+
for (let i = 0;i < state.errorHistory.length; i++) {
|
|
2490
|
+
const errs = state.errorHistory[i];
|
|
2491
|
+
if (errs.length > 0) {
|
|
2492
|
+
attemptedFixes.push(`Iteration ${i + 1}: ${errs.length} error(s) — ${errs.map((e) => `${e.code || "unknown"}: ${e.message}`).join("; ")}`);
|
|
2493
|
+
}
|
|
2494
|
+
}
|
|
2495
|
+
let recommendedAction;
|
|
2496
|
+
if (state.errorHistory.length >= 2) {
|
|
2497
|
+
const last = state.errorHistory[state.errorHistory.length - 1];
|
|
2498
|
+
const prev = state.errorHistory[state.errorHistory.length - 2];
|
|
2499
|
+
const identical = last.length === prev.length && last.every((e, i) => e.file === prev[i].file && e.code === prev[i].code && e.message === prev[i].message);
|
|
2500
|
+
if (identical) {
|
|
2501
|
+
recommendedAction = "Errors are identical across consecutive iterations. The agent appears unable to resolve these errors automatically. Manual intervention required.";
|
|
2502
|
+
} else {
|
|
2503
|
+
recommendedAction = "Max iterations reached with remaining errors. Review the error pattern and consider alternative approaches.";
|
|
2504
|
+
}
|
|
2505
|
+
} else {
|
|
2506
|
+
recommendedAction = "Max iterations reached. Review errors and consider manual fixes.";
|
|
2507
|
+
}
|
|
2508
|
+
return {
|
|
2509
|
+
taskTitle,
|
|
2510
|
+
iterationsAttempted: state.iteration,
|
|
2511
|
+
errorHistory: state.errorHistory,
|
|
2512
|
+
attemptedFixes,
|
|
2513
|
+
originalContext: originalTask ?? "No original task provided",
|
|
2514
|
+
recommendedAction
|
|
2515
|
+
};
|
|
2516
|
+
}
|
|
2517
|
+
var CLEAN_COMPILE = {
|
|
2518
|
+
success: true,
|
|
2519
|
+
exitCode: 0,
|
|
2520
|
+
stdout: "",
|
|
2521
|
+
stderr: "",
|
|
2522
|
+
errors: [],
|
|
2523
|
+
durationMs: 0,
|
|
2524
|
+
timedOut: false
|
|
2525
|
+
};
|
|
2526
|
+
function skippedCompileResult(reason) {
|
|
2527
|
+
return {
|
|
2528
|
+
...CLEAN_COMPILE,
|
|
2529
|
+
skipped: true,
|
|
2530
|
+
skipReason: reason,
|
|
2531
|
+
stderr: `compileCheck: skipped
|
|
2532
|
+
${reason}`
|
|
2533
|
+
};
|
|
2534
|
+
}
|
|
2535
|
+
function shouldRunAgentLoop(type, agentType, phase) {
|
|
2536
|
+
if (phase === "implement" || phase === "test")
|
|
2537
|
+
return true;
|
|
2538
|
+
if (agentType === "implementer" || agentType === "tester")
|
|
2539
|
+
return true;
|
|
2540
|
+
return type === "feature" || type === "fix" || type === "test";
|
|
2541
|
+
}
|
|
2542
|
+
async function advanceTddPhase(projectRoot, taskId, state, evidenceId) {
|
|
2543
|
+
const loaded = await loadTddSuiteEvidence(projectRoot, taskId, evidenceId);
|
|
2544
|
+
if (!loaded.success)
|
|
2545
|
+
return loaded;
|
|
2546
|
+
const next = tddCycleStateMachine(state, {
|
|
2547
|
+
type: "SUITE_EVIDENCE",
|
|
2548
|
+
evidenceId,
|
|
2549
|
+
evidence: loaded.data
|
|
2550
|
+
});
|
|
2551
|
+
return ok(next);
|
|
2552
|
+
}
|
|
2553
|
+
async function runLoopForProject(projectRoot, options) {
|
|
2554
|
+
const configResult = await loadConfig(projectRoot);
|
|
2555
|
+
const loopCfg = configResult.success ? configResult.data.loop : undefined;
|
|
2556
|
+
const compileCheck = configResult.success ? configResult.data.safety.compileCheck : undefined;
|
|
2557
|
+
const compileCheckFn = async () => {
|
|
2558
|
+
if (!compileCheck?.enabled || !compileCheck.command) {
|
|
2559
|
+
return skippedCompileResult(!compileCheck?.enabled ? "Compile check is not enabled in config." : "Compile check is enabled but no command is configured.");
|
|
2560
|
+
}
|
|
2561
|
+
const allowed = options.allowCompileCheck === true || isAllowlistedCompileCommand(compileCheck.command);
|
|
2562
|
+
if (!allowed) {
|
|
2563
|
+
return skippedCompileResult("Compile check not executed: the command is not on the compile allowlist. " + "Re-run with --allow-compile-check to trust it.");
|
|
2564
|
+
}
|
|
2565
|
+
const result = await runCompileCheck({
|
|
2566
|
+
command: compileCheck.command,
|
|
2567
|
+
cwd: projectRoot,
|
|
2568
|
+
timeoutMs: compileCheck.timeoutMs
|
|
2569
|
+
});
|
|
2570
|
+
if (result.success && result.errors.length === 0)
|
|
2571
|
+
return result;
|
|
2572
|
+
return {
|
|
2573
|
+
...result,
|
|
2574
|
+
errors: result.errors.length > 0 ? result.errors : [
|
|
2575
|
+
{
|
|
2576
|
+
file: compileCheck.command,
|
|
2577
|
+
code: "COMPILE",
|
|
2578
|
+
message: `Compile check failed (exit ${result.exitCode})`,
|
|
2579
|
+
raw: result.stderr || result.stdout
|
|
2580
|
+
}
|
|
2581
|
+
]
|
|
2582
|
+
};
|
|
2583
|
+
};
|
|
2584
|
+
return runLoop(async () => ({ tokenUsage: 0 }), compileCheckFn, {
|
|
2585
|
+
cwd: projectRoot,
|
|
2586
|
+
maxIterations: loopCfg?.maxIterations ?? 3,
|
|
2587
|
+
maxTokenBudget: loopCfg?.maxTokenBudget ?? 0
|
|
2588
|
+
}, options.taskTitle, options.originalTask);
|
|
2589
|
+
}
|
|
2590
|
+
|
|
2591
|
+
// src/index.ts
|
|
2592
|
+
init_schemas();
|
|
2593
|
+
export {
|
|
2594
|
+
validateWorkflowProfile,
|
|
2595
|
+
validateTaskOutcome,
|
|
2596
|
+
validateScorecardRecord,
|
|
2597
|
+
validateRunnerTarget,
|
|
2598
|
+
validateReviewerOutput,
|
|
2599
|
+
validateProjectProfile,
|
|
2600
|
+
validateProductGraph,
|
|
2601
|
+
validateProductEvent,
|
|
2602
|
+
validatePlannerOutput,
|
|
2603
|
+
validateOpenspecState,
|
|
2604
|
+
validateOpenCodeAgentFile,
|
|
2605
|
+
validateModelConfig,
|
|
2606
|
+
validateMemoryPointer,
|
|
2607
|
+
validateMemoryIndex,
|
|
2608
|
+
validateKnowledgeEntity,
|
|
2609
|
+
validateImplementerOutput,
|
|
2610
|
+
validateHarnessSuite,
|
|
2611
|
+
validateHarnessOverlay,
|
|
2612
|
+
validateHarnessExperiment,
|
|
2613
|
+
validateHarnessCatalog,
|
|
2614
|
+
validateGoalGraph,
|
|
2615
|
+
validateExecutionContext,
|
|
2616
|
+
validateEvidenceIds,
|
|
2617
|
+
validateEvidence,
|
|
2618
|
+
validateDecision,
|
|
2619
|
+
validateCouncilVerdictInput,
|
|
2620
|
+
validateCouncilVerdict,
|
|
2621
|
+
validateCouncilSpec,
|
|
2622
|
+
validateConsensusConfig,
|
|
2623
|
+
validateConfig,
|
|
2624
|
+
validateCommandEnvelope,
|
|
2625
|
+
validateClaudeAgentFile,
|
|
2626
|
+
validateCanonicalTaskCard,
|
|
2627
|
+
validateBacklogDocument,
|
|
2628
|
+
validateAgentOutput,
|
|
2629
|
+
validateAgentContract,
|
|
2630
|
+
tddCycleStateMachine,
|
|
2631
|
+
startTask,
|
|
2632
|
+
shouldRunAgentLoop,
|
|
2633
|
+
runVerification,
|
|
2634
|
+
runLoopForProject,
|
|
2635
|
+
runLoop,
|
|
2636
|
+
rollbackTaskStatus,
|
|
2637
|
+
loopStateMachine,
|
|
2638
|
+
loadTddSuiteEvidence,
|
|
2639
|
+
goalTaskToCanonicalCard,
|
|
2640
|
+
getReadyTasks,
|
|
2641
|
+
getNextTask,
|
|
2642
|
+
gateTaskCompletion,
|
|
2643
|
+
formatGoalStatus,
|
|
2644
|
+
formatFeedback,
|
|
2645
|
+
createInitialTddState,
|
|
2646
|
+
createInitialState,
|
|
2647
|
+
completeTask,
|
|
2648
|
+
captureTddSuiteEvidence,
|
|
2649
|
+
buildTaskEnvelope,
|
|
2650
|
+
advanceTddPhase,
|
|
2651
|
+
WorkflowRiskRuleSchema,
|
|
2652
|
+
WorkflowProfileSchema,
|
|
2653
|
+
WorkflowPhaseSchema,
|
|
2654
|
+
WorkflowCommandSchema,
|
|
2655
|
+
VerificationReportSchema,
|
|
2656
|
+
ToolProviderNamesSchema,
|
|
2657
|
+
TechnicalPlanOutputSchema,
|
|
2658
|
+
TaskOutcomeStatusSchema,
|
|
2659
|
+
TaskOutcomeSourceSchema,
|
|
2660
|
+
TaskOutcomeSchema,
|
|
2661
|
+
StrategicMemorySchema,
|
|
2662
|
+
SentryWebhookSchema,
|
|
2663
|
+
SentryStackFrameSchema,
|
|
2664
|
+
ScorecardVerdictSchema,
|
|
2665
|
+
ScorecardRecordSchema,
|
|
2666
|
+
ScorecardCriterionSchema,
|
|
2667
|
+
ScorecardCriterionIdSchema,
|
|
2668
|
+
RunnerTargetSchema,
|
|
2669
|
+
ReviewerOutputSchema,
|
|
2670
|
+
ReviewFindingSchema,
|
|
2671
|
+
ReviewAxisSchema,
|
|
2672
|
+
ProjectProfileSchema,
|
|
2673
|
+
ProductNodeTypeSchema,
|
|
2674
|
+
ProductMetaSchema,
|
|
2675
|
+
ProductGraphSchema,
|
|
2676
|
+
ProductGraphNodeSchema,
|
|
2677
|
+
ProductGraphEdgeSchema,
|
|
2678
|
+
ProductEventTypeSchema,
|
|
2679
|
+
ProductEventSchema,
|
|
2680
|
+
PlannerOutputSchema,
|
|
2681
|
+
PermissionProviderNamesSchema,
|
|
2682
|
+
OperationalStateSchema,
|
|
2683
|
+
OpenspecTaskCardStatusSchema,
|
|
2684
|
+
OpenspecTaskCardSchema,
|
|
2685
|
+
OpenspecTaskCardPhaseSchema,
|
|
2686
|
+
OpenspecStateSchema,
|
|
2687
|
+
OpenCodeAgentFileSchema,
|
|
2688
|
+
ModelConfigSchema,
|
|
2689
|
+
MemoryPointerSchema,
|
|
2690
|
+
MemoryIndexSchema,
|
|
2691
|
+
ManifestEntrySchema,
|
|
2692
|
+
LoopEngine,
|
|
2693
|
+
LoopConfigSchema,
|
|
2694
|
+
KnowledgeEntitySchema,
|
|
2695
|
+
InstallStrategySchema,
|
|
2696
|
+
InstallManifestSchema,
|
|
2697
|
+
ImplementerTestsSchema,
|
|
2698
|
+
ImplementerOutputSchema,
|
|
2699
|
+
ImpactReportSchema,
|
|
2700
|
+
HarnessToggleKindSchema,
|
|
2701
|
+
HarnessSuiteTaskSchema,
|
|
2702
|
+
HarnessSuiteSchema,
|
|
2703
|
+
HarnessOverlaySchema,
|
|
2704
|
+
HarnessExperimentSchema,
|
|
2705
|
+
HarnessComponentLayerSchema,
|
|
2706
|
+
HarnessComponentIdSchema,
|
|
2707
|
+
HarnessCatalogSchema,
|
|
2708
|
+
HarnessCatalogEntrySchema,
|
|
2709
|
+
GraphRelationSchema,
|
|
2710
|
+
GoalTaskSchema,
|
|
2711
|
+
GoalGraphSchema,
|
|
2712
|
+
ExecutionProfileSchema,
|
|
2713
|
+
ExecutionProfileNameSchema,
|
|
2714
|
+
ExecutionContextSchema,
|
|
2715
|
+
EvidenceSchema,
|
|
2716
|
+
EvaluationIndexSchema,
|
|
2717
|
+
DecisionSchema,
|
|
2718
|
+
CouncilVerdictSchema,
|
|
2719
|
+
CouncilVerdictInputSchema,
|
|
2720
|
+
CouncilSpecSchema,
|
|
2721
|
+
CouncilFindingSchema,
|
|
2722
|
+
CouncilAgentSpecSchema,
|
|
2723
|
+
ContractTargetSchema,
|
|
2724
|
+
ContractFormatSchema,
|
|
2725
|
+
ConsensusConfigSchema,
|
|
2726
|
+
ConfidenceLevelSchema,
|
|
2727
|
+
CompileCheckConfigSchema,
|
|
2728
|
+
CommandEnvelopeSchema,
|
|
2729
|
+
CodeConductorConfigSchema,
|
|
2730
|
+
ClaudeAgentFileSchema,
|
|
2731
|
+
CcepOutputFormatSchema,
|
|
2732
|
+
CanonicalTaskCardStatusSchema,
|
|
2733
|
+
CanonicalTaskCardSchema,
|
|
2734
|
+
BusinessReviewOutputSchema,
|
|
2735
|
+
BacklogTypeSchema,
|
|
2736
|
+
BacklogStatusSchema,
|
|
2737
|
+
BacklogPrioritySchema,
|
|
2738
|
+
BacklogItemSchema,
|
|
2739
|
+
BacklogGlobalSchema,
|
|
2740
|
+
BacklogDocumentSchema,
|
|
2741
|
+
AgentOutputSchema,
|
|
2742
|
+
AgentContractSchema,
|
|
2743
|
+
AgentArtifactSchema
|
|
2744
|
+
};
|