@quinteroac/agents-coding-toolkit 0.1.0-preview

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 (85) hide show
  1. package/AGENTS.md +7 -0
  2. package/README.md +127 -0
  3. package/package.json +34 -0
  4. package/scaffold/.agents/flow/archived/tmpl_.gitkeep +0 -0
  5. package/scaffold/.agents/flow/tmpl_README.md +7 -0
  6. package/scaffold/.agents/flow/tmpl_iteration_close_checklist.example.md +11 -0
  7. package/scaffold/.agents/skills/automated-fix/tmpl_SKILL.md +67 -0
  8. package/scaffold/.agents/skills/create-issue/tmpl_SKILL.md +68 -0
  9. package/scaffold/.agents/skills/create-pr-document/tmpl_SKILL.md +125 -0
  10. package/scaffold/.agents/skills/create-project-context/tmpl_SKILL.md +168 -0
  11. package/scaffold/.agents/skills/create-test-plan/tmpl_SKILL.md +86 -0
  12. package/scaffold/.agents/skills/debug/tmpl_SKILL.md +19 -0
  13. package/scaffold/.agents/skills/evaluate/tmpl_SKILL.md +19 -0
  14. package/scaffold/.agents/skills/execute-test-batch/tmpl_SKILL.md +49 -0
  15. package/scaffold/.agents/skills/execute-test-case/tmpl_SKILL.md +47 -0
  16. package/scaffold/.agents/skills/implement-user-story/tmpl_SKILL.md +68 -0
  17. package/scaffold/.agents/skills/plan-refactor/tmpl_SKILL.md +19 -0
  18. package/scaffold/.agents/skills/refactor-prd/tmpl_SKILL.md +19 -0
  19. package/scaffold/.agents/skills/refine-pr-document/tmpl_SKILL.md +108 -0
  20. package/scaffold/.agents/skills/refine-project-context/tmpl_SKILL.md +157 -0
  21. package/scaffold/.agents/skills/refine-test-plan/tmpl_SKILL.md +76 -0
  22. package/scaffold/.agents/tmpl_PROJECT_CONTEXT.md +3 -0
  23. package/scaffold/.agents/tmpl_state.example.json +26 -0
  24. package/scaffold/.agents/tmpl_state_rules.md +29 -0
  25. package/scaffold/docs/nvst-flow/templates/tmpl_CHANGELOG.md +18 -0
  26. package/scaffold/docs/nvst-flow/templates/tmpl_TECHNICAL_DEBT.md +11 -0
  27. package/scaffold/docs/nvst-flow/templates/tmpl_it_000001_evaluation-report.md +19 -0
  28. package/scaffold/docs/nvst-flow/templates/tmpl_it_000001_product-requirement-document.md +19 -0
  29. package/scaffold/docs/nvst-flow/templates/tmpl_it_000001_refactor_plan.md +19 -0
  30. package/scaffold/docs/nvst-flow/templates/tmpl_it_000001_test-plan.md +19 -0
  31. package/scaffold/docs/nvst-flow/tmpl_COMMANDS.md +0 -0
  32. package/scaffold/docs/nvst-flow/tmpl_QUICK_USE.md +0 -0
  33. package/scaffold/docs/tmpl_PLACEHOLDER.md +0 -0
  34. package/scaffold/schemas/node-shims.d.ts +15 -0
  35. package/scaffold/schemas/tmpl_issues.ts +19 -0
  36. package/scaffold/schemas/tmpl_prd.ts +26 -0
  37. package/scaffold/schemas/tmpl_progress.ts +39 -0
  38. package/scaffold/schemas/tmpl_state.ts +81 -0
  39. package/scaffold/schemas/tmpl_test-plan.ts +20 -0
  40. package/scaffold/schemas/tmpl_validate-progress.ts +13 -0
  41. package/scaffold/schemas/tmpl_validate-state.ts +13 -0
  42. package/scaffold/tmpl_AGENTS.md +7 -0
  43. package/schemas/prd.ts +26 -0
  44. package/schemas/progress.ts +39 -0
  45. package/schemas/state.ts +81 -0
  46. package/schemas/test-plan.test.ts +53 -0
  47. package/schemas/test-plan.ts +20 -0
  48. package/schemas/validate-progress.ts +13 -0
  49. package/schemas/validate-state.ts +13 -0
  50. package/src/agent.test.ts +37 -0
  51. package/src/agent.ts +225 -0
  52. package/src/cli-path.ts +4 -0
  53. package/src/cli.ts +578 -0
  54. package/src/commands/approve-project-context.ts +37 -0
  55. package/src/commands/approve-requirement.ts +217 -0
  56. package/src/commands/approve-test-plan.test.ts +193 -0
  57. package/src/commands/approve-test-plan.ts +202 -0
  58. package/src/commands/create-issue.test.ts +484 -0
  59. package/src/commands/create-issue.ts +371 -0
  60. package/src/commands/create-project-context.ts +96 -0
  61. package/src/commands/create-prototype.test.ts +153 -0
  62. package/src/commands/create-prototype.ts +425 -0
  63. package/src/commands/create-test-plan.test.ts +381 -0
  64. package/src/commands/create-test-plan.ts +248 -0
  65. package/src/commands/define-requirement.ts +47 -0
  66. package/src/commands/destroy.ts +113 -0
  67. package/src/commands/execute-automated-fix.test.ts +580 -0
  68. package/src/commands/execute-automated-fix.ts +363 -0
  69. package/src/commands/execute-manual-fix.test.ts +343 -0
  70. package/src/commands/execute-manual-fix.ts +203 -0
  71. package/src/commands/execute-test-plan.test.ts +1891 -0
  72. package/src/commands/execute-test-plan.ts +722 -0
  73. package/src/commands/init.ts +85 -0
  74. package/src/commands/refine-project-context.ts +74 -0
  75. package/src/commands/refine-requirement.ts +60 -0
  76. package/src/commands/refine-test-plan.test.ts +200 -0
  77. package/src/commands/refine-test-plan.ts +93 -0
  78. package/src/commands/start-iteration.test.ts +144 -0
  79. package/src/commands/start-iteration.ts +101 -0
  80. package/src/commands/write-json.ts +136 -0
  81. package/src/install.test.ts +124 -0
  82. package/src/pack.test.ts +103 -0
  83. package/src/state.test.ts +66 -0
  84. package/src/state.ts +52 -0
  85. package/tsconfig.json +15 -0
