@jterrats/open-orchestra 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/dist/autonomous-workflow.js +9 -0
  3. package/dist/autonomous-workflow.js.map +1 -1
  4. package/dist/benchmark.d.ts +2 -1
  5. package/dist/benchmark.js +70 -0
  6. package/dist/benchmark.js.map +1 -1
  7. package/dist/cli.js +19 -2
  8. package/dist/cli.js.map +1 -1
  9. package/dist/commands.d.ts +3 -0
  10. package/dist/commands.js +132 -21
  11. package/dist/commands.js.map +1 -1
  12. package/dist/constants.js +5 -0
  13. package/dist/constants.js.map +1 -1
  14. package/dist/defaults.d.ts +6 -0
  15. package/dist/defaults.js +6 -0
  16. package/dist/defaults.js.map +1 -1
  17. package/dist/model-providers.d.ts +26 -1
  18. package/dist/model-providers.js +257 -1
  19. package/dist/model-providers.js.map +1 -1
  20. package/dist/notifications.d.ts +31 -0
  21. package/dist/notifications.js +165 -0
  22. package/dist/notifications.js.map +1 -0
  23. package/dist/phase-executor.d.ts +18 -0
  24. package/dist/phase-executor.js +218 -0
  25. package/dist/phase-executor.js.map +1 -0
  26. package/dist/release-commands.d.ts +10 -0
  27. package/dist/release-commands.js +116 -0
  28. package/dist/release-commands.js.map +1 -1
  29. package/dist/sprint-metrics.d.ts +9 -0
  30. package/dist/sprint-metrics.js +203 -0
  31. package/dist/sprint-metrics.js.map +1 -0
  32. package/dist/types.d.ts +98 -0
  33. package/dist/types.js.map +1 -1
  34. package/dist/workflow-services.d.ts +3 -1
  35. package/dist/workflow-services.js +16 -6
  36. package/dist/workflow-services.js.map +1 -1
  37. package/docs/autonomous-workflow.md +28 -1
  38. package/docs/benchmark.md +18 -0
  39. package/docs/runtime-llm-flow.md +34 -9
  40. package/package.json +3 -4
