@vimhead.dev/norn-cli 0.1.0-tip.35359392805.1 → 0.1.0-tip.35436871363.1

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 (146) hide show
  1. package/assets/README.md +22 -27
  2. package/assets/docs/README.md +5 -5
  3. package/assets/docs/agents.md +48 -9
  4. package/assets/docs/cli.md +7 -7
  5. package/assets/docs/composition.md +25 -25
  6. package/assets/docs/persistence.md +34 -23
  7. package/assets/docs/projects.md +30 -18
  8. package/assets/docs/providers.md +3 -3
  9. package/assets/docs/recovery.md +13 -9
  10. package/assets/docs/schemas.md +1 -1
  11. package/assets/docs/workflows.md +105 -12
  12. package/assets/examples/agent-then-analysis/README.md +10 -10
  13. package/assets/examples/agent-then-analysis/input.json +1 -1
  14. package/assets/examples/agent-then-analysis/norn.project.json +1 -1
  15. package/assets/examples/agent-then-analysis/plugin.ts +57 -68
  16. package/assets/examples/caller-selected-continuation/README.md +15 -14
  17. package/assets/examples/caller-selected-continuation/caller.ts +37 -38
  18. package/assets/examples/caller-selected-continuation/input.json +2 -2
  19. package/assets/examples/caller-selected-continuation/norn.project.json +1 -1
  20. package/assets/examples/caller-selected-continuation/producer.ts +19 -24
  21. package/assets/examples/coordinating-multiple-agents/README.md +27 -17
  22. package/assets/examples/coordinating-multiple-agents/input.json +1 -1
  23. package/assets/examples/coordinating-multiple-agents/norn.project.json +1 -1
  24. package/assets/examples/coordinating-multiple-agents/plugin.ts +79 -60
  25. package/assets/examples/coordinating-multiple-agents/queue-tools.ts +43 -0
  26. package/assets/examples/coordinating-multiple-agents/work-queue.ts +60 -65
  27. package/assets/examples/getting-started/README.md +2 -2
  28. package/assets/examples/getting-started/norn.project.json +1 -1
  29. package/assets/examples/getting-started/plugin.ts +20 -26
  30. package/assets/examples/minimal-workflow/README.md +13 -12
  31. package/assets/examples/minimal-workflow/norn.project.json +1 -1
  32. package/assets/examples/minimal-workflow/plugin.ts +14 -25
  33. package/assets/examples/shared-state/README.md +12 -4
  34. package/assets/examples/shared-state/input.json +1 -1
  35. package/assets/examples/shared-state/norn.project.json +1 -1
  36. package/assets/examples/shared-state/plugin.ts +49 -41
  37. package/assets/examples/shared-state/shared-state.ts +56 -0
  38. package/assets/examples/shared-state/state-tools.ts +68 -0
  39. package/assets/examples/worktree-development-loop/README.md +18 -17
  40. package/assets/examples/worktree-development-loop/norn.project.json +1 -1
  41. package/assets/examples/worktree-development-loop/plugin.ts +6 -26
  42. package/assets/examples/worktree-development-loop/scope.ts +4 -0
  43. package/assets/examples/worktree-development-loop/workflows/development-loop/execute.ts +14 -15
  44. package/assets/examples/worktree-development-loop/workflows/development-loop/index.ts +3 -4
  45. package/assets/examples/worktree-development-loop/workflows/development-loop/repository.ts +5 -3
  46. package/assets/examples/worktree-development-loop/workflows/development-loop/schema.ts +2 -2
  47. package/assets/examples/worktree-development-loop/workflows/implementation/execute.ts +35 -33
  48. package/assets/examples/worktree-development-loop/workflows/implementation/index.ts +2 -3
  49. package/assets/examples/worktree-development-loop/workflows/implementation/schema.ts +6 -3
  50. package/assets/examples/worktree-development-loop/workflows/planning/execute.ts +27 -16
  51. package/assets/examples/worktree-development-loop/workflows/planning/index.ts +2 -3
  52. package/assets/examples/worktree-development-loop/workflows/planning/schema.ts +4 -2
  53. package/assets/examples/worktree-development-loop/workflows/review/execute.ts +43 -31
  54. package/assets/examples/worktree-development-loop/workflows/review/index.ts +3 -4
  55. package/assets/examples/worktree-development-loop/workflows/review/schema.ts +6 -6
  56. package/assets/examples/worktree-development-loop/workflows/review-router/execute.ts +50 -44
  57. package/assets/examples/worktree-development-loop/workflows/review-router/index.ts +2 -3
  58. package/assets/examples/worktree-development-loop/workflows/review-router/schema.ts +5 -5
  59. package/assets/package.json +1 -1
  60. package/assets/packages/cli/src/cli.ts +44 -37
  61. package/assets/packages/cli/src/client.ts +9 -16
  62. package/assets/packages/cli/src/documentation-intro.ts +1 -1
  63. package/assets/packages/cli/src/generated-build-info.ts +2 -2
  64. package/assets/packages/cli/src/internal/agent-response-tool.ts +3 -3
  65. package/assets/packages/cli/src/internal/agents.ts +24 -32
  66. package/assets/packages/cli/src/internal/commands.ts +2 -14
  67. package/assets/packages/cli/src/internal/engine.ts +63 -101
  68. package/assets/packages/cli/src/internal/errors.ts +4 -4
  69. package/assets/packages/cli/src/internal/launch-request.ts +6 -6
  70. package/assets/packages/cli/src/internal/logs.ts +1 -1
  71. package/assets/packages/cli/src/internal/run-log.ts +1 -1
  72. package/assets/packages/cli/src/internal/run-state.ts +38 -23
  73. package/assets/packages/cli/src/internal/run.ts +4 -62
  74. package/assets/packages/cli/src/internal/worker-directory.ts +17 -0
  75. package/assets/packages/cli/src/internal/workflow-registry.ts +126 -111
  76. package/assets/packages/cli/src/internal/working-directory.ts +6 -0
  77. package/assets/packages/cli/src/workflow-loader.ts +213 -0
  78. package/assets/packages/core/src/workflow-transition.ts +2 -2
  79. package/assets/packages/sdk/src/api.ts +141 -329
  80. package/assets/packages/sdk/src/index.ts +1 -4
  81. package/assets/packages/sdk/src/schema.ts +3 -3
  82. package/assets/tests/workflow-ref.test.ts +53 -55
  83. package/dist/cli.js +41 -35
  84. package/dist/client.d.ts +3 -4
  85. package/dist/client.js +3 -8
  86. package/dist/documentation-intro.js +1 -1
  87. package/dist/generated-build-info.d.ts +2 -2
  88. package/dist/generated-build-info.js +2 -2
  89. package/dist/internal/agent-response-tool.js +3 -3
  90. package/dist/internal/agents.d.ts +0 -4
  91. package/dist/internal/agents.js +30 -46
  92. package/dist/internal/commands.d.ts +0 -4
  93. package/dist/internal/commands.js +2 -10
  94. package/dist/internal/engine.d.ts +4 -8
  95. package/dist/internal/engine.js +57 -84
  96. package/dist/internal/errors.d.ts +3 -3
  97. package/dist/internal/errors.js +1 -1
  98. package/dist/internal/file-coordinator.d.ts +17 -0
  99. package/dist/internal/file-coordinator.js +162 -0
  100. package/dist/internal/launch-request.d.ts +4 -4
  101. package/dist/internal/launch-request.js +2 -2
  102. package/dist/internal/logs.d.ts +1 -1
  103. package/dist/internal/run-log.d.ts +1 -1
  104. package/dist/internal/run-state.d.ts +11 -8
  105. package/dist/internal/run-state.js +34 -22
  106. package/dist/internal/run.d.ts +3 -23
  107. package/dist/internal/run.js +4 -50
  108. package/dist/internal/worker-directory.d.ts +1 -0
  109. package/dist/internal/worker-directory.js +26 -0
  110. package/dist/internal/workflow-registry.d.ts +35 -17
  111. package/dist/internal/workflow-registry.js +110 -73
  112. package/dist/internal/working-directory.d.ts +1 -0
  113. package/dist/internal/working-directory.js +9 -0
  114. package/dist/{plugin-loader.d.ts → workflow-loader.d.ts} +7 -8
  115. package/dist/workflow-loader.js +234 -0
  116. package/package.json +2 -2
  117. package/assets/docs/resources.md +0 -61
  118. package/assets/examples/coordinating-multiple-agents/queue-adapter.ts +0 -51
  119. package/assets/examples/worktree-development-loop/manifest.ts +0 -26
  120. package/assets/examples/worktree-development-loop/state.ts +0 -23
  121. package/assets/examples/worktree-development-loop/workflows/development-loop/declaration.ts +0 -8
  122. package/assets/examples/worktree-development-loop/workflows/implementation/declaration.ts +0 -8
  123. package/assets/examples/worktree-development-loop/workflows/planning/declaration.ts +0 -8
  124. package/assets/examples/worktree-development-loop/workflows/review/declaration.ts +0 -8
  125. package/assets/examples/worktree-development-loop/workflows/review-router/declaration.ts +0 -12
  126. package/assets/packages/cli/src/internal/artifacts.ts +0 -26
  127. package/assets/packages/cli/src/internal/resource-bindings.ts +0 -35
  128. package/assets/packages/cli/src/internal/run-resources.ts +0 -23
  129. package/assets/packages/cli/src/internal/state-store.ts +0 -83
  130. package/assets/packages/cli/src/plugin-loader.ts +0 -400
  131. package/assets/packages/cli/src/resources.ts +0 -69
  132. package/assets/packages/sdk/src/agent-resource-adapter.ts +0 -11
  133. package/assets/packages/sdk/src/resources.ts +0 -20
  134. package/assets/packages/sdk/src/state-adapter.ts +0 -75
  135. package/dist/internal/artifacts.d.ts +0 -10
  136. package/dist/internal/artifacts.js +0 -29
  137. package/dist/internal/resource-bindings.d.ts +0 -13
  138. package/dist/internal/resource-bindings.js +0 -34
  139. package/dist/internal/run-resources.d.ts +0 -6
  140. package/dist/internal/run-resources.js +0 -26
  141. package/dist/internal/state-store.d.ts +0 -23
  142. package/dist/internal/state-store.js +0 -103
  143. package/dist/plugin-loader.js +0 -341
  144. package/dist/resources.d.ts +0 -11
  145. package/dist/resources.js +0 -100
  146. /package/assets/packages/{sdk/src/files.ts → cli/src/internal/file-coordinator.ts} +0 -0
