@trieungoctam/speckit 0.2.0 → 0.3.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 (52) hide show
  1. package/README.md +37 -5
  2. package/dist/adapters/antigravity-adapter.js +5 -5
  3. package/dist/adapters/claude-code-adapter.js +10 -5
  4. package/dist/adapters/codex-adapter.js +7 -3
  5. package/dist/adapters/cursor-adapter.js +10 -3
  6. package/dist/adapters/opencode-adapter.js +1 -0
  7. package/dist/cli.js +32 -0
  8. package/dist/commands/context.js +56 -22
  9. package/dist/commands/doctor.js +2 -1
  10. package/dist/commands/graph.d.ts +7 -0
  11. package/dist/commands/graph.js +51 -0
  12. package/dist/commands/init.js +3 -1
  13. package/dist/commands/memory.d.ts +6 -0
  14. package/dist/commands/memory.js +11 -0
  15. package/dist/commands/plan.js +19 -2
  16. package/dist/commands/quick.js +20 -2
  17. package/dist/commands/ready.d.ts +7 -0
  18. package/dist/commands/ready.js +20 -0
  19. package/dist/commands/run.js +15 -2
  20. package/dist/commands/session.d.ts +9 -0
  21. package/dist/commands/session.js +49 -0
  22. package/dist/commands/sprint.d.ts +7 -0
  23. package/dist/commands/sprint.js +54 -0
  24. package/dist/commands/start.js +4 -3
  25. package/dist/commands/sync.js +5 -2
  26. package/dist/commands/triage.js +2 -15
  27. package/dist/core/agent-scaffold.d.ts +2 -0
  28. package/dist/core/agent-scaffold.js +57 -0
  29. package/dist/core/beads-mirror.d.ts +3 -0
  30. package/dist/core/beads-mirror.js +46 -0
  31. package/dist/core/memory.d.ts +1 -0
  32. package/dist/core/memory.js +47 -0
  33. package/dist/core/readiness.d.ts +13 -0
  34. package/dist/core/readiness.js +120 -0
  35. package/dist/core/scaffold.js +72 -43
  36. package/dist/core/session-manager.d.ts +15 -0
  37. package/dist/core/session-manager.js +139 -0
  38. package/dist/core/skill-catalog.d.ts +2 -0
  39. package/dist/core/skill-catalog.js +177 -0
  40. package/dist/core/story.d.ts +5 -0
  41. package/dist/core/story.js +34 -0
  42. package/dist/core/synced-stories.d.ts +8 -0
  43. package/dist/core/synced-stories.js +17 -0
  44. package/dist/core/templates.d.ts +2 -0
  45. package/dist/core/templates.js +54 -0
  46. package/docs/development-roadmap.md +9 -7
  47. package/docs/product-contract.md +7 -4
  48. package/docs/project-changelog.md +66 -0
  49. package/docs/release-checklist.md +1 -1
  50. package/docs/spec-enterprise-harness-plan.md +18 -1
  51. package/docs/workflow-model.md +23 -0
  52. package/package.json +1 -1
