agentic-engineering-harness 0.4.16
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/LICENSE +201 -0
- package/README.md +273 -0
- package/dist/agents/audit.d.ts +12 -0
- package/dist/agents/audit.js +14 -0
- package/dist/agents/audit.js.map +1 -0
- package/dist/agents/compiler.d.ts +8 -0
- package/dist/agents/compiler.js +103 -0
- package/dist/agents/compiler.js.map +1 -0
- package/dist/agents/config.d.ts +6 -0
- package/dist/agents/config.js +161 -0
- package/dist/agents/config.js.map +1 -0
- package/dist/agents/escalation.d.ts +9 -0
- package/dist/agents/escalation.js +75 -0
- package/dist/agents/escalation.js.map +1 -0
- package/dist/agents/exceptionDetection.d.ts +24 -0
- package/dist/agents/exceptionDetection.js +42 -0
- package/dist/agents/exceptionDetection.js.map +1 -0
- package/dist/agents/findings.d.ts +14 -0
- package/dist/agents/findings.js +40 -0
- package/dist/agents/findings.js.map +1 -0
- package/dist/agents/gitCheckpoint.d.ts +6 -0
- package/dist/agents/gitCheckpoint.js +61 -0
- package/dist/agents/gitCheckpoint.js.map +1 -0
- package/dist/agents/jsonc.d.ts +1 -0
- package/dist/agents/jsonc.js +42 -0
- package/dist/agents/jsonc.js.map +1 -0
- package/dist/agents/outputContracts.d.ts +161 -0
- package/dist/agents/outputContracts.js +16 -0
- package/dist/agents/outputContracts.js.map +1 -0
- package/dist/agents/parallelism.d.ts +14 -0
- package/dist/agents/parallelism.js +54 -0
- package/dist/agents/parallelism.js.map +1 -0
- package/dist/agents/permissions.d.ts +5 -0
- package/dist/agents/permissions.js +30 -0
- package/dist/agents/permissions.js.map +1 -0
- package/dist/agents/qualityConvergence.d.ts +44 -0
- package/dist/agents/qualityConvergence.js +77 -0
- package/dist/agents/qualityConvergence.js.map +1 -0
- package/dist/agents/recovery.d.ts +13 -0
- package/dist/agents/recovery.js +35 -0
- package/dist/agents/recovery.js.map +1 -0
- package/dist/agents/reviewLifecycle.d.ts +30 -0
- package/dist/agents/reviewLifecycle.js +233 -0
- package/dist/agents/reviewLifecycle.js.map +1 -0
- package/dist/agents/routing.d.ts +9 -0
- package/dist/agents/routing.js +37 -0
- package/dist/agents/routing.js.map +1 -0
- package/dist/agents/structuredOutput.d.ts +1 -0
- package/dist/agents/structuredOutput.js +54 -0
- package/dist/agents/structuredOutput.js.map +1 -0
- package/dist/agents/types.d.ts +207 -0
- package/dist/agents/types.js +2 -0
- package/dist/agents/types.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +221 -0
- package/dist/cli.js.map +1 -0
- package/dist/core/config.d.ts +3 -0
- package/dist/core/config.js +59 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/doctor.d.ts +8 -0
- package/dist/core/doctor.js +59 -0
- package/dist/core/doctor.js.map +1 -0
- package/dist/core/git.d.ts +8 -0
- package/dist/core/git.js +47 -0
- package/dist/core/git.js.map +1 -0
- package/dist/core/init.d.ts +1 -0
- package/dist/core/init.js +52 -0
- package/dist/core/init.js.map +1 -0
- package/dist/core/quick.d.ts +20 -0
- package/dist/core/quick.js +49 -0
- package/dist/core/quick.js.map +1 -0
- package/dist/core/repair.d.ts +8 -0
- package/dist/core/repair.js +7 -0
- package/dist/core/repair.js.map +1 -0
- package/dist/core/run.d.ts +38 -0
- package/dist/core/run.js +165 -0
- package/dist/core/run.js.map +1 -0
- package/dist/core/sdd.d.ts +10 -0
- package/dist/core/sdd.js +88 -0
- package/dist/core/sdd.js.map +1 -0
- package/dist/core/seal.d.ts +3 -0
- package/dist/core/seal.js +74 -0
- package/dist/core/seal.js.map +1 -0
- package/dist/core/triage.d.ts +22 -0
- package/dist/core/triage.js +38 -0
- package/dist/core/triage.js.map +1 -0
- package/dist/core/types.d.ts +354 -0
- package/dist/core/types.js +2 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/verify.d.ts +6 -0
- package/dist/core/verify.js +51 -0
- package/dist/core/verify.js.map +1 -0
- package/dist/delivery/finalize.d.ts +17 -0
- package/dist/delivery/finalize.js +71 -0
- package/dist/delivery/finalize.js.map +1 -0
- package/dist/delivery/handoff.d.ts +39 -0
- package/dist/delivery/handoff.js +250 -0
- package/dist/delivery/handoff.js.map +1 -0
- package/dist/entry.d.ts +2 -0
- package/dist/entry.js +112 -0
- package/dist/entry.js.map +1 -0
- package/dist/evals/runner.d.ts +4 -0
- package/dist/evals/runner.js +112 -0
- package/dist/evals/runner.js.map +1 -0
- package/dist/evals/scoring.d.ts +3 -0
- package/dist/evals/scoring.js +41 -0
- package/dist/evals/scoring.js.map +1 -0
- package/dist/evals/types.d.ts +46 -0
- package/dist/evals/types.js +2 -0
- package/dist/evals/types.js.map +1 -0
- package/dist/issues/intake.d.ts +114 -0
- package/dist/issues/intake.js +213 -0
- package/dist/issues/intake.js.map +1 -0
- package/dist/memory/benchmark.d.ts +33 -0
- package/dist/memory/benchmark.js +69 -0
- package/dist/memory/benchmark.js.map +1 -0
- package/dist/metrics/runMetrics.d.ts +9 -0
- package/dist/metrics/runMetrics.js +34 -0
- package/dist/metrics/runMetrics.js.map +1 -0
- package/dist/metrics/usage.d.ts +3 -0
- package/dist/metrics/usage.js +53 -0
- package/dist/metrics/usage.js.map +1 -0
- package/dist/provenance/generate.d.ts +30 -0
- package/dist/provenance/generate.js +96 -0
- package/dist/provenance/generate.js.map +1 -0
- package/dist/providers/engram.d.ts +8 -0
- package/dist/providers/engram.js +14 -0
- package/dist/providers/engram.js.map +1 -0
- package/dist/providers/graphify.d.ts +9 -0
- package/dist/providers/graphify.js +28 -0
- package/dist/providers/graphify.js.map +1 -0
- package/dist/providers/paseo.d.ts +8 -0
- package/dist/providers/paseo.js +14 -0
- package/dist/providers/paseo.js.map +1 -0
- package/dist/providers/types.d.ts +41 -0
- package/dist/providers/types.js +2 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/telemetry/events.d.ts +2 -0
- package/dist/telemetry/events.js +29 -0
- package/dist/telemetry/events.js.map +1 -0
- package/dist/telemetry/otlp.d.ts +3 -0
- package/dist/telemetry/otlp.js +57 -0
- package/dist/telemetry/otlp.js.map +1 -0
- package/dist/toolchain/config.d.ts +10 -0
- package/dist/toolchain/config.js +54 -0
- package/dist/toolchain/config.js.map +1 -0
- package/dist/toolchain/doctor.d.ts +8 -0
- package/dist/toolchain/doctor.js +56 -0
- package/dist/toolchain/doctor.js.map +1 -0
- package/dist/toolchain/mise.d.ts +10 -0
- package/dist/toolchain/mise.js +61 -0
- package/dist/toolchain/mise.js.map +1 -0
- package/dist/toolchain/resolve.d.ts +8 -0
- package/dist/toolchain/resolve.js +159 -0
- package/dist/toolchain/resolve.js.map +1 -0
- package/dist/toolchain/setup.d.ts +7 -0
- package/dist/toolchain/setup.js +141 -0
- package/dist/toolchain/setup.js.map +1 -0
- package/dist/toolchain/types.d.ts +95 -0
- package/dist/toolchain/types.js +2 -0
- package/dist/toolchain/types.js.map +1 -0
- package/dist/utils/process.d.ts +15 -0
- package/dist/utils/process.js +94 -0
- package/dist/utils/process.js.map +1 -0
- package/dist/validators/commands.d.ts +2 -0
- package/dist/validators/commands.js +28 -0
- package/dist/validators/commands.js.map +1 -0
- package/dist/validators/constraints.d.ts +6 -0
- package/dist/validators/constraints.js +30 -0
- package/dist/validators/constraints.js.map +1 -0
- package/dist/validators/diffScope.d.ts +2 -0
- package/dist/validators/diffScope.js +36 -0
- package/dist/validators/diffScope.js.map +1 -0
- package/dist/validators/evidence.d.ts +6 -0
- package/dist/validators/evidence.js +8 -0
- package/dist/validators/evidence.js.map +1 -0
- package/dist/validators/external.d.ts +3 -0
- package/dist/validators/external.js +22 -0
- package/dist/validators/external.js.map +1 -0
- package/dist/validators/gherkin.d.ts +3 -0
- package/dist/validators/gherkin.js +59 -0
- package/dist/validators/gherkin.js.map +1 -0
- package/dist/validators/graphify.d.ts +4 -0
- package/dist/validators/graphify.js +108 -0
- package/dist/validators/graphify.js.map +1 -0
- package/dist/validators/opa.d.ts +3 -0
- package/dist/validators/opa.js +43 -0
- package/dist/validators/opa.js.map +1 -0
- package/dist/validators/openapi.d.ts +25 -0
- package/dist/validators/openapi.js +98 -0
- package/dist/validators/openapi.js.map +1 -0
- package/dist/validators/registry.d.ts +2 -0
- package/dist/validators/registry.js +36 -0
- package/dist/validators/registry.js.map +1 -0
- package/dist/validators/toolCommand.d.ts +5 -0
- package/dist/validators/toolCommand.js +33 -0
- package/dist/validators/toolCommand.js.map +1 -0
- package/dist/validators/types.d.ts +13 -0
- package/dist/validators/types.js +2 -0
- package/dist/validators/types.js.map +1 -0
- package/dist/workers/agentPrompt.d.ts +3 -0
- package/dist/workers/agentPrompt.js +84 -0
- package/dist/workers/agentPrompt.js.map +1 -0
- package/dist/workers/direct.d.ts +13 -0
- package/dist/workers/direct.js +30 -0
- package/dist/workers/direct.js.map +1 -0
- package/dist/workers/factory.d.ts +4 -0
- package/dist/workers/factory.js +10 -0
- package/dist/workers/factory.js.map +1 -0
- package/dist/workers/paseo.d.ts +14 -0
- package/dist/workers/paseo.js +29 -0
- package/dist/workers/paseo.js.map +1 -0
- package/dist/workers/podman.d.ts +13 -0
- package/dist/workers/podman.js +22 -0
- package/dist/workers/podman.js.map +1 -0
- package/dist/workers/prompt.d.ts +4 -0
- package/dist/workers/prompt.js +4 -0
- package/dist/workers/prompt.js.map +1 -0
- package/dist/workers/types.d.ts +11 -0
- package/dist/workers/types.js +2 -0
- package/dist/workers/types.js.map +1 -0
- package/docs/ARCHITECTURE.md +47 -0
- package/docs/EVALS.md +28 -0
- package/docs/MEMORY.md +28 -0
- package/docs/OBSERVABILITY.md +18 -0
- package/docs/OSS_STACK.md +27 -0
- package/docs/PASEO.md +9 -0
- package/docs/PUBLISHING.md +110 -0
- package/docs/SDD.md +35 -0
- package/docs/SECURITY.md +21 -0
- package/docs/V0.2.md +42 -0
- package/docs/V0.3.md +40 -0
- package/docs/V0.4.11.md +30 -0
- package/docs/V0.4.12.md +88 -0
- package/docs/V0.4.13.md +203 -0
- package/docs/V0.4.14.md +209 -0
- package/docs/V0.4.15.md +365 -0
- package/docs/V0.4.16.md +229 -0
- package/docs/V0.4.md +28 -0
- package/docs/VALIDATION.md +23 -0
- package/package.json +18 -0
- package/policies/core/dependency-policy.rego +12 -0
- package/policies/core/schema-policy.rego +12 -0
- package/policies/core/trust-boundary.rego +17 -0
- package/presets/agents/default.jsonc +80 -0
- package/presets/docker.yaml +4 -0
- package/presets/dotnet.yaml +12 -0
- package/presets/expo.yaml +6 -0
- package/presets/generic.yaml +3 -0
- package/presets/nextjs.yaml +8 -0
- package/presets/node.yaml +6 -0
- package/presets/pnpm.yaml +6 -0
- package/presets/postgres.yaml +4 -0
- package/schemas/agent-output-planner.schema.json +1 -0
- package/schemas/agent-topology.schema.json +37 -0
- package/schemas/project.schema.json +36 -0
- package/schemas/quick-contract.schema.json +17 -0
- package/schemas/task-contract.schema.json +18 -0
- package/schemas/toolchain.schema.json +70 -0
- package/schemas/validation-report.schema.json +15 -0
- package/skills/acceptance-traceability/SKILL.md +13 -0
- package/skills/deterministic-validation/SKILL.md +15 -0
- package/skills/engineering-workflow/SKILL.md +108 -0
- package/skills/finding-dedup/SKILL.md +12 -0
- package/skills/github-delivery-lifecycle/SKILL.md +16 -0
- package/skills/implementation-worker/SKILL.md +17 -0
- package/skills/lead-engineer/SKILL.md +30 -0
- package/skills/memory-hygiene/SKILL.md +22 -0
- package/skills/prompt-drift-audit/SKILL.md +10 -0
- package/skills/recovery-classifier/SKILL.md +13 -0
- package/skills/routing-normalizer/SKILL.md +17 -0
- package/skills/sdd/SKILL.md +21 -0
- package/skills/simplify/SKILL.md +16 -0
- package/skills/verification-planning/SKILL.md +17 -0
- package/skills/worktree-lifecycle/SKILL.md +18 -0
- package/templates/AGENTS.md +37 -0
- package/templates/agents.source.jsonc +39 -0
- package/templates/otel-collector.yaml +21 -0
- package/templates/project.yaml +196 -0
- package/templates/toolchain.yaml +127 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
function packageRoot() { return path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../.."); }
|
|
5
|
+
async function exists(file) { try {
|
|
6
|
+
await fs.access(file);
|
|
7
|
+
return true;
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return false;
|
|
11
|
+
} }
|
|
12
|
+
async function copyFileIfMissing(source, destination) { if (await exists(destination))
|
|
13
|
+
return; await fs.mkdir(path.dirname(destination), { recursive: true }); await fs.copyFile(source, destination); }
|
|
14
|
+
async function copyTree(source, destination) { await fs.mkdir(destination, { recursive: true }); for (const entry of await fs.readdir(source, { withFileTypes: true })) {
|
|
15
|
+
const src = path.join(source, entry.name);
|
|
16
|
+
const dst = path.join(destination, entry.name);
|
|
17
|
+
if (entry.isDirectory())
|
|
18
|
+
await copyTree(src, dst);
|
|
19
|
+
else
|
|
20
|
+
await copyFileIfMissing(src, dst);
|
|
21
|
+
} }
|
|
22
|
+
export async function initializeProject(root) {
|
|
23
|
+
const pkg = packageRoot();
|
|
24
|
+
const created = [];
|
|
25
|
+
const mappings = [["templates/project.yaml", ".harness/project.yaml"], ["templates/toolchain.yaml", ".harness/toolchain.yaml"], ["templates/agents.source.jsonc", ".harness/agents.source.jsonc"], ["templates/AGENTS.md", "AGENTS.md"], ["templates/otel-collector.yaml", ".harness/otel-collector.yaml"]];
|
|
26
|
+
for (const [src, dst] of mappings) {
|
|
27
|
+
const target = path.join(root, dst);
|
|
28
|
+
if (!(await exists(target))) {
|
|
29
|
+
await copyFileIfMissing(path.join(pkg, src), target);
|
|
30
|
+
created.push(dst);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
await copyTree(path.join(pkg, "policies", "core"), path.join(root, ".harness", "policies", "core"));
|
|
34
|
+
await copyTree(path.join(pkg, "skills"), path.join(root, ".harness", "skills"));
|
|
35
|
+
for (const dir of [".harness/bin", ".harness/contracts", ".harness/seals", ".harness/reports", ".harness/repairs", ".harness/runs", ".harness/telemetry", ".harness/evals/results", ".harness/evals/workspaces", ".harness/provenance", ".harness/generated", ".harness/findings", ".harness/delivery", ".config/mise/conf.d", "specs/changes", "docs/decisions", "evals/corpus", "memory-benchmarks"])
|
|
36
|
+
await fs.mkdir(path.join(root, dir), { recursive: true });
|
|
37
|
+
if (await ensureGitignore(root))
|
|
38
|
+
created.push(".gitignore (AEH generated-state block)");
|
|
39
|
+
return created;
|
|
40
|
+
}
|
|
41
|
+
async function ensureGitignore(root) {
|
|
42
|
+
const file = path.join(root, ".gitignore");
|
|
43
|
+
const marker = "# BEGIN Agentic Engineering Harness generated state";
|
|
44
|
+
const block = `${marker}\n.harness/bin/\n.harness/toolchain.state.json\n.harness/generated/\n.harness/contracts/\n.harness/seals/\n.harness/reports/\n.harness/repairs/\n.harness/runs/\n.harness/telemetry/\n.harness/findings/\n.harness/evals/\n.harness/provenance/\n.harness/delivery/\n.harness/issues/\n.config/mise/conf.d/aeh.toml\n# END Agentic Engineering Harness generated state`;
|
|
45
|
+
const current = await fs.readFile(file, "utf8").catch(() => "");
|
|
46
|
+
if (current.includes(marker))
|
|
47
|
+
return false;
|
|
48
|
+
const prefix = current && !current.endsWith("\n") ? `${current}\n` : current;
|
|
49
|
+
await fs.writeFile(file, `${prefix}${prefix ? "\n" : ""}${block}\n`);
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/core/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { HarnessProjectConfig, TaskContract } from "./types.js";
|
|
2
|
+
import { type TriageFlag } from "./triage.js";
|
|
3
|
+
export interface CreateQuickContractInput {
|
|
4
|
+
title: string;
|
|
5
|
+
request: string;
|
|
6
|
+
scope: string[];
|
|
7
|
+
acceptance: string[];
|
|
8
|
+
domains?: string[];
|
|
9
|
+
risk?: "low" | "medium" | "high";
|
|
10
|
+
flags?: TriageFlag[];
|
|
11
|
+
profile?: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function createQuickContract(root: string, config: HarnessProjectConfig, taskId: string, input: CreateQuickContractInput): Promise<{
|
|
14
|
+
file: string;
|
|
15
|
+
contract: TaskContract;
|
|
16
|
+
}>;
|
|
17
|
+
export declare function validateQuickTaskContract(config: HarnessProjectConfig, contract: TaskContract): {
|
|
18
|
+
ok: boolean;
|
|
19
|
+
issues: string[];
|
|
20
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import YAML from "yaml";
|
|
4
|
+
import { triageChange } from "./triage.js";
|
|
5
|
+
export async function createQuickContract(root, config, taskId, input) {
|
|
6
|
+
const decision = triageChange(config, { request: input.request, files: input.scope, domains: input.domains, risk: input.risk, flags: input.flags });
|
|
7
|
+
if (!decision.quickEligible)
|
|
8
|
+
throw new Error(`QUICK_MODE_REJECTED: ${decision.reasons.join("; ")}. Create an SDD change instead.`);
|
|
9
|
+
if (!input.acceptance.length)
|
|
10
|
+
throw new Error("QUICK_MODE_REJECTED: at least one observable acceptance statement is required.");
|
|
11
|
+
const contract = {
|
|
12
|
+
version: 1,
|
|
13
|
+
mode: "quick",
|
|
14
|
+
task: { id: taskId, title: input.title },
|
|
15
|
+
quick: { request: input.request, acceptance: input.acceptance, triage: { mode: decision.mode, reasons: decision.reasons, evaluatedAt: new Date().toISOString() } },
|
|
16
|
+
git: { baseRef: config.validation?.baseRef ?? "main" },
|
|
17
|
+
scope: { allowed: [...new Set(input.scope)], forbidden: [], frozen: [] },
|
|
18
|
+
routing: { intent: "implement", domains: [...new Set(input.domains ?? [])], risk: "low", profile: input.profile },
|
|
19
|
+
constraints: { breakingApiChanges: false, newDependencies: false, schemaChanges: false, maxFilesChanged: config.workflow?.quick?.maxFiles ?? 5 },
|
|
20
|
+
repair: { maxAttempts: config.orchestration?.worker?.maxRepairAttempts ?? 2 }
|
|
21
|
+
};
|
|
22
|
+
const contractsDir = path.resolve(root, config.sdd?.contractsDir ?? ".harness/contracts");
|
|
23
|
+
await fs.mkdir(contractsDir, { recursive: true });
|
|
24
|
+
const file = path.join(contractsDir, `${taskId}.yaml`);
|
|
25
|
+
await fs.writeFile(file, YAML.stringify(contract));
|
|
26
|
+
return { file, contract };
|
|
27
|
+
}
|
|
28
|
+
export function validateQuickTaskContract(config, contract) {
|
|
29
|
+
const issues = [];
|
|
30
|
+
if (contract.mode !== "quick")
|
|
31
|
+
return { ok: true, issues };
|
|
32
|
+
if (!contract.quick?.request?.trim())
|
|
33
|
+
issues.push("quick.request is required");
|
|
34
|
+
if (!contract.quick?.acceptance?.length)
|
|
35
|
+
issues.push("quick.acceptance must contain at least one observable statement");
|
|
36
|
+
const scope = contract.scope?.allowed ?? [];
|
|
37
|
+
const evidence = { request: contract.quick?.request ?? "", files: scope, domains: contract.routing?.domains, risk: contract.routing?.risk ?? "low" };
|
|
38
|
+
const decision = triageChange(config, evidence);
|
|
39
|
+
if (!decision.quickEligible)
|
|
40
|
+
issues.push(...decision.reasons.map((reason) => `quick triage no longer qualifies: ${reason}`));
|
|
41
|
+
if (contract.constraints?.breakingApiChanges !== false)
|
|
42
|
+
issues.push("quick mode requires breakingApiChanges=false");
|
|
43
|
+
if (contract.constraints?.newDependencies !== false)
|
|
44
|
+
issues.push("quick mode requires newDependencies=false");
|
|
45
|
+
if (contract.constraints?.schemaChanges !== false)
|
|
46
|
+
issues.push("quick mode requires schemaChanges=false");
|
|
47
|
+
return { ok: issues.length === 0, issues };
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=quick.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quick.js","sourceRoot":"","sources":["../../src/core/quick.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { HarnessProjectConfig, RepairPacket, ValidationReport } from "./types.js";
|
|
2
|
+
import type { FailureType } from "../agents/types.js";
|
|
3
|
+
export declare function createRepairPacket(report: ValidationReport, attempt: number, context?: {
|
|
4
|
+
failureType?: FailureType;
|
|
5
|
+
failedAgent?: string;
|
|
6
|
+
recoveryAction?: string;
|
|
7
|
+
}): RepairPacket;
|
|
8
|
+
export declare function writeRepairPacket(root: string, config: HarnessProjectConfig, packet: RepairPacket): Promise<string>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
export function createRepairPacket(report, attempt, context) {
|
|
4
|
+
return { version: 1, taskId: report.taskId, attempt, createdAt: new Date().toISOString(), failureType: context?.failureType, failedAgent: context?.failedAgent, recoveryAction: context?.recoveryAction, failures: report.checks.filter((check) => check.status === "FAIL").map((check) => ({ id: check.id, category: check.category, message: check.message, details: check.details })) };
|
|
5
|
+
}
|
|
6
|
+
export async function writeRepairPacket(root, config, packet) { const repairsDir = path.resolve(root, config.sdd?.repairsDir ?? ".harness/repairs"); await fs.mkdir(repairsDir, { recursive: true }); const file = path.join(repairsDir, `${packet.taskId}-${packet.attempt}.json`); await fs.writeFile(file, `${JSON.stringify(packet, null, 2)}\n`); return file; }
|
|
7
|
+
//# sourceMappingURL=repair.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repair.js","sourceRoot":"","sources":["../../src/core/repair.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAI7B,MAAM,UAAU,kBAAkB,CAAC,MAAwB,EAAE,OAAe,EAAE,OAAsF;IAClK,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC;AAC7X,CAAC;AACD,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,IAAY,EAAE,MAA4B,EAAE,MAAoB,IAAqB,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG,EAAE,UAAU,IAAI,kBAAkB,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,OAAO,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { SeverityCounts } from "../agents/qualityConvergence.js";
|
|
2
|
+
import type { HarnessProjectConfig, RunMetrics, TaskContract, ValidationReport, WorkerSession } from "./types.js";
|
|
3
|
+
import { type DeliveryFinalizationResult } from "../delivery/finalize.js";
|
|
4
|
+
export interface TaskRunResult {
|
|
5
|
+
taskId: string;
|
|
6
|
+
status: "PASS" | "FAIL";
|
|
7
|
+
attempts: number;
|
|
8
|
+
worker: WorkerSession;
|
|
9
|
+
report: ValidationReport;
|
|
10
|
+
metrics: RunMetrics;
|
|
11
|
+
routing?: {
|
|
12
|
+
profile?: string;
|
|
13
|
+
ruleIds: string[];
|
|
14
|
+
agent: string;
|
|
15
|
+
runtime: string;
|
|
16
|
+
model: string;
|
|
17
|
+
nativeAgent?: string;
|
|
18
|
+
reviewers: string[];
|
|
19
|
+
validators: string[];
|
|
20
|
+
};
|
|
21
|
+
review?: {
|
|
22
|
+
status: "PASS" | "FAIL";
|
|
23
|
+
finalState: string;
|
|
24
|
+
humanRequired: boolean;
|
|
25
|
+
rounds: number;
|
|
26
|
+
findings: number;
|
|
27
|
+
debtScore: number;
|
|
28
|
+
debtPoints: number;
|
|
29
|
+
counts: SeverityCounts;
|
|
30
|
+
convergence: string;
|
|
31
|
+
leadAccepted?: boolean;
|
|
32
|
+
reviewerSessions: number;
|
|
33
|
+
};
|
|
34
|
+
delivery?: DeliveryFinalizationResult;
|
|
35
|
+
}
|
|
36
|
+
export declare function runTask(root: string, config: HarnessProjectConfig, contract: TaskContract, options?: {
|
|
37
|
+
profile?: string;
|
|
38
|
+
}): Promise<TaskRunResult>;
|
package/dist/core/run.js
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { auditAgentTopology } from "../agents/audit.js";
|
|
4
|
+
import { loadResolvedAgentTopology } from "../agents/config.js";
|
|
5
|
+
import { classifyFailure, formatRecoveryAction, resolveRecoveryStep } from "../agents/recovery.js";
|
|
6
|
+
import { executionSelectionForAgent, selectExecutionForTask, selectFallbackExecution } from "../agents/routing.js";
|
|
7
|
+
import { validateExecutionCapabilities } from "../agents/permissions.js";
|
|
8
|
+
import { runReviewLifecycle } from "../agents/reviewLifecycle.js";
|
|
9
|
+
import { loadTaskContract } from "./config.js";
|
|
10
|
+
import { validateSddChange } from "./sdd.js";
|
|
11
|
+
import { validateQuickTaskContract } from "./quick.js";
|
|
12
|
+
import { sealTask, verifyTaskSeal } from "./seal.js";
|
|
13
|
+
import { verifyTask } from "./verify.js";
|
|
14
|
+
import { createRepairPacket, writeRepairPacket } from "./repair.js";
|
|
15
|
+
import { createWorkerExecutor } from "../workers/factory.js";
|
|
16
|
+
import { snapshotGraph } from "../validators/graphify.js";
|
|
17
|
+
import { runProcess } from "../utils/process.js";
|
|
18
|
+
import { recordEvent } from "../telemetry/events.js";
|
|
19
|
+
import { extractUsageMetrics } from "../metrics/usage.js";
|
|
20
|
+
import { buildRunMetrics, countHumanInterventions } from "../metrics/runMetrics.js";
|
|
21
|
+
import { deliveryWorkspacePath } from "../delivery/handoff.js";
|
|
22
|
+
import { deliveryFinalizationFailure, finalizeAcceptedIssue } from "../delivery/finalize.js";
|
|
23
|
+
import { verifyGithubIssueDrift } from "../issues/intake.js";
|
|
24
|
+
export async function runTask(root, config, contract, options) {
|
|
25
|
+
const controlRoot = path.resolve(root);
|
|
26
|
+
const workspaceRoot = path.resolve(await deliveryWorkspacePath(controlRoot, config, contract.task.id) ?? controlRoot);
|
|
27
|
+
const effectiveContract = workspaceRoot === controlRoot ? contract : await loadTaskContract(workspaceRoot, contract.task.id, config);
|
|
28
|
+
const startedMs = Date.now();
|
|
29
|
+
const startedAt = new Date(startedMs).toISOString();
|
|
30
|
+
const issueDrift = await verifyGithubIssueDrift(controlRoot, config, effectiveContract);
|
|
31
|
+
if (!issueDrift.ok)
|
|
32
|
+
throw new Error(issueDrift.message);
|
|
33
|
+
if (effectiveContract.issue)
|
|
34
|
+
await recordEvent(controlRoot, config, "harness.issue.drift-check", { taskId: effectiveContract.task.id, issue: effectiveContract.issue.number, repository: effectiveContract.issue.repository, ok: true, contentSha256: effectiveContract.issue.contentSha256 });
|
|
35
|
+
if (effectiveContract.mode === "quick") {
|
|
36
|
+
const quick = validateQuickTaskContract(config, effectiveContract);
|
|
37
|
+
if (!quick.ok)
|
|
38
|
+
throw new Error(`QuickContract validation failed before delegation:\n${quick.issues.map((item) => `- ${item}`).join("\n")}\nEscalate this change to SDD/spec mode.`);
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
const trace = await validateSddChange(workspaceRoot, effectiveContract.task.id, config);
|
|
42
|
+
if (!trace.ok)
|
|
43
|
+
throw new Error(`SDD validation failed before delegation:\n${[...trace.missing, ...trace.issues].map((item) => `- ${item}`).join("\n")}`);
|
|
44
|
+
}
|
|
45
|
+
await recordEvent(controlRoot, config, "harness.run.start", { taskId: effectiveContract.task.id, mode: effectiveContract.mode ?? "spec", workspaceRoot: workspaceRoot === controlRoot ? undefined : workspaceRoot, issue: effectiveContract.issue ? { repository: effectiveContract.issue.repository, number: effectiveContract.issue.number } : undefined });
|
|
46
|
+
if (workspaceRoot === controlRoot)
|
|
47
|
+
await sealTask(controlRoot, config, effectiveContract);
|
|
48
|
+
else {
|
|
49
|
+
const seal = await verifyTaskSeal(workspaceRoot, effectiveContract, config.validation?.requireSeal ?? true);
|
|
50
|
+
if (seal.status === "FAIL")
|
|
51
|
+
throw new Error(`Delivery workspace trust check failed before delegation: ${seal.message}`);
|
|
52
|
+
}
|
|
53
|
+
const topologyState = await resolveTopology(controlRoot, config, effectiveContract, options?.profile);
|
|
54
|
+
const topology = topologyState.topology;
|
|
55
|
+
const route = topologyState.route;
|
|
56
|
+
let selection = topologyState.selection;
|
|
57
|
+
await refreshGraphIfConfigured(workspaceRoot, config);
|
|
58
|
+
const beforeSnapshot = await snapshotGraph(workspaceRoot, config, effectiveContract.task.id, "before");
|
|
59
|
+
if (!beforeSnapshot && config.codeIntelligence?.required)
|
|
60
|
+
throw new Error("Code intelligence is required but the Graphify before snapshot could not be created.");
|
|
61
|
+
let executor = createWorkerExecutor(config, selection);
|
|
62
|
+
const health = await executor.doctor(workspaceRoot, config, selection);
|
|
63
|
+
if (!health.ok)
|
|
64
|
+
throw new Error(`${executor.name} executor unavailable: ${health.message}`);
|
|
65
|
+
let worker = await executor.start(workspaceRoot, config, effectiveContract, selection);
|
|
66
|
+
let attempts = 0;
|
|
67
|
+
let report = withWorkerExecutionCheck(await verifyAfterWorker(workspaceRoot, controlRoot, config, effectiveContract), worker);
|
|
68
|
+
const firstPassSuccess = report.status === "PASS";
|
|
69
|
+
const maxRepairs = effectiveContract.repair?.maxAttempts ?? config.orchestration?.worker?.maxRepairAttempts ?? 2;
|
|
70
|
+
while (report.status === "FAIL" && attempts < maxRepairs) {
|
|
71
|
+
attempts += 1;
|
|
72
|
+
const failureType = classifyFailure({ report, worker });
|
|
73
|
+
const recovery = topology ? resolveRecoveryStep(topology, failureType, attempts) : { action: "same-agent" };
|
|
74
|
+
const recoveryAction = formatRecoveryAction(recovery, selection?.logicalAgent ?? "legacy-worker");
|
|
75
|
+
const packet = createRepairPacket(report, attempts, { failureType, failedAgent: selection?.logicalAgent, recoveryAction });
|
|
76
|
+
if (!packet.failures.length)
|
|
77
|
+
break;
|
|
78
|
+
await writeRepairPacket(controlRoot, config, packet);
|
|
79
|
+
await recordEvent(controlRoot, config, "harness.repair.start", { taskId: effectiveContract.task.id, attempt: attempts, failureType, recoveryAction, failures: packet.failures.length });
|
|
80
|
+
if (recovery.action === "lead" || recovery.action === "stop")
|
|
81
|
+
break;
|
|
82
|
+
if (topology && recovery.action === "agent" && recovery.agent)
|
|
83
|
+
selection = executionSelectionForAgent(topology, recovery.agent);
|
|
84
|
+
else if (topology && recovery.action === "reroute") {
|
|
85
|
+
const fallback = selectFallbackExecution(topology, effectiveContract, selection?.logicalAgent ?? "");
|
|
86
|
+
if (!fallback)
|
|
87
|
+
break;
|
|
88
|
+
selection = fallback;
|
|
89
|
+
}
|
|
90
|
+
if (selection) {
|
|
91
|
+
const transport = selection.transport === "inherit" ? (config.orchestration?.provider ?? "none") : selection.transport;
|
|
92
|
+
const issues = validateExecutionCapabilities(selection, transport);
|
|
93
|
+
if (issues.length)
|
|
94
|
+
throw new Error(`Recovery agent ${selection.logicalAgent} is not executable: ${issues.join("; ")}`);
|
|
95
|
+
}
|
|
96
|
+
executor = createWorkerExecutor(config, selection);
|
|
97
|
+
const recoveryHealth = await executor.doctor(workspaceRoot, config, selection);
|
|
98
|
+
if (!recoveryHealth.ok)
|
|
99
|
+
throw new Error(`${executor.name} recovery executor unavailable: ${recoveryHealth.message}`);
|
|
100
|
+
worker = await executor.repair(workspaceRoot, config, effectiveContract, worker, packet, selection);
|
|
101
|
+
report = withWorkerExecutionCheck(await verifyAfterWorker(workspaceRoot, controlRoot, config, effectiveContract), worker);
|
|
102
|
+
await recordEvent(controlRoot, config, "harness.repair.finish", { taskId: effectiveContract.task.id, attempt: attempts, status: report.status, agent: selection?.logicalAgent });
|
|
103
|
+
}
|
|
104
|
+
let reviewSummary;
|
|
105
|
+
if (report.status === "PASS" && topology && route && selection) {
|
|
106
|
+
const review = await runReviewLifecycle({ root: workspaceRoot, stateRoot: controlRoot, config, contract: effectiveContract, topology, route, implementationSelection: selection, report, revalidate: async () => verifyAfterWorker(workspaceRoot, controlRoot, config, effectiveContract) });
|
|
107
|
+
report = mergeChecks(withWorkerExecutionCheck(review.report, worker), review.checks);
|
|
108
|
+
const quality = review.qualityHistory.at(-1);
|
|
109
|
+
reviewSummary = { status: review.status, finalState: review.finalState, humanRequired: review.humanRequired, rounds: review.rounds, findings: review.findings.outputCount, debtScore: quality.debtScore, debtPoints: quality.debtPoints, counts: quality.counts, convergence: quality.convergence, leadAccepted: review.leadAccepted, reviewerSessions: review.sessions.length };
|
|
110
|
+
await recordEvent(controlRoot, config, "harness.review.finish", { taskId: effectiveContract.task.id, status: review.status, finalState: review.finalState, humanRequired: review.humanRequired, rounds: review.rounds, findings: review.findings.outputCount, debtScore: quality.debtScore, convergence: quality.convergence, leadAccepted: review.leadAccepted, sessions: review.sessions.length });
|
|
111
|
+
}
|
|
112
|
+
let deliverySummary;
|
|
113
|
+
if (report.status === "PASS") {
|
|
114
|
+
try {
|
|
115
|
+
deliverySummary = await finalizeAcceptedIssue(workspaceRoot, config, effectiveContract);
|
|
116
|
+
if (deliverySummary.status !== "SKIPPED")
|
|
117
|
+
await recordEvent(controlRoot, config, "harness.delivery.finalize", { taskId: effectiveContract.task.id, status: deliverySummary.status, commitSha: deliverySummary.commitSha, pullRequest: deliverySummary.pullRequest });
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
deliverySummary = deliveryFinalizationFailure(error);
|
|
121
|
+
report = mergeChecks(report, [{ id: "delivery.finalization", category: "delivery", status: "FAIL", message: deliverySummary.message, details: { status: deliverySummary.status, humanRequired: deliverySummary.humanRequired } }]);
|
|
122
|
+
if (reviewSummary && deliverySummary.humanRequired)
|
|
123
|
+
reviewSummary = { ...reviewSummary, status: "FAIL", finalState: "BLOCKED_EXTERNAL", humanRequired: true };
|
|
124
|
+
await recordEvent(controlRoot, config, "harness.delivery.finalize", { taskId: effectiveContract.task.id, status: deliverySummary.status, humanRequired: deliverySummary.humanRequired, message: deliverySummary.message });
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
worker.metrics = extractUsageMetrics(`${worker.stdout}\n${worker.stderr}`);
|
|
128
|
+
const metrics = buildRunMetrics({ firstPassSuccess, repairCount: attempts, humanInterventions: await countHumanInterventions(controlRoot, config, effectiveContract.task.id, startedAt), durationMs: Date.now() - startedMs, usage: worker.metrics });
|
|
129
|
+
const routing = selection ? { profile: selection.profile, ruleIds: route?.ruleIds ?? [], agent: selection.logicalAgent, runtime: selection.runtimeName, model: selection.modelId, nativeAgent: selection.nativeAgent, reviewers: route?.reviewers ?? [], validators: route?.validators ?? [] } : undefined;
|
|
130
|
+
const result = { taskId: effectiveContract.task.id, status: report.status, attempts, worker, report, metrics, routing, review: reviewSummary, delivery: deliverySummary };
|
|
131
|
+
const runsDir = path.resolve(controlRoot, config.sdd?.runsDir ?? ".harness/runs");
|
|
132
|
+
await fs.mkdir(runsDir, { recursive: true });
|
|
133
|
+
await fs.writeFile(path.join(runsDir, `${effectiveContract.task.id}.json`), `${JSON.stringify(result, null, 2)}\n`);
|
|
134
|
+
await recordEvent(controlRoot, config, "harness.run.finish", { taskId: effectiveContract.task.id, status: result.status, attempts, mode: effectiveContract.mode ?? "spec", workspaceRoot: workspaceRoot === controlRoot ? undefined : workspaceRoot, agent: selection?.logicalAgent, runtime: selection?.runtimeName, model: selection?.modelId, profile: selection?.profile, reviewStatus: reviewSummary?.status, reviewFinalState: reviewSummary?.finalState, humanRequired: reviewSummary?.humanRequired ?? deliverySummary?.humanRequired, debtScore: reviewSummary?.debtScore, deliveryStatus: deliverySummary?.status, pullRequest: deliverySummary?.pullRequest, durationMs: metrics.durationMs, totalTokens: metrics.usage.totalTokens ?? 0, costUsd: metrics.usage.costUsd ?? 0 });
|
|
135
|
+
return result;
|
|
136
|
+
}
|
|
137
|
+
async function resolveTopology(root, config, contract, profileOverride) { if (!config.agents)
|
|
138
|
+
return {}; const explicitProfile = profileOverride ?? contract.routing?.profile; const profile = explicitProfile ?? config.agents.activeProfile; try {
|
|
139
|
+
const audit = await auditAgentTopology(root, config, profile, { checkGenerated: !explicitProfile });
|
|
140
|
+
if (!audit.ok)
|
|
141
|
+
throw new Error(`Agent topology audit failed:\n${audit.checks.filter((check) => check.status === "FAIL").map((check) => `- ${check.id}: ${check.message}`).join("\n")}`);
|
|
142
|
+
const topology = await loadResolvedAgentTopology(root, config, profile);
|
|
143
|
+
const { route, selection } = selectExecutionForTask(topology, contract);
|
|
144
|
+
const transport = selection.transport === "inherit" ? (config.orchestration?.provider ?? "none") : selection.transport;
|
|
145
|
+
const issues = validateExecutionCapabilities(selection, transport);
|
|
146
|
+
if (issues.length)
|
|
147
|
+
throw new Error(`Selected agent ${selection.logicalAgent} is not executable: ${issues.join("; ")}`);
|
|
148
|
+
await recordEvent(root, config, "harness.agent.route", { taskId: contract.task.id, profile, agent: selection.logicalAgent, runtime: selection.runtimeName, model: selection.modelId, nativeAgent: selection.nativeAgent, transport, ruleIds: route.ruleIds, reviewers: route.reviewers });
|
|
149
|
+
return { topology, route, selection };
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
if (config.agents.required)
|
|
153
|
+
throw error;
|
|
154
|
+
await recordEvent(root, config, "harness.agent.topology-fallback", { taskId: contract.task.id, error: String(error) });
|
|
155
|
+
return {};
|
|
156
|
+
} }
|
|
157
|
+
function withWorkerExecutionCheck(report, worker) { const checks = report.checks.filter((check) => check.id !== "agent.execution"); checks.unshift({ id: "agent.execution", category: "agent-runtime", status: worker.exitCode === 0 ? "PASS" : "FAIL", message: worker.exitCode === 0 ? `Agent ${worker.logicalAgent ?? worker.provider} completed successfully.` : `Agent runtime exited with code ${worker.exitCode}.`, details: worker.exitCode === 0 ? undefined : { stderr: worker.stderr.slice(-4000), stdout: worker.stdout.slice(-4000), logicalAgent: worker.logicalAgent, runtime: worker.runtime, model: worker.model } }); return { ...report, checks, status: checks.some((check) => check.status === "FAIL") ? "FAIL" : "PASS" }; }
|
|
158
|
+
function mergeChecks(report, extra) { const byId = new Map(report.checks.map((check) => [check.id, check])); for (const check of extra)
|
|
159
|
+
byId.set(check.id, check); const checks = [...byId.values()]; return { ...report, checks, status: checks.some((check) => check.status === "FAIL") ? "FAIL" : "PASS" }; }
|
|
160
|
+
async function verifyAfterWorker(workspaceRoot, controlRoot, config, contract) { await refreshGraphIfConfigured(workspaceRoot, config); const afterSnapshot = await snapshotGraph(workspaceRoot, config, contract.task.id, "after"); if (!afterSnapshot && config.codeIntelligence?.required)
|
|
161
|
+
throw new Error("Code intelligence is required but the Graphify after snapshot could not be created."); return verifyTask(workspaceRoot, config, contract, { stateRoot: controlRoot, policyRoot: controlRoot }); }
|
|
162
|
+
async function refreshGraphIfConfigured(root, config) { const command = config.codeIntelligence?.refreshCommand; if (!command)
|
|
163
|
+
return; const result = await runProcess(command, { cwd: root, timeoutMs: 300_000 }); if (result.exitCode !== 0 && config.codeIntelligence?.required)
|
|
164
|
+
throw new Error(`Code intelligence refresh failed: ${result.stderr || result.stdout}`); }
|
|
165
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/core/run.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { HarnessProjectConfig, RequirementTrace } from "./types.js";
|
|
2
|
+
export interface SddValidationResult {
|
|
3
|
+
ok: boolean;
|
|
4
|
+
missing: string[];
|
|
5
|
+
issues: string[];
|
|
6
|
+
requirements: RequirementTrace[];
|
|
7
|
+
}
|
|
8
|
+
export declare function createSddChange(root: string, taskId: string, title: string, config?: HarnessProjectConfig): Promise<string>;
|
|
9
|
+
export declare function validateSddChange(root: string, taskId: string, config?: HarnessProjectConfig): Promise<SddValidationResult>;
|
|
10
|
+
export declare function formatTraceabilityMatrix(requirements: RequirementTrace[]): string;
|
package/dist/core/sdd.js
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import YAML from "yaml";
|
|
4
|
+
import { getCurrentBranch } from "./git.js";
|
|
5
|
+
const requiredArtifacts = ["proposal.md", "spec.md", "design.md", "tasks.yaml", "acceptance.feature"];
|
|
6
|
+
export async function createSddChange(root, taskId, title, config) { const specsDir = config?.sdd?.specsDir ?? "specs"; const dir = path.join(root, specsDir, "changes", taskId); const requirementId = `${taskId}-R1`; const originatingBranch = await getCurrentBranch(root); await fs.mkdir(dir, { recursive: true }); const files = { "proposal.md": `# ${taskId}: ${title}\n\n## Problem\n\nTODO\n\n## Desired outcome\n\nTODO\n\n## Requirements\n\n- ${requirementId} — TODO observable requirement.\n\n## Scope\n\n## Non-goals\n`, "spec.md": `# Specification: ${title}\n\n## Requirements\n\n### ${requirementId}\n\nTODO observable behavior.\n\n## Invariants\n\nTODO\n`, "design.md": `# Design: ${title}\n\n## Current state\n\n## Proposed design\n\n## Requirement mapping\n\n- ${requirementId} — TODO implementation approach.\n\n## Data/API impact\n\n## Risks and trade-offs\n`, "tasks.yaml": `version: 1\ntask: ${taskId}\nitems:\n - id: 1\n title: Implement ${requirementId}\n status: pending\n requirements:\n - ${requirementId}\n`, "acceptance.feature": `@${taskId}\nFeature: ${title}\n\n Rule: TODO business rule\n\n @${requirementId}\n Scenario: TODO observable behavior\n Given TODO\n When TODO\n Then TODO\n` }; for (const [name, content] of Object.entries(files))
|
|
7
|
+
await writeIfMissing(path.join(dir, name), content); const contractsDir = path.join(root, config?.sdd?.contractsDir ?? ".harness/contracts"); await fs.mkdir(contractsDir, { recursive: true }); const contractPath = path.join(contractsDir, `${taskId}.yaml`); const contract = { version: 1, task: { id: taskId, title }, source: { proposal: relative(root, path.join(dir, "proposal.md")), spec: relative(root, path.join(dir, "spec.md")), design: relative(root, path.join(dir, "design.md")), tasks: relative(root, path.join(dir, "tasks.yaml")), acceptance: relative(root, path.join(dir, "acceptance.feature")) }, git: { baseRef: config?.validation?.baseRef ?? "main", ...(originatingBranch ? { originatingBranch } : {}) }, scope: { allowed: ["**"], forbidden: [], frozen: [] }, routing: { intent: "implement", domains: [], risk: "medium" }, requirements: [{ id: requirementId, description: "TODO observable requirement.", validators: ["gherkin"] }], constraints: { breakingApiChanges: false, newDependencies: false, schemaChanges: false }, repair: { maxAttempts: config?.orchestration?.worker?.maxRepairAttempts ?? 2 } }; await writeIfMissing(contractPath, YAML.stringify(contract)); return dir; }
|
|
8
|
+
export async function validateSddChange(root, taskId, config) { const specsDir = config?.sdd?.specsDir ?? "specs"; const dir = path.join(root, specsDir, "changes", taskId); const missing = []; const issues = []; const contents = new Map(); for (const name of requiredArtifacts) {
|
|
9
|
+
try {
|
|
10
|
+
const content = await fs.readFile(path.join(dir, name), "utf8");
|
|
11
|
+
if (!content.trim())
|
|
12
|
+
missing.push(name);
|
|
13
|
+
else
|
|
14
|
+
contents.set(name, content);
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
missing.push(name);
|
|
18
|
+
}
|
|
19
|
+
} if (missing.length)
|
|
20
|
+
return { ok: false, missing, issues, requirements: [] }; const spec = contents.get("spec.md") ?? ""; const proposal = contents.get("proposal.md") ?? ""; const design = contents.get("design.md") ?? ""; const acceptance = contents.get("acceptance.feature") ?? ""; const tasksRaw = contents.get("tasks.yaml") ?? ""; const requirementIds = extractRequirementIds(spec); if (!requirementIds.length)
|
|
21
|
+
issues.push("spec.md defines no traceable requirement IDs (expected e.g. CHANGE-123-R1 or REQ-001)."); const taskRequirements = extractTaskRequirements(tasksRaw); const contract = await tryLoadContract(root, taskId, config); if (!contract)
|
|
22
|
+
issues.push(`TaskContract ${taskId}.yaml is missing or unreadable.`); const known = config ? knownValidatorNames(config, contract) : undefined; const traces = requirementIds.map((id) => { const contractRequirement = contract?.requirements?.find((item) => item.id === id); const validators = normalizeValidators(contractRequirement); const trace = { id, proposal: proposal.includes(id), spec: true, design: design.includes(id), acceptance: containsTag(acceptance, id), tasks: taskRequirements.has(id), contract: Boolean(contractRequirement), validators }; for (const field of ["proposal", "design", "acceptance", "tasks", "contract"])
|
|
23
|
+
if (!trace[field])
|
|
24
|
+
issues.push(`${id} is not traceable through ${field}.`); if (!validators.length)
|
|
25
|
+
issues.push(`${id} has no validator declared in the TaskContract.`); if (known)
|
|
26
|
+
for (const validator of validators) {
|
|
27
|
+
const name = validator.split(":", 1)[0];
|
|
28
|
+
if (!known.has(name) && !known.has(validator))
|
|
29
|
+
issues.push(`${id} references unknown validator '${validator}'.`);
|
|
30
|
+
} return trace; }); for (const requirement of contract?.requirements ?? [])
|
|
31
|
+
if (!requirementIds.includes(requirement.id))
|
|
32
|
+
issues.push(`${requirement.id} exists in the TaskContract but not in spec.md.`); return { ok: missing.length === 0 && issues.length === 0, missing, issues, requirements: traces }; }
|
|
33
|
+
export function formatTraceabilityMatrix(requirements) { const header = ["Requirement", "Proposal", "Spec", "Design", "Acceptance", "Tasks", "Contract", "Validators"].join(" | "); const separator = ["---", "---", "---", "---", "---", "---", "---", "---"].join(" | "); const rows = requirements.map((item) => [item.id, mark(item.proposal), mark(item.spec), mark(item.design), mark(item.acceptance), mark(item.tasks), mark(item.contract), item.validators.join(", ") || "—"].join(" | ")); return [header, separator, ...rows].join("\n"); }
|
|
34
|
+
function extractRequirementIds(markdown) { const matches = markdown.matchAll(/(?:^|\s|[#`*-])((?:[A-Z][A-Z0-9_-]*-R\d+)|(?:REQ-\d+))(?:\b|`)/gm); return [...new Set([...matches].map((match) => match[1]))]; }
|
|
35
|
+
function containsTag(feature, id) { return new RegExp(`(^|\\s)@${escapeRegex(id)}(?=\\s|$)`, "m").test(feature); }
|
|
36
|
+
function extractTaskRequirements(raw) { try {
|
|
37
|
+
const value = YAML.parse(raw);
|
|
38
|
+
const ids = new Set();
|
|
39
|
+
collectRequirementValues(value, ids);
|
|
40
|
+
return ids;
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return new Set();
|
|
44
|
+
} }
|
|
45
|
+
function collectRequirementValues(value, ids, key) { if (Array.isArray(value)) {
|
|
46
|
+
for (const item of value)
|
|
47
|
+
collectRequirementValues(item, ids, key);
|
|
48
|
+
return;
|
|
49
|
+
} if (!value || typeof value !== "object") {
|
|
50
|
+
if ((key === "requirement" || key === "requirements") && typeof value === "string")
|
|
51
|
+
ids.add(value);
|
|
52
|
+
return;
|
|
53
|
+
} for (const [childKey, child] of Object.entries(value)) {
|
|
54
|
+
if ((childKey === "requirement" || childKey === "requirements") && typeof child === "string")
|
|
55
|
+
ids.add(child);
|
|
56
|
+
if (childKey === "requirements" && Array.isArray(child))
|
|
57
|
+
for (const item of child)
|
|
58
|
+
if (typeof item === "string")
|
|
59
|
+
ids.add(item);
|
|
60
|
+
collectRequirementValues(child, ids, childKey);
|
|
61
|
+
} }
|
|
62
|
+
async function tryLoadContract(root, taskId, config) { try {
|
|
63
|
+
const contractsDir = config?.sdd?.contractsDir ?? ".harness/contracts";
|
|
64
|
+
return YAML.parse(await fs.readFile(path.join(root, contractsDir, `${taskId}.yaml`), "utf8"));
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return undefined;
|
|
68
|
+
} }
|
|
69
|
+
function knownValidatorNames(config, contract) { const names = new Set(["build", "test", "lint", "typecheck", "architecture", "gherkin", "openapi", "graphify", "opengrep", "trivy", "playwright", "pact", "mutation", "property", "command"]); for (const item of config.validation?.commands ?? [])
|
|
70
|
+
names.add(item.id); for (const item of config.validation?.validators ?? []) {
|
|
71
|
+
names.add(item.id);
|
|
72
|
+
names.add(item.adapter);
|
|
73
|
+
} for (const item of contract?.verification?.commands ?? [])
|
|
74
|
+
names.add(item.id); for (const item of contract?.verification?.validators ?? []) {
|
|
75
|
+
names.add(item.id);
|
|
76
|
+
names.add(item.adapter);
|
|
77
|
+
} return names; }
|
|
78
|
+
function normalizeValidators(requirement) { return [...new Set([...(requirement?.validators ?? []), ...(requirement?.validator ? [requirement.validator] : [])])]; }
|
|
79
|
+
function relative(root, file) { return path.relative(root, file).replaceAll("\\", "/"); }
|
|
80
|
+
function mark(value) { return value ? "✓" : "✗"; }
|
|
81
|
+
function escapeRegex(value) { return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); }
|
|
82
|
+
async function writeIfMissing(file, content) { try {
|
|
83
|
+
await fs.access(file);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
await fs.writeFile(file, content);
|
|
87
|
+
} }
|
|
88
|
+
//# sourceMappingURL=sdd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdd.js","sourceRoot":"","sources":["../../src/core/sdd.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { HarnessProjectConfig, TaskContract, ValidationCheck } from "./types.js";
|
|
2
|
+
export declare function sealTask(root: string, config: HarnessProjectConfig, contract: TaskContract): Promise<string>;
|
|
3
|
+
export declare function verifyTaskSeal(root: string, contract: TaskContract, required?: boolean): Promise<ValidationCheck>;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
import fs from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
export async function sealTask(root, config, contract) {
|
|
5
|
+
const artifacts = await artifactPaths(root, config, contract);
|
|
6
|
+
const seal = {
|
|
7
|
+
version: 1,
|
|
8
|
+
taskId: contract.task.id,
|
|
9
|
+
createdAt: new Date().toISOString(),
|
|
10
|
+
artifacts: []
|
|
11
|
+
};
|
|
12
|
+
for (const relative of artifacts) {
|
|
13
|
+
const content = await fs.readFile(path.resolve(root, relative));
|
|
14
|
+
seal.artifacts.push({ path: relative, sha256: sha256(content) });
|
|
15
|
+
}
|
|
16
|
+
const output = sealPath(root, contract.task.id);
|
|
17
|
+
await fs.mkdir(path.dirname(output), { recursive: true });
|
|
18
|
+
await fs.writeFile(output, `${JSON.stringify(seal, null, 2)}\n`);
|
|
19
|
+
return output;
|
|
20
|
+
}
|
|
21
|
+
export async function verifyTaskSeal(root, contract, required = true) {
|
|
22
|
+
const file = sealPath(root, contract.task.id);
|
|
23
|
+
let seal;
|
|
24
|
+
try {
|
|
25
|
+
seal = JSON.parse(await fs.readFile(file, "utf8"));
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return {
|
|
29
|
+
id: "trust.seal",
|
|
30
|
+
category: "trust-boundary",
|
|
31
|
+
status: required ? "FAIL" : "WARN",
|
|
32
|
+
message: `No valid seal exists for ${contract.task.id}. Run engineering-harness seal ${contract.task.id} before delegation.`
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
const mismatches = [];
|
|
36
|
+
for (const artifact of seal.artifacts) {
|
|
37
|
+
try {
|
|
38
|
+
const current = await fs.readFile(path.resolve(root, artifact.path));
|
|
39
|
+
const actual = sha256(current);
|
|
40
|
+
if (actual !== artifact.sha256)
|
|
41
|
+
mismatches.push({ path: artifact.path, expected: artifact.sha256, actual });
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
mismatches.push({ path: artifact.path, expected: artifact.sha256 });
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
id: "trust.seal",
|
|
49
|
+
category: "trust-boundary",
|
|
50
|
+
status: mismatches.length ? "FAIL" : "PASS",
|
|
51
|
+
message: mismatches.length ? `Sealed artifacts changed after freeze: ${mismatches.map((x) => x.path).join(", ")}` : "TaskContract and sealed SDD artifacts match their SHA-256 seal.",
|
|
52
|
+
details: { mismatches, sealedAt: seal.createdAt }
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
async function artifactPaths(root, config, contract) {
|
|
56
|
+
const contractsDir = config.sdd?.contractsDir ?? ".harness/contracts";
|
|
57
|
+
const paths = [path.posix.join(contractsDir.replaceAll("\\", "/"), `${contract.task.id}.yaml`)];
|
|
58
|
+
for (const source of Object.values(contract.source ?? {})) {
|
|
59
|
+
if (source)
|
|
60
|
+
paths.push(source.replaceAll("\\", "/"));
|
|
61
|
+
}
|
|
62
|
+
const unique = [...new Set(paths)];
|
|
63
|
+
for (const relative of unique) {
|
|
64
|
+
await fs.access(path.resolve(root, relative));
|
|
65
|
+
}
|
|
66
|
+
return unique;
|
|
67
|
+
}
|
|
68
|
+
function sealPath(root, taskId) {
|
|
69
|
+
return path.join(root, ".harness", "seals", `${taskId}.json`);
|
|
70
|
+
}
|
|
71
|
+
function sha256(content) {
|
|
72
|
+
return crypto.createHash("sha256").update(content).digest("hex");
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=seal.js.map
|