@@ -1,38 +1,40 @@
1
- import type { NornRunNext, NornRun } from "@vimhead.dev/norn";
2
- import { worktreeDevelopmentLoopManifest } from "../../manifest.ts";
1
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import { join, resolve } from "node:path";
3
+ import { reviewWorkflow } from "../review/execute.ts";
4
+ import type { WorkflowResult } from "@vimhead.dev/norn";
5
+ import { developmentLoopScope } from "../../scope.ts";
6
+ import { implementationArgsSchema } from "./schema.ts";
3
7
  import { ensureCommandSucceeded } from "../../shared/commands.ts";
4
- import { implementationAgentResponseSchema, type ImplementationParams } from "./schema.ts";
8
+ import { implementationAgentResponseSchema } from "./schema.ts";
5
9
 
6
- export async function executeImplementationWorkflow(
7
- run: NornRun,
8
- params: ImplementationParams,
9
- ): Promise<NornRunNext> {
10
- const repositoryPath = await run.state.get(worktreeDevelopmentLoopManifest.states.developmentLoop.repositoryPath);
11
- const planArtifact = await run.state.get(worktreeDevelopmentLoopManifest.states.planning.planArtifact);
12
- const plan = await run.artifacts.read(planArtifact);
13
- const previousReviewArtifact = await run.state.getOptional(worktreeDevelopmentLoopManifest.states.review.reviewArtifact);
14
- const previousReview = previousReviewArtifact ? await run.artifacts.read(previousReviewArtifact) : undefined;
15
- const implementation = await run.agents.prompt({
16
- label: `implementation-${params.iteration}`,
17
- cwd: repositoryPath,
18
- tools: ["read", "grep", "find", "ls", "edit", "write", "bash"],
19
- prompt: buildImplementationPrompt(params.task, plan, params.iteration, previousReview),
20
- response: implementationAgentResponseSchema,
21
- });
22
- await run.state.set(worktreeDevelopmentLoopManifest.states.implementation.implementationSummary, implementation.summary);
23
- const status = await run.commands.run({
24
- label: `implementation-${params.iteration}-status`,
25
- cwd: repositoryPath,
26
- command: "git status --short",
27
- });
28
- await ensureCommandSucceeded(status);
29
- const statusOutput = await run.logs.read(status.stdoutLog);
30
- await run.artifacts.write(`implementation/iteration-${params.iteration}-status.txt`, statusOutput);
31
- return worktreeDevelopmentLoopManifest.workflows.review({
32
- task: params.task,
33
- iteration: params.iteration,
34
- });
35
- }
10
+ export const implementationWorkflow = developmentLoopScope.workflow({
11
+ id: "implementation",
12
+ isEntrypoint: false,
13
+ instructions: "Apply one implementation pass in the current repository.",
14
+ args: implementationArgsSchema,
15
+ async execute({ args, paths, run }): Promise<WorkflowResult> {
16
+ const repositoryPath = resolve(paths.workspace, args.repositoryPath);
17
+ const plan = await readFile(join(paths.workspace, args.planPath), "utf8");
18
+ const previousReview = args.previousReviewPath ? await readFile(join(paths.workspace, args.previousReviewPath), "utf8") : undefined;
19
+ const implementation = await run.agents.prompt({
20
+ label: `implementation-${args.iteration}`,
21
+ cwd: repositoryPath,
22
+ tools: ["read", "grep", "find", "ls", "edit", "write", "bash"],
23
+ prompt: buildImplementationPrompt(args.task, plan, args.iteration, previousReview),
24
+ response: implementationAgentResponseSchema,
25
+ });
26
+ const status = await run.commands.run({
27
+ label: `implementation-${args.iteration}-status`,
28
+ cwd: repositoryPath,
29
+ command: "git status --short",
30
+ });
31
+ await ensureCommandSucceeded(status);
32
+ const statusOutput = await run.logs.read(status.stdoutLog);
33
+ await mkdir(join(paths.workspace, "implementation"), { recursive: true });
34
+ await writeFile(join(paths.workspace, `implementation/iteration-${args.iteration}-status.txt`), statusOutput);
35
+ return reviewWorkflow({ ...args, implementationSummary: implementation.summary });
36
+ }
37
+ });
36
38
 