@@ -0,0 +1,26 @@
1
+ {
2
+ "current_iteration": "000001",
3
+ "current_phase": "define",
4
+ "phases": {
5
+ "define": {
6
+ "requirement_definition": { "status": "pending", "file": null },
7
+ "prd_generation": { "status": "pending", "file": null }
8
+ },
9
+ "prototype": {
10
+ "project_context": { "status": "pending", "file": null },
11
+ "test_plan": { "status": "pending", "file": null },
12
+ "tp_generation": { "status": "pending", "file": null },
13
+ "prototype_build": { "status": "pending", "file": null },
14
+ "test_execution": { "status": "pending", "file": null },
15
+ "prototype_approved": false
16
+ },
17
+ "refactor": {
18
+ "evaluation_report": { "status": "pending", "file": null },
19
+ "refactor_plan": { "status": "pending", "file": null },
20
+ "refactor_execution": { "status": "pending", "file": null },
21
+ "changelog": { "status": "pending", "file": null }
22
+ }
23
+ },
24
+ "last_updated": "2026-02-18T12:00:00Z",
25
+ "history": []
26
+ }
@@ -0,0 +1,29 @@
1
+ # State validation rules (scaffold)
2
+
3
+ <!-- TODO: Fill in preconditions and postconditions per command. All content in English. -->
4
+
5
+ Each command must validate the relevant fields of `state.json` before running. If the current state does not allow the command, the command fails with a clear message.
6
+
7
+ | Command | Pre | Post |
8
+ |--------|-----|-----|
9
+ | `bun start iteration` | TBD | TBD |
10
+ | `bun define requirement` | TBD | TBD |
11
+ | `bun refine requirement` | TBD | TBD |
12
+ | `bun approve requirement` | TBD | TBD |
13
+ | `bun create prd` | TBD | TBD |
14
+ | `bun create project-context` | TBD | TBD |
15
+ | `bun approve project-context` | TBD | TBD |
16
+ | `bun create prototype` | TBD | TBD |
17
+ | `bun define test-plan` | TBD | TBD |
18
+ | `bun refine test-plan` | TBD | TBD |
19
+ | `bun approve test-plan` | TBD | TBD |
20
+ | `bun execute test-plan` | TBD | TBD |
21
+ | `bun execute automated-fix` | TBD | TBD |
22
+ | `bun execute manual-fix` | TBD | TBD |
23
+ | `bun approve prototype` | TBD | TBD |
24
+ | `bun define refactor-plan` | TBD | TBD |
25
+ | `bun refine refactor-plan` | TBD | TBD |
26
+ | `bun approve refactor-plan` | TBD | TBD |
27
+ | `bun create prd --refactor` | TBD | TBD |
28
+ | `bun execute refactor` | TBD | TBD |
29
+ | `bun register changelog` (or equivalent) | TBD | TBD |
@@ -0,0 +1,18 @@
1
+ # Changelog
2
+
3
+ <!-- TODO: All content in English. One block per iteration. -->
4
+
5
+ ## [Unreleased]
6
+
7
+ <!-- TODO -->
8
+
9
+ ## Iteration 000001 — YYYY-MM-DD
10
+
11
+ <!-- TODO: Summary of requirements, refactorings, fixes. -->
12
+
13
+ ---
14
+
15
+ <!-- Template for next iteration:
16
+ ## Iteration 000002 — YYYY-MM-DD
17
+ ...
18
+ -->
@@ -0,0 +1,11 @@
1
+ # Technical debt (discarded or deferred)
2
+
3
+ <!-- TODO: All content in English. Updated when approving refactor plan (bun approve refactor-plan). Used as input in future iteration evaluations. -->
4
+
5
+ ## From iteration 000001
6
+
7
+ <!-- TODO: Items not included in the refactor plan; rationale optional. -->
8
+
9
+ ---
10
+
11
+ <!-- Add new section per iteration when refactor plan is approved. -->
@@ -0,0 +1,19 @@
1
+ # Evaluation report — Iteration 000001
2
+
3
+ <!-- TODO: Replace 000001 with current iteration. Complete sections. All content in English. -->
4
+
5
+ ## Strengths
6
+
7
+ <!-- TODO -->
8
+
9
+ ## Technical debt
10
+
11
+ <!-- TODO: Items to consider for refactor. -->
12
+
13
+ ## Violations of PROJECT_CONTEXT.md
14
+
15
+ <!-- TODO -->
16
+
17
+ ## Recommendations
18
+
19
+ <!-- TODO: By impact, urgency, effort, scope; optional numeric score for ordering. -->
@@ -0,0 +1,19 @@
1
+ # Product requirement document — Iteration 000001
2
+
3
+ <!-- TODO: Replace 000001 with current iteration. Complete sections. All content in English. -->
4
+
5
+ ## Summary
6
+
7
+ <!-- TODO -->
8
+
9
+ ## Requirements
10
+
11
+ <!-- TODO: List requirements / user stories. -->
12
+
13
+ ## Acceptance criteria
14
+
15
+ <!-- TODO -->
16
+
17
+ ## Out of scope (this iteration)
18
+
19
+ <!-- TODO -->
@@ -0,0 +1,19 @@
1
+ # Refactor plan — Iteration 000001
2
+
3
+ <!-- TODO: Replace 000001 with current iteration. Complete sections. All content in English. -->
4
+
5
+ ## Quick wins
6
+
7
+ <!-- TODO -->
8
+
9
+ ## Critical refactorings
10
+
11
+ <!-- TODO -->
12
+
13
+ ## Deferred / discarded (→ TECHNICAL_DEBT.md)
14
+
15
+ <!-- TODO -->
16
+
17
+ ## Order of execution
18
+
19
+ <!-- TODO: Ordered list of refactor steps. -->
@@ -0,0 +1,19 @@
1
+ # Test plan — Iteration 000001
2
+
3
+ <!-- TODO: Replace 000001 with current iteration. Complete sections. All content in English. -->
4
+
5
+ ## Scope
6
+
7
+ <!-- TODO: What is in scope for testing this iteration. -->
8
+
9
+ ## Automated tests
10
+
11
+ <!-- TODO: List test cases; link to use cases / progress.json entries. -->
12
+
13
+ ## Exploratory / manual tests
14
+
15
+ <!-- TODO: UX, exploratory; owned by user. -->
16
+
17
+ ## Environment and data
18
+
19
+ <!-- TODO if needed -->
File without changes
File without changes
File without changes
@@ -0,0 +1,15 @@
1
+ declare module "fs" {
2
+ export function readFileSync(path: string, encoding: string): string;
3
+ }
4
+
5
+ declare module "path" {
6
+ export function join(...paths: string[]): string;
7
+ }
8
+
9
+ declare const process: {
10
+ exitCode?: number;
11
+ };
12
+
13
+ interface ImportMeta {
14
+ readonly dir: string;
15
+ }
@@ -0,0 +1,19 @@
1
+ import { z } from "zod";
2
+
3
+ const IssueSchema = z.object({
4
+ id: z.string(),
5
+ title: z.string(),
6
+ description: z.string(),
7
+ status: z.enum(["open", "fixed", "retry", "manual-fix"]),
8
+ });
9
+
10
+ export const IssuesSchema = z.array(IssueSchema).refine(
11
+ (issues) => {
12
+ const ids = issues.map((i) => i.id);
13
+ return new Set(ids).size === ids.length;
14
+ },
15
+ { message: "Issue IDs must be unique" },
16
+ );
17
+
18
+ export type Issue = z.infer<typeof IssueSchema>;
19
+ export type Issues = z.infer<typeof IssuesSchema>;
@@ -0,0 +1,26 @@
1
+ import { z } from "zod";
2
+
3
+ const acceptanceCriterion = z.object({
4
+ id: z.string(),
5
+ text: z.string(),
6
+ });
7
+
8
+ const userStory = z.object({
9
+ id: z.string(),
10
+ title: z.string(),
11
+ description: z.string(),
12
+ acceptanceCriteria: z.array(acceptanceCriterion),
13
+ });
14
+
15
+ const functionalRequirement = z.object({
16
+ id: z.string(),
17
+ description: z.string(),
18
+ });
19
+
20
+ export const PrdSchema = z.object({
21
+ goals: z.array(z.string()),
22
+ userStories: z.array(userStory),
23
+ functionalRequirements: z.array(functionalRequirement),
24
+ });
25
+
26
+ export type Prd = z.infer<typeof PrdSchema>;
@@ -0,0 +1,39 @@
1
+ import { z } from "zod";
2
+
3
+ const implementationStatus = z.enum(["pending", "in_progress", "completed"]);
4
+ const testStatus = z.enum([
5
+ "pending",
6
+ "written",
7
+ "passed",
8
+ "failed",
9
+ "fixed",
10
+ "unfixed",
11
+ ]);
12
+
13
+ const implementation = z.object({
14
+ status: implementationStatus,
15
+ summary_of_actions: z.string(),
16
+ learnings: z.string(),
17
+ });
18
+
19
+ const testEntry = z.object({
20
+ id: z.string(),
21
+ description: z.string(),
22
+ status: testStatus,
23
+ file: z.string().optional(),
24
+ last_run: z.string().optional(),
25
+ error: z.string().optional(),
26
+ });
27
+
28
+ const progressEntry = z.object({
29
+ use_case_id: z.string(),
30
+ timestamp: z.string(),
31
+ implementation,
32
+ tests: z.array(testEntry),
33
+ });
34
+
35
+ export const ProgressSchema = z.object({
36
+ entries: z.array(progressEntry),
37
+ });
38
+
39
+ export type Progress = z.infer<typeof ProgressSchema>;
@@ -0,0 +1,81 @@
1
+ import { z } from "zod";
2
+
3
+ const iterationId = z.string().regex(/^\d{6}$/);
4
+ const phase = z.enum(["define", "prototype", "refactor"]);
5
+ const iso8601 = z.string(); // TODO: tighten to ISO 8601 regex if desired
6
+
7
+ const statusFile = z.object({
8
+ status: z.string(),
9
+ file: z.string().nullable(),
10
+ });
11
+
12
+ const definePhase = z.object({
13
+ requirement_definition: z.object({
14
+ status: z.enum(["pending", "in_progress", "approved"]),
15
+ file: z.string().nullable(),
16
+ }),
17
+ prd_generation: z.object({
18
+ status: z.enum(["pending", "completed"]),
19
+ file: z.string().nullable(),
20
+ }),
21
+ });
22
+
23
+ const prototypePhase = z.object({
24
+ project_context: statusFile.extend({
25
+ status: z.enum(["pending", "pending_approval", "created"]),
26
+ }),
27
+ test_plan: statusFile.extend({
28
+ status: z.enum(["pending", "pending_approval", "created"]),
29
+ }),
30
+ tp_generation: z.object({
31
+ status: z.enum(["pending", "created"]),
32
+ file: z.string().nullable(),
33
+ }),
34
+ prototype_build: statusFile.extend({
35
+ status: z.enum(["pending", "in_progress", "created"]),
36
+ }),
37
+ test_execution: statusFile.extend({
38
+ status: z.enum(["pending", "in_progress", "completed", "failed"]),
39
+ }),
40
+ prototype_approved: z.boolean(),
41
+ });
42
+
43
+ const refactorPhase = z.object({
44
+ evaluation_report: z.object({
45
+ status: z.enum(["pending", "created"]),
46
+ file: z.string().nullable(),
47
+ }),
48
+ refactor_plan: z.object({
49
+ status: z.enum(["pending", "pending_approval", "approved"]),
50
+ file: z.string().nullable(),
51
+ }),
52
+ refactor_execution: z.object({
53
+ status: z.enum(["pending", "in_progress", "completed"]),
54
+ file: z.string().nullable(),
55
+ }),
56
+ changelog: z.object({
57
+ status: z.enum(["pending", "created"]),
58
+ file: z.string().nullable(),
59
+ }),
60
+ });
61
+
62
+ const historyEntry = z.object({
63
+ iteration: iterationId,
64
+ archived_at: iso8601,
65
+ archived_path: z.string(),
66
+ });
67
+
68
+ export const StateSchema = z.object({
69
+ current_iteration: iterationId,
70
+ current_phase: phase,
71
+ phases: z.object({
72
+ define: definePhase,
73
+ prototype: prototypePhase,
74
+ refactor: refactorPhase,
75
+ }),
76
+ last_updated: iso8601,
77
+ updated_by: z.string().optional(),
78
+ history: z.array(historyEntry).optional(),
79
+ });
80
+
81
+ export type State = z.infer<typeof StateSchema>;
@@ -0,0 +1,20 @@
1
+ import { z } from "zod";
2
+
3
+ const TestStatusSchema = z.enum(["pending", "passed", "failed", "skipped"]);
4
+
5
+ const TestItemSchema = z.object({
6
+ id: z.string(),
7
+ description: z.string(),
8
+ status: TestStatusSchema,
9
+ correlatedRequirements: z.array(z.string()),
10
+ });
11
+
12
+ export const TestPlanSchema = z.object({
13
+ overallStatus: TestStatusSchema,
14
+ scope: z.array(z.string()),
15
+ environmentData: z.array(z.string()),
16
+ automatedTests: z.array(TestItemSchema),
17
+ exploratoryManualTests: z.array(TestItemSchema),
18
+ });
19
+
20
+ export type TestPlan = z.infer<typeof TestPlanSchema>;
@@ -0,0 +1,13 @@
1
+ import { ProgressSchema } from "./tmpl_progress";
2
+ import { readFile } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+
5
+ const path = join(import.meta.dir, "..", ".agents", "flow", "tmpl_it_000001_progress.example.json");
6
+ const raw = JSON.parse(await readFile(path, "utf-8"));
7
+ const result = ProgressSchema.safeParse(raw);
8
+ if (result.success) {
9
+ console.log("tmpl_it_000001_progress.example.json is valid");
10
+ } else {
11
+ console.error("Validation failed:", result.error.flatten());
12
+ process.exitCode = 1;
13
+ }
@@ -0,0 +1,13 @@
1
+ import { StateSchema } from "./tmpl_state";
2
+ import { readFile } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+
5
+ const path = join(import.meta.dir, "..", ".agents", "tmpl_state.example.json");
6
+ const raw = JSON.parse(await readFile(path, "utf-8"));
7
+ const result = StateSchema.safeParse(raw);
8
+ if (result.success) {
9
+ console.log("tmpl_state.example.json is valid");
10
+ } else {
11
+ console.error("tmpl_state.example.json validation failed:", result.error.flatten());
12
+ process.exitCode = 1;
13
+ }
@@ -0,0 +1,7 @@
1
+ # Agents entry point
2
+
3
+ - **What this project is:** (Describe the product or project. This file is the single entry point for the agent.)
4
+ - **How to work here:** Use this file as the single entry point. Follow the process phases in order; read and update `.agents/state.json` for the current iteration and phase. Invoke the skills under `.agents/skills/` as indicated by each command. All iteration artifacts live in `.agents/flow/` with the naming `it_` + 6-digit iteration (e.g. `it_000001_product-requirement-document.md`). From the second iteration onward, adhere to `.agents/PROJECT_CONTEXT.md`.
5
+ - **Process:** Define → Prototype → Refactor (see package or usage documentation).
6
+ - **Project context:** `.agents/PROJECT_CONTEXT.md` (conventions and architecture; agent adheres from second iteration onward).
7
+ - **Rule:** All generated resources in this repo must be in English.
package/schemas/prd.ts ADDED
@@ -0,0 +1,26 @@
1
+ import { z } from "zod";
2
+
3
+ const acceptanceCriterion = z.object({
4
+ id: z.string(),
5
+ text: z.string(),
6
+ });
7
+
8
+ const userStory = z.object({
9
+ id: z.string(),
10
+ title: z.string(),
11
+ description: z.string(),
12
+ acceptanceCriteria: z.array(acceptanceCriterion),
13
+ });
14
+
15
+ const functionalRequirement = z.object({
16
+ id: z.string(),
17
+ description: z.string(),
18
+ });
19
+
20
+ export const PrdSchema = z.object({
21
+ goals: z.array(z.string()),
22
+ userStories: z.array(userStory),
23
+ functionalRequirements: z.array(functionalRequirement),
24
+ });
25
+
26
+ export type Prd = z.infer<typeof PrdSchema>;
@@ -0,0 +1,39 @@
1
+ import { z } from "zod";
2
+
3
+ const implementationStatus = z.enum(["pending", "in_progress", "completed"]);
4
+ const testStatus = z.enum([
5
+ "pending",
6
+ "written",
7
+ "passed",
8
+ "failed",
9
+ "fixed",
10
+ "unfixed",
11
+ ]);
12
+
13
+ const implementation = z.object({
14
+ status: implementationStatus,
15
+ summary_of_actions: z.string(),
16
+ learnings: z.string(),
17
+ });
18
+
19
+ const testEntry = z.object({
20
+ id: z.string(),
21
+ description: z.string(),
22
+ status: testStatus,
23
+ file: z.string().optional(),
24
+ last_run: z.string().optional(),
25
+ error: z.string().optional(),
26
+ });
27
+
28
+ const progressEntry = z.object({
29
+ use_case_id: z.string(),
30
+ timestamp: z.string(),
31
+ implementation,
32
+ tests: z.array(testEntry),
33
+ });
34
+
35
+ export const ProgressSchema = z.object({
36
+ entries: z.array(progressEntry),
37
+ });
38
+
39
+ export type Progress = z.infer<typeof ProgressSchema>;
@@ -0,0 +1,81 @@
1
+ import { z } from "zod";
2
+
3
+ const iterationId = z.string().regex(/^\d{6}$/);
4
+ const phase = z.enum(["define", "prototype", "refactor"]);
5
+ const iso8601 = z.string(); // TODO: tighten to ISO 8601 regex if desired
6
+
7
+ const statusFile = z.object({
8
+ status: z.string(),
9
+ file: z.string().nullable(),
10
+ });
11
+
12
+ const definePhase = z.object({
13
+ requirement_definition: z.object({
14
+ status: z.enum(["pending", "in_progress", "approved"]),
15
+ file: z.string().nullable(),
16
+ }),
17
+ prd_generation: z.object({
18
+ status: z.enum(["pending", "completed"]),
19
+ file: z.string().nullable(),
20
+ }),
21
+ });
22
+
23
+ const prototypePhase = z.object({
24
+ project_context: statusFile.extend({
25
+ status: z.enum(["pending", "pending_approval", "created"]),
26
+ }),
27
+ test_plan: statusFile.extend({
28
+ status: z.enum(["pending", "pending_approval", "created"]),
29
+ }),
30
+ tp_generation: z.object({
31
+ status: z.enum(["pending", "created"]),
32
+ file: z.string().nullable(),
33
+ }),
34
+ prototype_build: statusFile.extend({
35
+ status: z.enum(["pending", "in_progress", "created"]),
36
+ }),
37
+ test_execution: statusFile.extend({
38
+ status: z.enum(["pending", "in_progress", "completed", "failed"]),
39
+ }),
40
+ prototype_approved: z.boolean(),
41
+ });
42
+
43
+ const refactorPhase = z.object({
44
+ evaluation_report: z.object({
45
+ status: z.enum(["pending", "created"]),
46
+ file: z.string().nullable(),
47
+ }),
48
+ refactor_plan: z.object({
49
+ status: z.enum(["pending", "pending_approval", "approved"]),
50
+ file: z.string().nullable(),
51
+ }),
52
+ refactor_execution: z.object({
53
+ status: z.enum(["pending", "in_progress", "completed"]),
54
+ file: z.string().nullable(),
55
+ }),
56
+ changelog: z.object({
57
+ status: z.enum(["pending", "created"]),
58
+ file: z.string().nullable(),
59
+ }),
60
+ });
61
+
62
+ const historyEntry = z.object({
63
+ iteration: iterationId,
64
+ archived_at: iso8601,
65
+ archived_path: z.string(),
66
+ });
67
+
68
+ export const StateSchema = z.object({
69
+ current_iteration: iterationId,
70
+ current_phase: phase,
71
+ phases: z.object({
72
+ define: definePhase,
73
+ prototype: prototypePhase,
74
+ refactor: refactorPhase,
75
+ }),
76
+ last_updated: iso8601,
77
+ updated_by: z.string().optional(),
78
+ history: z.array(historyEntry).optional(),
79
+ });
80
+
81
+ export type State = z.infer<typeof StateSchema>;
@@ -0,0 +1,53 @@
1
+ import { describe, expect, test } from "bun:test";
2
+
3
+ import { TestPlanSchema } from "./test-plan";
4
+
5
+ describe("TestPlanSchema", () => {
6
+ test("accepts enhanced test plan metadata structure", () => {
7
+ const validation = TestPlanSchema.safeParse({
8
+ overallStatus: "pending",
9
+ scope: ["Validate login flow and session persistence"],
10
+ environmentData: ["Node 22", "Chromium latest", "seeded test users"],
11
+ automatedTests: [
12
+ {
13
+ id: "TC-001",
14
+ description: "POST /login returns 200 for valid credentials",
15
+ status: "passed",
16
+ correlatedRequirements: ["US-001", "FR-1"],
17
+ },
18
+ ],
19
+ exploratoryManualTests: [
20
+ {
21
+ id: "TC-002",
22
+ description: "Visual check of error message clarity for invalid login",
23
+ status: "skipped",
24
+ correlatedRequirements: ["US-001"],
25
+ },
26
+ ],
27
+ });
28
+
29
+ expect(validation.success).toBe(true);
30
+ if (!validation.success) {
31
+ throw new Error("Expected enhanced test plan payload to be valid");
32
+ }
33
+
34
+ expect(validation.data.overallStatus).toBe("pending");
35
+ expect(validation.data.environmentData).toEqual([
36
+ "Node 22",
37
+ "Chromium latest",
38
+ "seeded test users",
39
+ ]);
40
+ expect(validation.data.automatedTests[0]?.correlatedRequirements).toEqual(["US-001", "FR-1"]);
41
+ });
42
+
43
+ test("rejects legacy flat-list schema shape", () => {
44
+ const validation = TestPlanSchema.safeParse({
45
+ scope: ["Legacy scope"],
46
+ automatedTests: ["legacy test line item"],
47
+ exploratoryManualTests: ["legacy manual line item"],
48
+ environmentAndData: ["legacy env entry"],
49
+ });
50
+
51
+ expect(validation.success).toBe(false);
52
+ });
53
+ });
@@ -0,0 +1,20 @@
1
+ import { z } from "zod";
2
+
3
+ const TestStatusSchema = z.enum(["pending", "passed", "failed", "skipped"]);
4
+
5
+ const TestItemSchema = z.object({
6
+ id: z.string(),
7
+ description: z.string(),
8
+ status: TestStatusSchema,
9
+ correlatedRequirements: z.array(z.string()),
10
+ });
11
+
12
+ export const TestPlanSchema = z.object({
13
+ overallStatus: TestStatusSchema,
14
+ scope: z.array(z.string()),
15
+ environmentData: z.array(z.string()),
16
+ automatedTests: z.array(TestItemSchema),
17
+ exploratoryManualTests: z.array(TestItemSchema),
18
+ });
19
+
20
+ export type TestPlan = z.infer<typeof TestPlanSchema>;
@@ -0,0 +1,13 @@
1
+ import { ProgressSchema } from "./tmpl_progress.ts";
2
+ import { readFile } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+
5
+ const path = join(import.meta.dir, "..", ".agents", "flow", "tmpl_it_000001_progress.example.json");
6
+ const raw = JSON.parse(await readFile(path, "utf-8"));
7
+ const result = ProgressSchema.safeParse(raw);
8
+ if (result.success) {
9
+ console.log("tmpl_it_000001_progress.example.json is valid");
10
+ } else {
11
+ console.error("Validation failed:", result.error.flatten());
12
+ process.exitCode = 1;
13
+ }
@@ -0,0 +1,13 @@
1
+ import { StateSchema } from "./tmpl_state.ts";
2
+ import { readFile } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+
5
+ const path = join(import.meta.dir, "..", ".agents", "tmpl_state.example.json");
6
+ const raw = JSON.parse(await readFile(path, "utf-8"));
7
+ const result = StateSchema.safeParse(raw);
8
+ if (result.success) {
9
+ console.log("tmpl_state.example.json is valid");
10
+ } else {
11
+ console.error("tmpl_state.example.json validation failed:", result.error.flatten());
12
+ process.exitCode = 1;
13
+ }