@@ -0,0 +1,9 @@
1
+ export type SessionOptions = {
2
+ root: string;
3
+ action: string;
4
+ target?: string;
5
+ note?: string;
6
+ json?: boolean;
7
+ stdout?: Pick<typeof console, "log" | "error">;
8
+ };
9
+ export declare function sessionCommand(options: SessionOptions): Promise<number>;
@@ -0,0 +1,49 @@
1
+ import { checkpointSession, compactSession, ensureSession, resumeSession, sessionStatus, } from "../core/session-manager.js";
2
+ export async function sessionCommand(options) {
3
+ const stdout = options.stdout ?? console;
4
+ switch (options.action) {
5
+ case "start": {
6
+ const session = await ensureSession(options.root, options.note ?? options.target ?? "long session");
7
+ stdout.log(session.id);
8
+ stdout.log(`${session.dir}/handoff.md`);
9
+ return 0;
10
+ }
11
+ case "checkpoint": {
12
+ const session = await checkpointSession({
13
+ root: options.root,
14
+ note: options.note ?? options.target,
15
+ story: options.target,
16
+ });
17
+ stdout.log(`Checkpointed ${session.id}`);
18
+ return 0;
19
+ }
20
+ case "compact": {
21
+ const session = await compactSession(options.root);
22
+ stdout.log(`${session.dir}/summary.md`);
23
+ return 0;
24
+ }
25
+ case "resume": {
26
+ const session = await resumeSession(options.root, options.target);
27
+ if (!session) {
28
+ stdout.error("No Speckit session to resume.");
29
+ return 1;
30
+ }
31
+ stdout.log(session.id);
32
+ stdout.log(`${session.dir}/handoff.md`);
33
+ return 0;
34
+ }
35
+ case "status": {
36
+ const status = await sessionStatus(options.root);
37
+ stdout.log(options.json ? JSON.stringify(status, null, 2) : renderStatus(status));
38
+ return status.status === "missing" ? 1 : 0;
39
+ }
40
+ default:
41
+ stdout.error("Usage: speckit session start|checkpoint|compact|resume|status");
42
+ return 1;
43
+ }
44
+ }
45
+ function renderStatus(status) {
46
+ if (status.status === "missing")
47
+ return "Spec session: missing";
48
+ return `Spec session: ${status.id}\nState: ${status.state}\nSummary: ${status.summary}\nHandoff: ${status.handoff}`;
49
+ }
@@ -0,0 +1,7 @@
1
+ export type SprintOptions = {
2
+ root: string;
3
+ action: string;
4
+ json?: boolean;
5
+ stdout?: Pick<typeof console, "log" | "error">;
6
+ };
7
+ export declare function sprintCommand(options: SprintOptions): Promise<number>;
@@ -0,0 +1,54 @@
1
+ import { markdown, text, writeManagedFiles } from "../core/managed-files.js";
2
+ import { readSyncedStories, selectableStories } from "../core/synced-stories.js";
3
+ export async function sprintCommand(options) {
4
+ const stdout = options.stdout ?? console;
5
+ const stories = await readSyncedStories(options.root);
6
+ switch (options.action) {
7
+ case "plan": {
8
+ const selected = selectableStories(stories);
9
+ await writeManagedFiles(options.root, [
10
+ {
11
+ path: ".speckit/sprint/status.yaml",
12
+ content: text(renderStatus(stories)),
13
+ },
14
+ {
15
+ path: ".speckit/sprint/plan.md",
16
+ content: markdown(renderPlan(selected)),
17
+ },
18
+ ], true);
19
+ stdout.log(`Planned sprint with ${selected.length} selectable stories`);
20
+ return 0;
21
+ }
22
+ case "next": {
23
+ const next = selectableStories(stories)[0] ?? null;
24
+ stdout.log(options.json ? JSON.stringify({ next }, null, 2) : renderNext(next));
25
+ return next ? 0 : 1;
26
+ }
27
+ default:
28
+ stdout.error("Usage: speckit sprint plan|next [--json]");
29
+ return 1;
30
+ }
31
+ }
32
+ function renderStatus(stories) {
33
+ const rows = stories.map((story) => ` ${story.id}: ${story.status}`);
34
+ return `version: 1\nsource: .speckit/sync/beads-sync.jsonl\ndevelopment_status:\n${rows.join("\n") || " none: empty"}\n`;
35
+ }
36
+ function renderPlan(stories) {
37
+ const rows = stories.map((story) => `- [ ] ${story.id} (${story.status}) - \`${story.path}\``);
38
+ return `# Spec Sprint Plan
39
+
40
+ ## Goal
41
+ Deliver the highest-priority ready stories while preserving TDD evidence and graph traceability.
42
+
43
+ ## Selected Stories
44
+ ${rows.join("\n") || "- No selectable stories. Run `speckit quick`, `speckit sync`, then retry."}
45
+
46
+ ## Automation
47
+ - Run \`speckit graph triage --json\` before claiming work.
48
+ - Run \`speckit context <story>\` and \`speckit ready <story>\` before implementation.
49
+ - Run \`speckit session checkpoint\` at task boundaries.
50
+ `;
51
+ }
52
+ function renderNext(story) {
53
+ return story ? `Next sprint story: ${story.id} (${story.path})` : "Next sprint story: none";
54
+ }
@@ -1,9 +1,10 @@
1
1
  import { markdown, writeManagedFiles } from "../core/managed-files.js";