@@ -0,0 +1,218 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { ensureDir, resolveWorkflowPath } from "./fs-utils.js";
4
+ import { renderSkills } from "./skills.js";
5
+ import { appendEvent, readEvents, writeArtifact } from "./workspace.js";
6
+ import { checkUsageBudget, completeWithProviderFallback, getTaskContext, getWorkflowConfig, recordDecision, recordModelProvenance, } from "./workflow-services.js";
7
+ const DEFAULT_ARCHITECT_SIZING = "m [3 points]";
8
+ export async function phaseExecutionMode(root, role) {
9
+ const routing = await phaseRouting(root, role);
10
+ return routing.provider === "none" ? "deterministic" : "llm";
11
+ }
12
+ export async function executePhaseWithLlm({ root, run, phase, phaseIndex, }) {
13
+ const budget = await checkUsageBudget(run.taskId, root);
14
+ if (!budget.passed) {
15
+ throw new Error(`budget exceeded before ${phase.phase}: ${budget.violations.join("; ")}`);
16
+ }
17
+ const routing = await phaseRouting(root, phase.role);
18
+ if (routing.provider === "none") {
19
+ return {
20
+ mode: "deterministic",
21
+ outcome: { kind: "done", notes: phase.summary },
22
+ };
23
+ }
24
+ const prompt = await buildPhasePrompt({ root, run, phase, phaseIndex });
25
+ const result = await completeWithProviderFallback(routing, prompt.user, {
26
+ root,
27
+ taskId: run.taskId,
28
+ role: phase.role,
29
+ jsonMode: true,
30
+ providerMode: "real",
31
+ });
32
+ const response = result.response;
33
+ const output = parsePhaseOutput(response.content);
34
+ const artifact = await writePhaseArtifact({
35
+ root,
36
+ run,
37
+ phase,
38
+ response,
39
+ output,
40
+ fallbackUsed: result.fallbackUsed,
41
+ });
42
+ await recordModelProvenance({
43
+ task: run.taskId,
44
+ role: phase.role,
45
+ provider: response.provider,
46
+ model: response.model,
47
+ promptId: `workflow:${run.id}:${phase.phase}`,
48
+ responseId: response.id,
49
+ inputTokens: response.usage.inputTokens,
50
+ outputTokens: response.usage.outputTokens,
51
+ estimatedCostUsd: 0,
52
+ finishReason: response.finishReason,
53
+ }, root);
54
+ await appendEvent(root, {
55
+ type: "AUTONOMOUS_PHASE_LLM_COMPLETED",
56
+ taskId: run.taskId,
57
+ actor: phase.role,
58
+ summary: `LLM phase completed: ${phase.phase}`,
59
+ artifacts: [artifact],
60
+ metadata: {
61
+ runId: run.id,
62
+ phase: phase.phase,
63
+ provider: response.provider,
64
+ model: response.model,
65
+ responseId: response.id,
66
+ fallbackUsed: result.fallbackUsed,
67
+ },
68
+ });
69
+ if (phase.role === "architect") {
70
+ await recordArchitectSizing(root, run.taskId, output);
71
+ }
72
+ const outcome = phaseOutcome(phase, output);
73
+ return { mode: "llm", artifact, output, outcome };
74
+ }
75
+ export async function buildPhasePrompt({ root, run, phase, phaseIndex, }) {
76
+ const context = await getTaskContext(run.taskId, root);
77
+ const skills = await renderSkills({
78
+ target: "generic",
79
+ taskId: run.taskId,
80
+ skillIds: undefined,
81
+ root,
82
+ });
83
+ const priorHandoff = await latestHandoffContent(root, run.taskId);
84
+ const fakeResponse = defaultStructuredOutput(phase);
85
+ return {
86
+ system: [
87
+ `You are the ${phase.role} phase agent for Open Orchestra.`,
88
+ skills.content,
89
+ ].join("\n\n"),
90
+ user: [
91
+ "Use the task context and prior handoff to produce structured phase output.",
92
+ `Run: ${run.id}`,
93
+ `Phase index: ${phaseIndex}`,
94
+ `Phase: ${phase.phase}`,
95
+ `Role: ${phase.role}`,
96
+ "",
97
+ "Task context JSON:",
98
+ JSON.stringify(context, null, 2),
99
+ "",
100
+ "Prior handoff:",
101
+ priorHandoff || "No prior handoff.",
102
+ "",
103
+ "Return JSON only with this shape:",
104
+ JSON.stringify(defaultStructuredOutput(phase), null, 2),
105
+ "",
106
+ `FAKE_JSON_RESPONSE:${JSON.stringify(fakeResponse)}`,
107
+ ].join("\n"),
108
+ };
109
+ }
110
+ export function parsePhaseOutput(content) {
111
+ const parsed = JSON.parse(extractJson(content));
112
+ return {
113
+ summary: stringOrDefault(parsed.summary, "Phase completed"),
114
+ notes: stringOrDefault(parsed.notes, parsed.summary ?? "Phase completed"),
115
+ verdict: parsed.verdict === "fail" ? "fail" : "pass",
116
+ findings: Array.isArray(parsed.findings)
117
+ ? parsed.findings.map((finding) => String(finding))
118
+ : [],
119
+ decisions: Array.isArray(parsed.decisions)
120
+ ? parsed.decisions.map((decision) => String(decision))
121
+ : [],
122
+ evidence: Array.isArray(parsed.evidence)
123
+ ? parsed.evidence.map((item) => String(item))
124
+ : [],
125
+ handoff: stringOrDefault(parsed.handoff, parsed.notes ?? "Phase handoff ready"),
126
+ sizing: typeof parsed.sizing === "string" && parsed.sizing.trim()
127
+ ? parsed.sizing
128
+ : DEFAULT_ARCHITECT_SIZING,
129
+ };
130
+ }
131
+ async function phaseRouting(root, role) {
132
+ const config = await getWorkflowConfig(root);
133
+ return config.providers.byRole?.[role] ?? config.providers.defaults;
134
+ }
135
+ function phaseOutcome(phase, output) {
136
+ if (phase.phase === "qa" && output.verdict === "fail") {
137
+ return {
138
+ kind: "qa_fail",
139
+ notes: output.findings.join("; ") || output.notes,
140
+ };
141
+ }
142
+ return { kind: "done", notes: output.notes };
143
+ }
144
+ async function recordArchitectSizing(root, taskId, output) {
145
+ await recordDecision({
146
+ task: taskId,
147
+ owner: "architect",
148
+ title: "Story sizing",
149
+ context: output.summary,
150
+ decision: output.sizing ?? DEFAULT_ARCHITECT_SIZING,
151
+ consequences: output.handoff,
152
+ status: "accepted",
153
+ }, root);
154
+ }
155
+ async function writePhaseArtifact({ root, run, phase, response, output, fallbackUsed, }) {
156
+ const directory = path.join("runs", run.taskId, phase.phase);
157
+ await ensureDir(resolveWorkflowPath(root, directory));
158
+ return writeArtifact(root, directory, `${run.id}-${phase.phase}.md`, [
159
+ `# ${phase.phase}: ${run.taskId}`,
160
+ "",
161
+ `- Role: ${phase.role}`,
162
+ `- Provider: ${response.provider}`,
163
+ `- Model: ${response.model}`,
164
+ `- Response: ${response.id}`,
165
+ `- Fallback used: ${String(fallbackUsed)}`,
166
+ "",
167
+ "## Summary",
168
+ output.summary,
169
+ "",
170
+ "## Notes",
171
+ output.notes,
172
+ "",
173
+ "## Structured Output",
174
+ "```json",
175
+ JSON.stringify(output, null, 2),
176
+ "```",
177
+ "",
178
+ ].join("\n"));
179
+ }
180
+ async function latestHandoffContent(root, taskId) {
181
+ const events = await readEvents(root);
182
+ const artifact = [...events]
183
+ .reverse()
184
+ .find((event) => event.taskId === taskId && event.type === "HANDOFF_READY")
185
+ ?.artifacts?.[0];
186
+ if (!artifact)
187
+ return "";
188
+ return readFile(path.join(root, artifact), "utf8").catch(() => "");
189
+ }
190
+ function defaultStructuredOutput(phase) {
191
+ const output = {
192
+ summary: `${phase.role} completed ${phase.phase}`,
193
+ notes: phase.summary,
194
+ verdict: "pass",
195
+ findings: [],
196
+ decisions: phase.role === "architect" ? ["Use incremental implementation"] : [],
197
+ evidence: [],
198
+ handoff: `${phase.phase} output is ready for the next phase.`,
199
+ };
200
+ if (phase.role === "architect") {
201
+ output.sizing = DEFAULT_ARCHITECT_SIZING;
202
+ }
203
+ return output;
204
+ }
205
+ function extractJson(content) {
206
+ const trimmed = content.trim();
207
+ if (trimmed.startsWith("{"))
208
+ return trimmed;
209
+ const start = trimmed.indexOf("{");
210
+ const end = trimmed.lastIndexOf("}");
211
+ if (start >= 0 && end > start)
212
+ return trimmed.slice(start, end + 1);
213
+ throw new Error("phase provider response did not contain JSON output");
214
+ }
215
+ function stringOrDefault(value, fallback) {
216
+ return typeof value === "string" && value.trim() ? value : fallback;
217
+ }
218
+ //# sourceMappingURL=phase-executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"phase-executor.js","sourceRoot":"","sources":["../src/phase-executor.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,14 @@
1
1
  import type { CliIo, CliOptions } from "./types.js";