37
39
  function buildImplementationPrompt(task: string, plan: string, iteration: number, previousReview: string | undefined): string {
38
40
  return [
@@ -1,3 +1,2 @@
1
- export { implementationWorkflow } from "./declaration.ts";
2
- export { executeImplementationWorkflow } from "./execute.ts";
3
- export { implementationAgentResponseSchema, implementationParamsSchema, type ImplementationParams } from "./schema.ts";
1
+ export { implementationWorkflow } from "./execute.ts";
2
+ export { implementationAgentResponseSchema, implementationArgsSchema, type ImplementationArgs } from "./schema.ts";
@@ -1,12 +1,15 @@
1
+ import { planningArgsSchema } from "../planning/schema.ts";
1
2
  import { Type, type StaticDecode } from "typebox";
2
3
 
3
- export const implementationParamsSchema = Type.Object({
4
- task: Type.String(),
4
+ export const implementationArgsSchema = Type.Object({
5
+ ...planningArgsSchema.properties,
5
6
  iteration: Type.Integer({ minimum: 1 }),
7
+ planPath: Type.String(),
8
+ previousReviewPath: Type.Optional(Type.String()),
6
9
  });
7
10
 
8
11
  export const implementationAgentResponseSchema = Type.Object({
9
12
  summary: Type.String(),
10
13
  });
11
14
 
12
- export type ImplementationParams = StaticDecode<typeof implementationParamsSchema>;
15
+ export type ImplementationArgs = StaticDecode<typeof implementationArgsSchema>;
@@ -1,20 +1,31 @@
1
- import type { NornRunNext, NornRun } from "@vimhead.dev/norn";
2
- import { worktreeDevelopmentLoopManifest } from "../../manifest.ts";
3
- import { planningAgentResponseSchema, type PlanningParams } from "./schema.ts";
1
+ import { mkdir, writeFile } from "node:fs/promises";
2
+ import { join, resolve } from "node:path";
3
+ import { implementationWorkflow } from "../implementation/execute.ts";
4
+ import type { WorkflowResult } from "@vimhead.dev/norn";
5
+ import { developmentLoopScope } from "../../scope.ts";
6
+ import { planningArgsSchema } from "./schema.ts";
7
+ import { planningAgentResponseSchema } from "./schema.ts";
4
8
 
5
- export async function executePlanningWorkflow(run: NornRun, params: PlanningParams): Promise<NornRunNext> {
6
- const repositoryPath = await run.state.get(worktreeDevelopmentLoopManifest.states.developmentLoop.repositoryPath);
7
- const planning = await run.agents.prompt({
8
- label: "planning",
9
- cwd: repositoryPath,
10
- tools: ["read", "grep", "find", "ls"],
11
- prompt: buildPlanningPrompt(params.task),
12
- response: planningAgentResponseSchema,
13
- });
14
- const planArtifact = await run.artifacts.write("planning/plan.md", planning.plan);
15
- await run.state.set(worktreeDevelopmentLoopManifest.states.planning.planArtifact, planArtifact);
16
- return worktreeDevelopmentLoopManifest.workflows.implementation({ task: params.task, iteration: 1 });
17
- }
9
+ export const planningWorkflow = developmentLoopScope.workflow({
10
+ id: "planning",
11
+ isEntrypoint: false,
12
+ instructions: "Create an implementation plan for a repository task.",
13
+ args: planningArgsSchema,
14
+ async execute({ args, paths, run }): Promise<WorkflowResult> {
15
+ const repositoryPath = resolve(paths.workspace, args.repositoryPath);
16
+ const planning = await run.agents.prompt({
17
+ label: "planning",
18
+ cwd: repositoryPath,
19
+ tools: ["read", "grep", "find", "ls"],
20
+ prompt: buildPlanningPrompt(args.task),
21
+ response: planningAgentResponseSchema,
22
+ });
23
+ const planPath = "planning/plan.md";
24
+ await mkdir(join(paths.workspace, "planning"), { recursive: true });
25
+ await writeFile(join(paths.workspace, planPath), planning.plan);
26
+ return implementationWorkflow({ ...args, planPath, iteration: 1 });
27
+ }
28
+ });
18
29
 
19
30
  function buildPlanningPrompt(task: string): string {
20
31
  return [
@@ -1,3 +1,2 @@
1
- export { planningWorkflow } from "./declaration.ts";
2
- export { executePlanningWorkflow } from "./execute.ts";
3
- export { planningAgentResponseSchema, planningParamsSchema, type PlanningParams } from "./schema.ts";
1
+ export { planningWorkflow } from "./execute.ts";
2
+ export { planningAgentResponseSchema, planningArgsSchema, type PlanningArgs } from "./schema.ts";
@@ -1,7 +1,9 @@
1
1
  import { Type, type StaticDecode } from "typebox";
2
2
 
3
- export const planningParamsSchema = Type.Object({
3
+ export const planningArgsSchema = Type.Object({
4
4
  task: Type.String(),
5
+ repositoryPath: Type.String(),
6
+ maxIterations: Type.Integer({ minimum: 1, maximum: 10 }),
5
7
  });
6
8
 
7
9
  export const planningAgentResponseSchema = Type.Object({
@@ -9,4 +11,4 @@ export const planningAgentResponseSchema = Type.Object({
9
11
  summary: Type.String(),
10
12
  });
11
13
 
12
- export type PlanningParams = StaticDecode<typeof planningParamsSchema>;
14
+ export type PlanningArgs = StaticDecode<typeof planningArgsSchema>;
@@ -1,36 +1,48 @@
1
- import type { NornRunNext, NornRun } from "@vimhead.dev/norn";
2
- import { worktreeDevelopmentLoopManifest } from "../../manifest.ts";
1
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import { join, resolve } from "node:path";
3
+ import { reviewRouterWorkflow } from "../review-router/execute.ts";
4
+ import type { WorkflowResult } from "@vimhead.dev/norn";
5
+ import { developmentLoopScope } from "../../scope.ts";
6
+ import { reviewArgsSchema } from "./schema.ts";
3
7
  import { ensureCommandSucceeded } from "../../shared/commands.ts";
4
- import { reviewAgentResponseSchema, type ReviewParams } from "./schema.ts";
8
+ import { reviewAgentResponseSchema } from "./schema.ts";
5
9
 
6
- export async function executeReviewWorkflow(run: NornRun, params: ReviewParams): Promise<NornRunNext> {
7
- const repositoryPath = await run.state.get(worktreeDevelopmentLoopManifest.states.developmentLoop.repositoryPath);
8
- const planArtifact = await run.state.get(worktreeDevelopmentLoopManifest.states.planning.planArtifact);
9
- const implementationSummary = await run.state.get(worktreeDevelopmentLoopManifest.states.implementation.implementationSummary);
10
- const plan = await run.artifacts.read(planArtifact);
11
- const diff = await run.commands.run({
12
- label: `review-${params.iteration}-diff`,
13
- cwd: repositoryPath,
14
- command: "git status --short && git diff --stat HEAD -- . && git diff HEAD -- .",
15
- });
16
- await ensureCommandSucceeded(diff);
17
- const diffOutput = await run.logs.read(diff.stdoutLog);
18
- await run.artifacts.write(`review/iteration-${params.iteration}-diff.txt`, diffOutput);
19
- const review = await run.agents.prompt({
20
- label: `review-${params.iteration}`,
21
- cwd: repositoryPath,
22
- tools: ["read", "grep", "find", "ls", "bash"],
23
- prompt: buildReviewPrompt(params.task, plan, implementationSummary, diffOutput),
24
- response: reviewAgentResponseSchema,
25
- });
26
- const automatedReviewArtifact = await run.artifacts.write(`review/iteration-${params.iteration}-automated.json`, JSON.stringify(review, null, 2));
27
- return worktreeDevelopmentLoopManifest.workflows.reviewRouter({
28
- iteration: params.iteration,
29
- decision: review.decision,
30
- summary: review.summary,
31
- automatedReviewArtifact,
32
- });
33
- }
10
+ export const reviewWorkflow = developmentLoopScope.workflow({
11
+ id: "review",
12
+ isEntrypoint: false,
13
+ instructions: "Review the current repository boundary changes.",
14
+ args: reviewArgsSchema,
15
+ async execute({ args, paths, run }): Promise<WorkflowResult> {
16
+ const repositoryPath = resolve(paths.workspace, args.repositoryPath);
17
+ const implementationSummary = args.implementationSummary;
18
+ const plan = await readFile(join(paths.workspace, args.planPath), "utf8");
19
+ const diff = await run.commands.run({
20
+ label: `review-${args.iteration}-diff`,
21
+ cwd: repositoryPath,
22
+ command: "git status --short && git diff --stat HEAD -- . && git diff HEAD -- .",
23
+ });
24
+ await ensureCommandSucceeded(diff);
25
+ const diffOutput = await run.logs.read(diff.stdoutLog);
26
+ await mkdir(join(paths.workspace, "review"), { recursive: true });
27
+ await writeFile(join(paths.workspace, `review/iteration-${args.iteration}-diff.txt`), diffOutput);
28
+ const review = await run.agents.prompt({
29
+ label: `review-${args.iteration}`,
30
+ cwd: repositoryPath,
31
+ tools: ["read", "grep", "find", "ls", "bash"],
32
+ prompt: buildReviewPrompt(args.task, plan, implementationSummary, diffOutput),
33
+ response: reviewAgentResponseSchema,
34
+ });
35
+ const automatedReviewPath = `review/iteration-${args.iteration}-automated.json`;
36
+ await writeFile(join(paths.workspace, automatedReviewPath), JSON.stringify(review, null, 2));
37
+ return reviewRouterWorkflow({
38
+ ...args,
39
+ iteration: args.iteration,
40
+ decision: review.decision,
41
+ summary: review.summary,
42
+ automatedReviewPath,
43
+ });
44
+ }
45
+ });
34
46
 
35
47
  function buildReviewPrompt(task: string, plan: string, implementationSummary: string, diff: string): string {
36
48
  return [
@@ -1,10 +1,9 @@
1
- export { reviewWorkflow } from "./declaration.ts";
2
- export { executeReviewWorkflow } from "./execute.ts";
1
+ export { reviewWorkflow } from "./execute.ts";
3
2
  export {
4
3
  reviewAgentResponseSchema,
5
4
  reviewDecisionSchema,
6
- reviewParamsSchema,
5
+ reviewArgsSchema,
7
6
  storedReviewSchema,
8
- type ReviewParams,
7
+ type ReviewArgs,
9
8
  type StoredReview,
10
9
  } from "./schema.ts";
@@ -1,11 +1,11 @@
1
- import { artifactRefSchema } from "@vimhead.dev/norn";
1
+ import { implementationArgsSchema } from "../implementation/schema.ts";
2
2
  import { Type, type StaticDecode } from "typebox";
3
3
 
4
4
  export const reviewDecisionSchema = Type.Enum(["accept", "revise", "blocked"]);
5
5
 
6
- export const reviewParamsSchema = Type.Object({
7
- task: Type.String(),
8
- iteration: Type.Integer({ minimum: 1 }),
6
+ export const reviewArgsSchema = Type.Object({
7
+ ...implementationArgsSchema.properties,
8
+ implementationSummary: Type.String(),
9
9
  });
10
10
 
11
11
  export const reviewAgentResponseSchema = Type.Object({
@@ -16,8 +16,8 @@ export const reviewAgentResponseSchema = Type.Object({
16
16
  export const storedReviewSchema = Type.Object({
17
17
  decision: reviewDecisionSchema,
18
18
  summary: Type.String(),
19
- reviewArtifact: artifactRefSchema,
19
+ reviewPath: Type.String(),
20
20
  });
21
21
 
22
- export type ReviewParams = StaticDecode<typeof reviewParamsSchema>;
22
+ export type ReviewArgs = StaticDecode<typeof reviewArgsSchema>;
23
23
  export type StoredReview = StaticDecode<typeof storedReviewSchema>;
@@ -1,51 +1,57 @@
1
- import type { NornWorkflowExecutionResult, NornRun } from "@vimhead.dev/norn";
2
- import { worktreeDevelopmentLoopManifest } from "../../manifest.ts";
1
+ import { mkdir, writeFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { implementationWorkflow } from "../implementation/execute.ts";
4
+ import type { WorkflowResult } from "@vimhead.dev/norn";
5
+ import { developmentLoopScope } from "../../scope.ts";
6
+ import { reviewRouterArgsSchema } from "./schema.ts";
3
7
  import type { StoredReview } from "../review/schema.ts";
4
- import type { ReviewRouterParams } from "./schema.ts";
5
8
 
6
- export async function executeReviewRouterWorkflow(
7
- run: NornRun,
8
- params: ReviewRouterParams,
9
- ): Promise<NornWorkflowExecutionResult> {
10
- const repositoryPath = await run.state.get(worktreeDevelopmentLoopManifest.states.developmentLoop.repositoryPath);
11
- const planArtifact = await run.state.get(worktreeDevelopmentLoopManifest.states.planning.planArtifact);
12
- const currentIteration = await run.state.get(worktreeDevelopmentLoopManifest.states.developmentLoop.currentIteration);
13
- const maxIterations = await run.state.get(worktreeDevelopmentLoopManifest.states.developmentLoop.maxIterations);
14
- const task = await run.state.get(worktreeDevelopmentLoopManifest.states.developmentLoop.task);
15
- const reviewArtifact = await run.artifacts.write(
16
- `review/iteration-${params.iteration}-decision.json`,
17
- JSON.stringify({ decision: params.decision, summary: params.summary, automatedReviewArtifact: params.automatedReviewArtifact }, null, 2),
18
- );
19
- const lastReview: StoredReview = { decision: params.decision, summary: params.summary, reviewArtifact };
9
+ export const reviewRouterWorkflow = developmentLoopScope.workflow({
10
+ id: "reviewRouter",
11
+ isEntrypoint: false,
12
+ instructions: "Route implementation and review iterations based on the latest review decision.",
13
+ gate: {
14
+ enabled: true,
15
+ describe: ({ args }) => `Review iteration ${args.iteration}. Confirm or edit the automated decision before continuing. Plan: ${args.planPath}.`,
16
+ fields: ["decision", "summary"] as const,
17
+ },
18
+ args: reviewRouterArgsSchema,
19
+ async execute({ args, paths, run }): Promise<WorkflowResult> {
20
+ const repositoryPath = args.repositoryPath;
21
+ const planPath = args.planPath;
22
+ const currentIteration = args.iteration;
23
+ const maxIterations = args.maxIterations;
24
+ const task = args.task;
25
+ const reviewPath = `review/iteration-${args.iteration}-decision.json`;
26
+ await mkdir(join(paths.workspace, "review"), { recursive: true });
27
+ await writeFile(
28
+ join(paths.workspace, reviewPath),
29
+ JSON.stringify({ decision: args.decision, summary: args.summary, automatedReviewPath: args.automatedReviewPath }, null, 2),
30
+ );
31
+ const lastReview: StoredReview = { decision: args.decision, summary: args.summary, reviewPath };
20
32
 
21
- await run.state.set(worktreeDevelopmentLoopManifest.states.review.reviewDecision, params.decision);
22
- await run.state.set(worktreeDevelopmentLoopManifest.states.review.reviewArtifact, reviewArtifact);
33
+ if (args.decision === "accept") {
34
+ return run.complete({
35
+ summary: `Implementation accepted after ${currentIteration} iteration(s).`,
36
+ data: { status: "done", repositoryPath, planPath, reviewPath, iterations: currentIteration, lastReview },
37
+ });
38
+ }
23
39
 
24
- if (params.decision === "accept") {
25
- return run.complete({
26
- summary: `Implementation accepted after ${currentIteration} iteration(s).`,
27
- artifacts: { plan: planArtifact, review: reviewArtifact },
28
- data: { status: "done", repositoryPath, iterations: currentIteration, lastReview },
29
- });
30
- }
40
+ if (args.decision === "blocked") {
41
+ return run.fail({
42
+ summary: args.summary,
43
+ data: { status: "blocked", repositoryPath, planPath, reviewPath, iterations: currentIteration, lastReview },
44
+ });
45
+ }
31
46
 
32
- if (params.decision === "blocked") {
33
- return run.fail({
34
- summary: params.summary,
35
- artifacts: { plan: planArtifact, review: reviewArtifact },
36
- data: { status: "blocked", repositoryPath, iterations: currentIteration, lastReview },
37
- });
38
- }
47
+ if (currentIteration >= maxIterations) {
48
+ return run.fail({
49
+ summary: `Maximum iteration count reached after ${currentIteration} iteration(s).`,
50
+ data: { status: "needs-attention", repositoryPath, planPath, reviewPath, iterations: currentIteration, lastReview },
51
+ });
52
+ }
39
53
 
40
- if (currentIteration >= maxIterations) {
41
- return run.fail({
42
- summary: `Maximum iteration count reached after ${currentIteration} iteration(s).`,
43
- artifacts: { plan: planArtifact, review: reviewArtifact },
44
- data: { status: "needs-attention", repositoryPath, iterations: currentIteration, lastReview },
45
- });
54
+ const nextIteration = currentIteration + 1;
55
+ return implementationWorkflow({ task, repositoryPath, maxIterations, planPath, iteration: nextIteration, previousReviewPath: reviewPath });
46
56
  }
47
-
48
- const nextIteration = currentIteration + 1;
49
- await run.state.set(worktreeDevelopmentLoopManifest.states.developmentLoop.currentIteration, nextIteration);
50
- return worktreeDevelopmentLoopManifest.workflows.implementation({ task, iteration: nextIteration });
51
- }
57
+ });
@@ -1,3 +1,2 @@
1
- export { reviewRouterWorkflow } from "./declaration.ts";
2
- export { executeReviewRouterWorkflow } from "./execute.ts";
3
- export { reviewRouterParamsSchema, type ReviewRouterParams } from "./schema.ts";
1
+ export { reviewRouterWorkflow } from "./execute.ts";
2
+ export { reviewRouterArgsSchema, type ReviewRouterArgs } from "./schema.ts";
@@ -1,12 +1,12 @@
1
- import { artifactRefSchema } from "@vimhead.dev/norn";
1
+ import { implementationArgsSchema } from "../implementation/schema.ts";
2
2
  import { Type, type StaticDecode } from "typebox";
3
3
  import { reviewDecisionSchema } from "../review/schema.ts";
4
4
 
5
- export const reviewRouterParamsSchema = Type.Object({
6
- iteration: Type.Integer({ minimum: 1 }),
5
+ export const reviewRouterArgsSchema = Type.Object({
6
+ ...implementationArgsSchema.properties,
7
7
  decision: reviewDecisionSchema,
8
8
  summary: Type.String(),
9
- automatedReviewArtifact: artifactRefSchema,
9
+ automatedReviewPath: Type.String(),
10
10
  });
11
11
 
12
- export type ReviewRouterParams = StaticDecode<typeof reviewRouterParamsSchema>;
12
+ export type ReviewRouterArgs = StaticDecode<typeof reviewRouterArgsSchema>;
@@ -1 +1 @@
1
- {"version":"0.1.0-tip.35359392805.1"}
1
+ {"version":"0.1.0-tip.35436871363.1"}