2
- import { slugify, timestamp } from "../core/slug.js";
2
+ import { createSession } from "../core/session-manager.js";
3
3
  export async function startCommand(options) {
4
4
  const stdout = options.stdout ?? console;
5
- const sessionId = `${timestamp()}-${slugify(options.intent)}`;
6
- const handoffPath = `.speckit/sessions/${sessionId}/handoff.md`;
5
+ const session = await createSession(options.root, options.intent);
6
+ const sessionId = session.id;
7
+ const handoffPath = `${session.dir}/handoff.md`;
7
8
  const contextPath = ".speckit/context/current.md";
8
9
  await writeManagedFiles(options.root, [
9
10
  {
@@ -1,7 +1,8 @@
1
1
  import { readdir, readFile } from "node:fs/promises";
2
2
  import { join } from "node:path";
3
3
  import { markdown, writeManagedFiles } from "../core/managed-files.js";
4
- import { firstHeading } from "../core/story.js";
4
+ import { firstHeading, frontmatterValue } from "../core/story.js";
5
+ import { writeBeadsMirror } from "../core/beads-mirror.js";
5
6
  export async function syncCommand(options) {
6
7
  const stdout = options.stdout ?? console;
7
8
  const storiesDir = join(options.root, ".speckit", "stories");
@@ -20,7 +21,7 @@ export async function syncCommand(options) {
20
21
  id: entry.replace(/\.md$/, ""),
21
22
  path: `.speckit/stories/${entry}`,
22
23
  title: firstHeading(content) ?? entry.replace(/\.md$/, ""),
23
- status: content.includes("- [ ]") ? "open" : "ready-for-review",
24
+ status: frontmatterValue(content, "status") ?? (content.includes("- [ ]") ? "open" : "ready-for-review"),
24
25
  });
25
26
  }
26
27
  const jsonl = stories.map((story) => JSON.stringify(story)).join("\n");
@@ -43,6 +44,8 @@ bv --robot-next --format json
43
44
  `),
44
45
  },
45
46
  ], true);
47
+ const beadsPath = await writeBeadsMirror(options.root, stories);
46
48
  stdout.log(`Synced ${stories.length} stories to .speckit/sync/beads-sync.jsonl`);
49
+ stdout.log(`Prepared Beads Viewer mirror at ${beadsPath}`);
47
50
  return 0;
48
51
  }
@@ -1,9 +1,8 @@
1
- import { readFile } from "node:fs/promises";
2
- import { join } from "node:path";
1
+ import { readSyncedStories, selectableStories } from "../core/synced-stories.js";
3
2
  export async function triageCommand(options) {
4
3
  const stdout = options.stdout ?? console;
5
4
  const stories = await readSyncedStories(options.root);
6
- const open = stories.filter((story) => story.status === "open");
5
+ const open = selectableStories(stories);
7
6
  const ready = stories.filter((story) => story.status !== "open");
8
7
  const report = {
9
8
  source: ".speckit/sync/beads-sync.jsonl",
@@ -19,15 +18,3 @@ export async function triageCommand(options) {
19
18
  stdout.log(open[0] ? `Next: ${open[0].id} (${open[0].path})` : "Next: none");
20
19
  return 0;
21
20
  }
22
- async function readSyncedStories(root) {
23
- try {
24
- const content = await readFile(join(root, ".speckit", "sync", "beads-sync.jsonl"), "utf8");
25
- return content
26
- .split("\n")
27
- .filter(Boolean)
28
- .map((line) => JSON.parse(line));
29
- }
30
- catch {
31
- return [];
32
- }
33
- }
@@ -0,0 +1,2 @@
1
+ import { ManagedFile } from "./managed-files.js";
2
+ export declare function agentFiles(): ManagedFile[];
@@ -0,0 +1,57 @@
1
+ import { markdown } from "./managed-files.js";
2
+ import { specSkillFiles } from "./skill-catalog.js";
3
+ export function agentFiles() {
4
+ return [
5
+ {
6
+ path: ".speckit/agents/super-agent.md",
7
+ content: markdown(`# Spec Super Agent
8
+
9
+ ## Mission
10
+
11
+ Act as the controller for Speckit enterprise work. Do not be the only worker when context isolation is useful; route work through focused skills and subagent handoffs.
12
+
13
+ ## Load Order
14
+
15
+ 1. \`.speckit/memory/project-context.md\`
16
+ 2. \`.speckit/sessions/active.md\` and the linked session summary
17
+ 3. \`.speckit/skills/catalog.md\`
18
+ 4. \`.speckit/context/current.md\`
19
+ 5. \`.speckit/context/subagent-handoff.md\`
20
+
21
+ ## Routing Rules
22
+
23
+ - Use planning skills before implementation.
24
+ - Select the smallest matching Speckit skill for the current phase.
25
+ - Route by the story state first, then by the requested action.
26
+ - Use TDD execution skills only after \`speckit ready <story>\` passes.
27
+ - Use graph skills before choosing or reordering work.
28
+ - Use session skills at every task boundary.
29
+ - Use review skills before closure.
30
+
31
+ ## Delegation Contract
32
+
33
+ Every handoff must include:
34
+
35
+ - Work context path.
36
+ - Reports path.
37
+ - Plans path.
38
+ - Files to read.
39
+ - Files to modify.
40
+ - Acceptance criteria.
41
+ - Constraints and stop conditions.
42
+
43
+ Subagents must finish with one status: \`DONE\`, \`DONE_WITH_CONCERNS\`, \`BLOCKED\`, or \`NEEDS_CONTEXT\`.
44
+
45
+ ## Long Session Contract
46
+
47
+ - Keep durable facts in files, not in chat.
48
+ - Checkpoint after red, green, refactor, and review.
49
+ - Compact before handoff, after noisy tool output, or before switching stories.
50
+ - Prefer focused subagent handoffs over passing full conversation history.
51
+ - Hydrate runtime tasks from unchecked plan/story checkboxes at session start.
52
+ - Sync completed runtime tasks back to durable plan/story files before close.
53
+ `),
54
+ },
55
+ ...specSkillFiles(),
56
+ ];
57
+ }
@@ -0,0 +1,3 @@
1
+ import { SyncedStory } from "./synced-stories.js";
2
+ export declare function writeBeadsMirror(root: string, stories: SyncedStory[]): Promise<string>;
3
+ export declare function prepareBeadsMirror(root: string): Promise<string>;
@@ -0,0 +1,46 @@
1
+ import { mkdir, writeFile } from "node:fs/promises";
2
+ import { dirname, join } from "node:path";
3
+ import { readSyncedStories } from "./synced-stories.js";
4
+ export async function writeBeadsMirror(root, stories) {
5
+ const path = ".beads/beads.jsonl";
6
+ const now = new Date().toISOString();
7
+ const jsonl = stories
8
+ .map((story) => JSON.stringify(toBeadIssue(story, now)))
9
+ .join("\n");
10
+ const target = join(root, path);
11
+ await mkdir(dirname(target), { recursive: true });
12
+ await writeFile(target, `${jsonl}${jsonl ? "\n" : ""}`, "utf8");
13
+ return path;
14
+ }
15
+ export async function prepareBeadsMirror(root) {
16
+ return writeBeadsMirror(root, await readSyncedStories(root));
17
+ }
18
+ function toBeadIssue(story, timestamp) {
19
+ return {
20
+ id: story.id,
21
+ title: story.title,
22
+ description: `Speckit story: ${story.path}`,
23
+ status: mapStatus(story.status),
24
+ priority: 2,
25
+ issue_type: "task",
26
+ labels: ["speckit", "story"],
27
+ created_at: timestamp,
28
+ updated_at: timestamp,
29
+ };
30
+ }
31
+ function mapStatus(status) {
32
+ switch (status) {
33
+ case "in-progress":
34
+ return "in_progress";
35
+ case "ready-for-review":
36
+ case "review-ready":
37
+ return "review";
38
+ case "closed":
39
+ case "done":
40
+ return "closed";
41
+ case "draft":
42
+ return "draft";
43
+ default:
44
+ return "open";
45
+ }
46
+ }
@@ -0,0 +1 @@
1
+ export declare function refreshMemory(root: string): Promise<string[]>;
@@ -0,0 +1,47 @@
1
+ import { markdown, writeManagedFiles } from "./managed-files.js";
2
+ export async function refreshMemory(root) {
3
+ const files = [
4
+ {
5
+ path: ".speckit/memory/project-context.md",
6
+ content: markdown(`# Spec Project Context
7
+
8
+ ## Technology Stack & Versions
9
+ - Update this section with project-specific runtime, framework, test, and deployment facts.
10
+
11
+ ## Critical Implementation Rules
12
+ - Prefer existing project patterns over generic framework defaults.
13
+ - Keep implementation scoped to the active story and acceptance criteria.
14
+ - Record red-green-refactor evidence for code stories.
15
+ - Use robot-safe graph commands only.
16
+
17
+ ## Context Loading Rules
18
+ - Load this file before implementation, review, sprint planning, and session resume.
19
+ - Treat this file as durable guidance, not as proof that the current environment still matches it.
20
+ `),
21
+ },
22
+ {
23
+ path: ".speckit/memory/decisions.md",
24
+ content: markdown(`# Spec Decisions
25
+
26
+ ## Active Decisions
27
+ - Record durable architecture and workflow decisions here.
28
+
29
+ ## Superseded Decisions
30
+ - Move stale decisions here with the replacement decision and date.
31
+ `),
32
+ },
33
+ {
34
+ path: ".speckit/memory/lessons.md",
35
+ content: markdown(`# Spec Lessons
36
+
37
+ ## Repeated Mistakes To Avoid
38
+ - Add a lesson when an agent repeats a mistake or review catches a missed project rule.
39
+
40
+ ## Useful Verification Commands
41
+ - Add commands that reliably validate this project.
42
+ `),
43
+ },
44
+ ];
45
+ const results = await writeManagedFiles(root, files, false);
46
+ return results.map((result) => result.path);
47
+ }
@@ -0,0 +1,13 @@
1
+ import { StoryResolution } from "./story.js";
2
+ export type ReadinessCheck = {
3
+ name: string;
4
+ ok: boolean;
5
+ detail: string;
6
+ };
7
+ export type ReadinessReport = {
8
+ story?: Pick<StoryResolution, "id" | "path" | "title" | "status" | "evidencePath">;
9
+ checks: ReadinessCheck[];
10
+ status: "ready" | "blocked";
11
+ };
12
+ export declare function evaluateReadiness(root: string, target: string): Promise<ReadinessReport>;
13
+ export declare function evidenceStatus(root: string, evidencePath: string | undefined): Promise<string | undefined>;
@@ -0,0 +1,120 @@
1
+ import { access, readFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { extractSection, frontmatterValue, resolveStory } from "./story.js";
4
+ export async function evaluateReadiness(root, target) {
5
+ const story = await resolveStory(root, target);
6
+ if (!story) {
7
+ return {
8
+ checks: [{ name: "story", ok: false, detail: `Story not found: ${target}` }],
9
+ status: "blocked",
10
+ };
11
+ }
12
+ const evidencePath = story.evidencePath;
13
+ const checks = [
14
+ {
15
+ name: "story-status",
16
+ ok: story.status === "ready-for-dev",
17
+ detail: story.status ? `status=${story.status}` : "status missing",
18
+ },
19
+ {
20
+ name: "acceptance-criteria",
21
+ ok: hasActionableAcceptanceCriteria(story.content),
22
+ detail: "story has testable acceptance criteria",
23
+ },
24
+ {
25
+ name: "evidence-link",
26
+ ok: Boolean(evidencePath),
27
+ detail: evidencePath ?? "missing TDD evidence reference",
28
+ },
29
+ {
30
+ name: "evidence-file",
31
+ ok: evidencePath ? await fileExists(root, evidencePath) : false,
32
+ detail: evidencePath ?? "missing TDD evidence reference",
33
+ },
34
+ {
35
+ name: "context",
36
+ ok: await contextIsFreshForStory(root, story.path),
37
+ detail: ".speckit/context/current.md links this story and is fresh",
38
+ },
39
+ {
40
+ name: "graph-sync",
41
+ ok: await graphContainsStory(root, story.path),
42
+ detail: ".speckit/sync/beads-sync.jsonl contains this story",
43
+ },
44
+ {
45
+ name: "tool-policy",
46
+ ok: await fileExists(root, ".speckit/tool-policy.yaml"),
47
+ detail: ".speckit/tool-policy.yaml",
48
+ },
49
+ {
50
+ name: "safety-policy",
51
+ ok: await fileExists(root, ".speckit/rules/enterprise-safety.md"),
52
+ detail: ".speckit/rules/enterprise-safety.md",
53
+ },
54
+ ];
55
+ return {
56
+ story: {
57
+ id: story.id,
58
+ path: story.path,
59
+ title: story.title,
60
+ status: story.status,
61
+ evidencePath,
62
+ },
63
+ checks,
64
+ status: checks.every((check) => check.ok) ? "ready" : "blocked",
65
+ };
66
+ }
67
+ function hasActionableAcceptanceCriteria(content) {
68
+ const criteria = extractSection(content, "Acceptance Criteria");
69
+ if (!criteria)
70
+ return false;
71
+ return /Given .+|When .+|Then .+|\d+\./i.test(criteria) && !criteria.includes("...");
72
+ }
73
+ async function contextIsFreshForStory(root, storyPath) {
74
+ try {
75
+ const content = await readFile(join(root, ".speckit", "context", "current.md"), "utf8");
76
+ return content.includes("status: fresh") && content.includes(storyPath);
77
+ }
78
+ catch {
79
+ return false;
80
+ }
81
+ }
82
+ async function graphContainsStory(root, storyPath) {
83
+ try {
84
+ const content = await readFile(join(root, ".speckit", "sync", "beads-sync.jsonl"), "utf8");
85
+ return content
86
+ .split("\n")
87
+ .filter(Boolean)
88
+ .some((line) => {
89
+ try {
90
+ return JSON.parse(line).path === storyPath;
91
+ }
92
+ catch {
93
+ return false;
94
+ }
95
+ });
96
+ }
97
+ catch {
98
+ return false;
99
+ }
100
+ }
101
+ async function fileExists(root, path) {
102
+ try {
103
+ await access(join(root, path));
104
+ return true;
105
+ }
106
+ catch {
107
+ return false;
108
+ }
109
+ }
110
+ export async function evidenceStatus(root, evidencePath) {
111
+ if (!evidencePath)
112
+ return undefined;
113
+ try {
114
+ const content = await readFile(join(root, evidencePath), "utf8");
115
+ return frontmatterValue(content, "status");
116
+ }
117
+ catch {
118
+ return undefined;
119
+ }
120
+ }
@@ -1,5 +1,6 @@
1
1
  import { markdown, text } from "./managed-files.js";
2
2
  import { agilePolicy, enterpriseSafetyPolicy, tddPolicy, workflowReview, workflowShape, workflowTddRun, } from "./policy.js";
3
+ import { storyTemplate, tddEvidenceTemplate } from "./templates.js";
3
4
  export function coreFiles() {
4
5
  return [
5
6
  {
@@ -13,6 +14,14 @@ tdd:
13
14
  task_graph:
14
15
  provider: beads
15
16
  bv_robot_only: true
17
+ memory:
18
+ project_context: .speckit/memory/project-context.md
19
+ session_dir: .speckit/sessions
20
+ skills:
21
+ catalog: .speckit/skills/catalog.md
22
+ super_agent: .speckit/agents/super-agent.md
23
+ sprint:
24
+ status: .speckit/sprint/status.yaml
16
25
  adapters:
17
26
  enabled: []`),
18
27
  },
@@ -27,45 +36,11 @@ adapters:
27
36
  { path: ".speckit/workflows/review.md", content: markdown(workflowReview) },
28
37
  {
29
38
  path: ".speckit/templates/story.md",
30
- content: markdown(`# Story: {{title}}
31
-
32
- ## Intent
33
- {{intent}}
34
-
35
- ## Acceptance Criteria
36
- - Given ...
37
- - When ...
38
- - Then ...
39
-
40
- ## TDD Checklist
41
- - [ ] Test targets identified
42
- - [ ] Red evidence recorded
43
- - [ ] Green evidence recorded
44
- - [ ] Refactor validation recorded
45
-
46
- ## Notes
47
- - Risks:
48
- - Dependencies:
49
- `),
39
+ content: markdown(storyTemplate),
50
40
  },
51
41
  {
52
42
  path: ".speckit/templates/tdd-evidence.md",
53
- content: markdown(`# TDD Evidence: {{story}}
54
-
55
- ## Test Intent
56
-
57
- ## Red
58
- - Command:
59
- - Result:
60
-
61
- ## Green
62
- - Command:
63
- - Result:
64
-
65
- ## Refactor
66
- - Command:
67
- - Result:
68
- `),
43
+ content: markdown(tddEvidenceTemplate),
69
44
  },
70
45
  ];
71
46
  }
@@ -76,12 +51,14 @@ export function enterpriseFiles() {
76
51
  content: markdown(`# Spec Flow
77
52
 
78
53
  ## Order
79
- start -> shape -> plan -> context -> sync -> triage -> run -> review -> close
54
+ start -> memory -> sprint -> context -> sync -> triage -> ready -> run -> checkpoint -> review -> close
80
55
 
81
56
  ## Traceability
82
57
  - A session links the original idea to every downstream artifact.
58
+ - Project memory links durable rules to every new session.
83
59
  - A story links acceptance criteria to TDD evidence.
84
60
  - Sync links stories to graph-ready JSONL.
61
+ - Session checkpoints preserve file changes, decisions, and next steps across compaction.
85
62
  - Close links review output back to story and graph sync.
86
63
  `),
87
64
  },
@@ -105,12 +82,64 @@ graph:
105
82
  path: ".speckit/prompts/spec-run.md",
106
83
  content: markdown(`# Spec Run Prompt
107
84
 
108
- 1. Read \`.speckit/context/current.md\`.
109
- 2. Confirm story acceptance criteria.
110
- 3. Write or run the failing test first.
111
- 4. Implement the smallest change.
112
- 5. Record red, green, and refactor evidence.
113
- 6. Run \`speckit review\` before handoff.
85
+ ## Required Inputs
86
+
87
+ - Current context: \`.speckit/context/current.md\`
88
+ - Subagent handoff: \`.speckit/context/subagent-handoff.md\`
89
+ - Project memory: \`.speckit/memory/project-context.md\`
90
+ - Active session summary: \`.speckit/sessions/active.md\` and the linked \`summary.md\`
91
+ - Active artifact log: linked \`artifact-log.md\`
92
+ - Super agent router: \`.speckit/agents/super-agent.md\`
93
+ - Skill catalog: \`.speckit/skills/catalog.md\`
94
+ - Story with acceptance criteria
95
+ - Matching TDD evidence file
96
+ - Tool policy: \`.speckit/tool-policy.yaml\`
97
+
98
+ ## Status Preconditions
99
+
100
+ - Story status is \`ready-for-dev\`.
101
+ - Context status is \`fresh\`.
102
+ - \`speckit ready <story>\` returns ready.
103
+ - \`speckit session status\` identifies the active session.
104
+
105
+ ## Allowed Edits
106
+
107
+ - Implementation files needed for the story.
108
+ - Matching tests.
109
+ - Linked TDD evidence file.
110
+ - Story completion checkboxes and implementation notes.
111
+
112
+ ## Execution Contract
113
+
114
+ Use the red-green-refactor loop.
115
+
116
+ 1. Read the current context before touching code.
117
+ 2. Read the super agent router and select the smallest matching Speckit skill.
118
+ 3. Confirm the story path, acceptance criteria, and evidence path.
119
+ 4. Write or run the smallest failing test first.
120
+ 5. Record red evidence before implementation.
121
+ 6. Implement the smallest change that satisfies the failing test.
122
+ 7. Record green evidence after tests pass.
123
+ 8. Refactor only while tests stay green, then record validation.
124
+ 9. Use graph commands only through robot-safe flags such as \`bv --robot-next --format json\`.
125
+ 10. Run \`speckit session checkpoint --note "<phase complete>"\` after red, green, refactor, and review boundaries.
126
+ 11. Run \`speckit session compact\` before context gets noisy or before handing off to another agent.
127
+ 12. Run \`speckit review\` before handoff.
128
+
129
+ ## Stop Conditions
130
+
131
+ - Stop if acceptance criteria are missing.
132
+ - Stop if the evidence file cannot be identified.
133
+ - Stop if \`speckit ready <story>\` reports blocked.
134
+ - Stop if active session state cannot be written.
135
+ - Stop before destructive commands, production changes, or secret access.
136
+
137
+ ## Completion Signal
138
+
139
+ - All acceptance criteria satisfied.
140
+ - TDD evidence status can be advanced through red, green, and refactor.
141
+ - Session checkpoint and compact summary are current.
142
+ - Review handoff is ready.
114
143
  `),
115
144
  },
116
145
  ];
@@ -0,0 +1,15 @@
1
+ export type SessionCheckpointOptions = {
2
+ root: string;
3
+ note?: string;
4
+ story?: string;
5
+ };
6
+ export type SessionRef = {
7
+ id: string;
8
+ dir: string;
9
+ };
10
+ export declare function ensureSession(root: string, intent?: string): Promise<SessionRef>;
11
+ export declare function createSession(root: string, intent?: string): Promise<SessionRef>;
12
+ export declare function checkpointSession(options: SessionCheckpointOptions): Promise<SessionRef>;
13
+ export declare function compactSession(root: string): Promise<SessionRef>;
14
+ export declare function resumeSession(root: string, id?: string): Promise<SessionRef | undefined>;
15
+ export declare function sessionStatus(root: string): Promise<Record<string, string>>;