2
+ export interface ReleaseCheck {
3
+ name: string;
4
+ passed: boolean;
5
+ detail?: string;
6
+ }
7
+ export interface ReleaseCheckResult {
8
+ passed: boolean;
9
+ checks: ReleaseCheck[];
10
+ }
11
+ export declare function releaseCheckCommand(options: CliOptions, io: CliIo): Promise<void>;
2
12
  export declare function releaseCandidateCommand(options: CliOptions, io: CliIo): Promise<void>;
3
13
  export declare function releaseTagCommand(options: CliOptions, io: CliIo): Promise<void>;
4
14
  export declare function releaseEvidenceCommand(options: CliOptions, io: CliIo): Promise<void>;
@@ -1,5 +1,121 @@
1
+ import { execFile, spawn } from "node:child_process";
2
+ import { readFile } from "node:fs/promises";
3
+ import { promisify } from "node:util";
1
4
  import { requireArg } from "./args.js";
2
5
  import { attachReleaseEvidence, generateCandidateReleasePlan, recordReleaseTagApproval, writeCandidateReleasePlan, } from "./release-candidate.js";
6
+ const execFileAsync = promisify(execFile);
7
+ export async function releaseCheckCommand(options, io) {
8
+ const root = typeof options.root === "string" ? options.root : process.cwd();
9
+ const result = await runReleaseChecks(root);
10
+ if (options.json) {
11
+ io.log(JSON.stringify(result, null, 2));
12
+ return;
13
+ }
14
+ for (const check of result.checks) {
15
+ const icon = check.passed ? "✓" : "✗";
16
+ const detail = check.detail ? ` — ${check.detail}` : "";
17
+ io.log(` ${icon} ${check.name}${detail}`);
18
+ }
19
+ if (result.passed) {
20
+ io.log("\nRelease check passed.");
21
+ }
22
+ else {
23
+ const failed = result.checks.filter((c) => !c.passed).length;
24
+ io.log(`\nRelease check failed (${failed} issue${failed === 1 ? "" : "s"}).`);
25
+ process.exitCode = 1;
26
+ }
27
+ }
28
+ async function runReleaseChecks(root) {
29
+ const checks = [];
30
+ // 1. Lint
31
+ checks.push(await runScript(root, "lint", "npm run lint"));
32
+ // 2. Typecheck
33
+ checks.push(await runScript(root, "typecheck", "npm run typecheck"));
34
+ // 3. Secret scan
35
+ checks.push(await runScript(root, "secret-scan", "npm run secret-scan"));
36
+ // 4. Tests
37
+ checks.push(await runScript(root, "tests", "npm test"));
38
+ // 5. package.json version matches latest git tag
39
+ checks.push(await checkVersionMatchesTag(root));
40
+ // 6. No uncommitted changes
41
+ checks.push(await checkCleanWorkingTree(root));
42
+ return {
43
+ passed: checks.every((c) => c.passed),
44
+ checks,
45
+ };
46
+ }
47
+ async function runScript(root, name, cmd) {
48
+ const [bin, ...args] = cmd.split(" ");
49
+ try {
50
+ await runProcess(bin, args, root);
51
+ return { name, passed: true };
52
+ }
53
+ catch (err) {
54
+ const msg = err instanceof Error
55
+ ? (err.message.split("\n")[0] ?? err.message)
56
+ : String(err);
57
+ return { name, passed: false, detail: msg };
58
+ }
59
+ }
60
+ function runProcess(command, args, cwd) {
61
+ return new Promise((resolve, reject) => {
62
+ const child = spawn(command, args, { cwd, stdio: "ignore" });
63
+ child.on("error", reject);
64
+ child.on("close", (code, signal) => {
65
+ if (code === 0) {
66
+ resolve();
67
+ return;
68
+ }
69
+ const reason = signal !== null ? `signal ${signal}` : `exit code ${code ?? "unknown"}`;
70
+ reject(new Error(`Command failed: ${command} ${args.join(" ")} (${reason})`));
71
+ });
72
+ });
73
+ }
74
+ async function checkVersionMatchesTag(root) {
75
+ const name = "version matches latest tag";
76
+ try {
77
+ const pkg = JSON.parse(await readFile(`${root}/package.json`, "utf8"));
78
+ const version = pkg.version;
79
+ if (!version)
80
+ return { name, passed: false, detail: "no version in package.json" };
81
+ const { stdout } = await execFileAsync("git", ["tag", "--sort=-creatordate"], { cwd: root });
82
+ const tags = stdout.trim().split("\n").filter(Boolean);
83
+ const latest = tags.find((t) => t.match(/^v\d+\.\d+\.\d+$/));
84
+ if (!latest)
85
+ return { name, passed: false, detail: "no semver tags found" };
86
+ const tagVersion = latest.slice(1);
87
+ if (tagVersion === version)
88
+ return { name, passed: true };
89
+ return {
90
+ name,
91
+ passed: false,
92
+ detail: `package.json=${version} latest tag=${latest}`,
93
+ };
94
+ }
95
+ catch (err) {
96
+ return { name, passed: false, detail: String(err) };
97
+ }
98
+ }
99
+ async function checkCleanWorkingTree(root) {
100
+ const name = "clean working tree";
101
+ try {
102
+ const { stdout } = await execFileAsync("git", ["status", "--porcelain"], {
103
+ cwd: root,
104
+ });
105
+ const dirty = stdout.trim();
106
+ if (!dirty)
107
+ return { name, passed: true };
108
+ const lines = dirty.split("\n").length;
109
+ return {
110
+ name,
111
+ passed: false,
112
+ detail: `${lines} uncommitted file${lines === 1 ? "" : "s"}`,
113
+ };
114
+ }
115
+ catch (err) {
116
+ return { name, passed: false, detail: String(err) };
117
+ }
118
+ }
3
119
  export async function releaseCandidateCommand(options, io) {
4
120
  const version = stringOption(options.version);
5
121
  if (options["dry-run"]) {
@@ -1 +1 @@
1
- {"version":3,"file":"release-commands.js","sourceRoot":"","sources":["../src/release-commands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EACL,qBAAqB,EACrB,4BAA4B,EAC5B,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,wBAAwB,CAAC;AAGhC,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,OAAmB,EACnB,EAAS;IAET,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9C,IAAI,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,MAAM,4BAA4B,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;QAC7D,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACtC,OAAO;IACT,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,yBAAyB,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;IAC5D,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACxC,OAAO;IACT,CAAC;IACD,EAAE,CAAC,GAAG,CAAC,kCAAkC,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,OAAmB,EACnB,EAAS;IAET,MAAM,KAAK,GAAG,MAAM,wBAAwB,CAAC;QAC3C,OAAO,EAAE,UAAU,CAAC,OAAO,EAAE,SAAS,CAAC;QACvC,QAAQ,EAAE,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC;QACxC,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;KACnC,CAAC,CAAC;IACH,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACvC,OAAO;IACT,CAAC;IACD,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AACxB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,OAAmB,EACnB,EAAS;IAET,MAAM,KAAK,GAAG,MAAM,qBAAqB,CAAC;QACxC,IAAI,EAAE,wBAAwB,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC3D,OAAO,EAAE,UAAU,CAAC,OAAO,EAAE,SAAS,CAAC;QACvC,YAAY,EAAE,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC;KACzC,CAAC,CAAC;IACH,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACvC,OAAO;IACT,CAAC;IACD,EAAE,CAAC,GAAG,CAAC,6BAA6B,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;AACxD,CAAC;AAED,SAAS,wBAAwB,CAAC,KAAa;IAC7C,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,UAAU,EAAE,CAAC;QAC9C,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;AACrE,CAAC;AAED,SAAS,YAAY,CACnB,KAA8C;IAE9C,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACvD,CAAC"}
1
+ {"version":3,"file":"release-commands.js","sourceRoot":"","sources":["../src/release-commands.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { CalibrationReport, SprintRecord, SprintVelocity, SprintVelocityReport } from "./types.js";
2
+ export declare const SPRINTS_FILE = "sprints.jsonl";
3
+ export declare function sprintsPath(root: string): string;
4
+ export declare function startSprint(root: string, sprintId: string, taskIds: string[]): Promise<SprintRecord>;
5
+ export declare function closeSprint(root: string, sprintId: string): Promise<SprintRecord>;
6
+ export declare function listSprints(root: string): Promise<SprintRecord[]>;
7
+ export declare function computeSprintVelocity(root: string, sprintId: string): Promise<SprintVelocity>;
8
+ export declare function velocityTrend(root: string, limit: number): Promise<SprintVelocityReport>;
9
+ export declare function calibrationReport(root: string): Promise<CalibrationReport>;
@@ -0,0 +1,203 @@
1
+ import { existsSync } from "node:fs";
2
+ import { readFile } from "node:fs/promises";
3
+ import { appendJsonLine, resolveWorkflowPath } from "./fs-utils.js";
4
+ import { appendEvent } from "./workspace.js";
5
+ import { computeBenchmark, listEstimates } from "./benchmark.js";
6
+ export const SPRINTS_FILE = "sprints.jsonl";
7
+ const POINTS_BY_SIZE = { xs: 1, s: 2, m: 3, l: 5, xl: 8 };
8
+ const CALIBRATION_BIAS_THRESHOLD_PCT = 30;
9
+ const CALIBRATION_MIN_STORIES = 3;
10
+ export function sprintsPath(root) {
11
+ return resolveWorkflowPath(root, SPRINTS_FILE);
12
+ }
13
+ export async function startSprint(root, sprintId, taskIds) {
14
+ if (taskIds.length === 0) {
15
+ throw new Error("--tasks requires at least one task id");
16
+ }
17
+ const existing = await listSprints(root);
18
+ const latest = existing.find((sprint) => sprint.id === sprintId);
19
+ if (latest?.status === "active") {
20
+ throw new Error(`sprint already active: ${sprintId}`);
21
+ }
22
+ const now = new Date().toISOString();
23
+ const record = {
24
+ id: sprintId,
25
+ taskIds,
26
+ status: "active",
27
+ startedAt: now,
28
+ closedAt: null,
29
+ };
30
+ await appendJsonLine(sprintsPath(root), record);
31
+ await appendEvent(root, {
32
+ type: "SPRINT_STARTED",
33
+ actor: "pm",
34
+ summary: `Sprint started: ${sprintId}`,
35
+ metadata: { sprintId, taskIds },
36
+ });
37
+ return record;
38
+ }
39
+ export async function closeSprint(root, sprintId) {
40
+ const latest = (await listSprints(root)).find((sprint) => sprint.id === sprintId);
41
+ if (!latest) {
42
+ throw new Error(`sprint not found: ${sprintId}`);
43
+ }
44
+ if (latest.status === "closed") {
45
+ return latest;
46
+ }
47
+ const record = {
48
+ ...latest,
49
+ status: "closed",
50
+ closedAt: new Date().toISOString(),
51
+ };
52
+ await appendJsonLine(sprintsPath(root), record);
53
+ await appendEvent(root, {
54
+ type: "SPRINT_CLOSED",
55
+ actor: "pm",
56
+ summary: `Sprint closed: ${sprintId}`,
57
+ metadata: { sprintId, taskIds: record.taskIds },
58
+ });
59
+ return record;
60
+ }
61
+ export async function listSprints(root) {
62
+ const file = sprintsPath(root);
63
+ if (!existsSync(file))
64
+ return [];
65
+ const lines = (await readFile(file, "utf8"))
66
+ .split("\n")
67
+ .filter((line) => line.trim() !== "");
68
+ const latest = new Map();
69
+ for (const line of lines) {
70
+ const sprint = JSON.parse(line);
71
+ latest.set(sprint.id, sprint);
72
+ }
73
+ return [...latest.values()].sort((a, b) => a.startedAt.localeCompare(b.startedAt));
74
+ }
75
+ export async function computeSprintVelocity(root, sprintId) {
76
+ const sprint = (await listSprints(root)).find((item) => item.id === sprintId);
77
+ if (!sprint) {
78
+ throw new Error(`sprint not found: ${sprintId}`);
79
+ }
80
+ const completed = [];
81
+ for (const taskId of sprint.taskIds) {
82
+ const benchmark = await computeBenchmark(root, taskId).catch(() => null);
83
+ if (benchmark?.status === "complete" && benchmark.actualDays !== null) {
84
+ completed.push(benchmark);
85
+ }
86
+ }
87
+ return {
88
+ sprintId,
89
+ taskIds: sprint.taskIds,
90
+ storiesCompleted: completed.length,
91
+ pointsCompleted: completed.reduce((sum, story) => sum + POINTS_BY_SIZE[story.sizingLabel], 0),
92
+ };
93
+ }
94
+ export async function velocityTrend(root, limit) {
95
+ const closed = (await listSprints(root))
96
+ .filter((sprint) => sprint.status === "closed")
97
+ .slice(-limit);
98
+ const sprints = [];
99
+ for (const sprint of closed) {
100
+ sprints.push(await computeSprintVelocity(root, sprint.id));
101
+ }
102
+ return {
103
+ sprints,
104
+ trend: computeTrend(sprints.map((s) => s.pointsCompleted)),
105
+ };
106
+ }
107
+ export async function calibrationReport(root) {
108
+ const estimates = await listEstimates(root);
109
+ const byRole = new Map();
110
+ for (const estimate of estimates) {
111
+ const benchmark = await computeBenchmark(root, estimate.taskId).catch(() => null);
112
+ if (benchmark?.status !== "complete" || benchmark.actualDays === null) {
113
+ continue;
114
+ }
115
+ const current = byRole.get(estimate.declaredBy) ?? {
116
+ declaredTotal: 0,
117
+ actualTotal: 0,
118
+ errorPctTotal: 0,
119
+ stories: 0,
120
+ };
121
+ const errorPct = ((benchmark.actualDays - estimate.soloEstimateDays) /
122
+ estimate.soloEstimateDays) *
123
+ 100;
124
+ byRole.set(estimate.declaredBy, {
125
+ declaredTotal: current.declaredTotal + estimate.soloEstimateDays,
126
+ actualTotal: current.actualTotal + benchmark.actualDays,
127
+ errorPctTotal: current.errorPctTotal + errorPct,
128
+ stories: current.stories + 1,
129
+ });
130
+ }
131
+ const roles = [];
132
+ for (const [role, stats] of byRole) {
133
+ const avgErrorPct = Math.round(stats.errorPctTotal / stats.stories);
134
+ const bias = calibrationBias(stats.stories, avgErrorPct);
135
+ const lessonRecorded = bias === "over" || bias === "under";
136
+ if (lessonRecorded) {
137
+ await recordCalibrationLesson(root, role, bias, avgErrorPct);
138
+ }
139
+ roles.push({
140
+ role,
141
+ stories: stats.stories,
142
+ avgDeclaredDays: round(stats.declaredTotal / stats.stories),
143
+ avgActualDays: round(stats.actualTotal / stats.stories),
144
+ avgErrorPct,
145
+ bias,
146
+ lessonRecorded,
147
+ });
148
+ }
149
+ return { roles: roles.sort((a, b) => a.role.localeCompare(b.role)) };
150
+ }
151
+ async function recordCalibrationLesson(root, role, bias, avgErrorPct) {
152
+ const eventsPath = resolveWorkflowPath(root, "events.jsonl");
153
+ const content = existsSync(eventsPath)
154
+ ? await readFile(eventsPath, "utf8")
155
+ : "";
156
+ const signature = `calibration:${role}:${bias}`;
157
+ if (content.includes(signature)) {
158
+ return;
159
+ }
160
+ await appendEvent(root, {
161
+ type: "LESSON_RECORDED",
162
+ actor: "system",
163
+ summary: `Calibration lesson recorded for ${role}`,
164
+ metadata: {
165
+ signature,
166
+ role,
167
+ bias,
168
+ avgErrorPct,
169
+ recommendation: bias === "under"
170
+ ? "Increase future estimates or split stories before commitment."
171
+ : "Reduce future estimates or raise confidence thresholds before commitment.",
172
+ },
173
+ });
174
+ }
175
+ function calibrationBias(stories, avgErrorPct) {
176
+ if (stories < CALIBRATION_MIN_STORIES)
177
+ return "insufficient_data";
178
+ if (avgErrorPct > CALIBRATION_BIAS_THRESHOLD_PCT)
179
+ return "under";
180
+ if (avgErrorPct < -CALIBRATION_BIAS_THRESHOLD_PCT)
181
+ return "over";
182
+ return "balanced";
183
+ }
184
+ function computeTrend(points) {
185
+ if (points.length < 3)
186
+ return "insufficient_data";
187
+ const half = Math.floor(points.length / 2);
188
+ const firstHalf = average(points.slice(0, half));
189
+ const secondHalf = average(points.slice(-half));
190
+ const delta = secondHalf - firstHalf;
191
+ if (delta > firstHalf * 0.1)
192
+ return "improving";
193
+ if (delta < -firstHalf * 0.1)
194
+ return "declining";
195
+ return "stable";
196
+ }
197
+ function average(values) {
198
+ return values.reduce((sum, value) => sum + value, 0) / values.length;
199
+ }
200
+ function round(value) {
201
+ return Math.round(value * 100) / 100;
202
+ }
203
+ //# sourceMappingURL=sprint-metrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sprint-metrics.js","sourceRoot":"","sources":["../src/sprint-metrics.ts"],"names":[],"mappings":"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"}