agentweaver 0.1.14 → 0.1.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/README.md +29 -7
  2. package/dist/artifact-manifest.js +219 -0
  3. package/dist/artifacts.js +21 -1
  4. package/dist/doctor/checks/cwd-context.js +4 -3
  5. package/dist/doctor/checks/env-diagnostics.js +193 -71
  6. package/dist/doctor/checks/flow-readiness.js +212 -203
  7. package/dist/doctor/index.js +1 -1
  8. package/dist/doctor/orchestrator.js +18 -7
  9. package/dist/doctor/runner.js +9 -8
  10. package/dist/doctor/types.js +12 -0
  11. package/dist/flow-state.js +75 -15
  12. package/dist/index.js +499 -199
  13. package/dist/interactive/blessed-session.js +361 -0
  14. package/dist/interactive/controller.js +1293 -0
  15. package/dist/interactive/create-interactive-session.js +5 -0
  16. package/dist/interactive/ink/index.js +576 -0
  17. package/dist/interactive/progress.js +245 -0
  18. package/dist/interactive/selectors.js +14 -0
  19. package/dist/interactive/session.js +1 -0
  20. package/dist/interactive/state.js +34 -0
  21. package/dist/interactive/tree.js +155 -0
  22. package/dist/interactive/types.js +1 -0
  23. package/dist/interactive/view-model.js +1 -0
  24. package/dist/interactive-ui.js +159 -194
  25. package/dist/pipeline/context.js +1 -0
  26. package/dist/pipeline/declarative-flow-runner.js +212 -6
  27. package/dist/pipeline/declarative-flows.js +27 -0
  28. package/dist/pipeline/execution-routing-config.js +15 -0
  29. package/dist/pipeline/flow-catalog.js +23 -3
  30. package/dist/pipeline/flow-run-resume.js +29 -0
  31. package/dist/pipeline/flow-specs/auto-common.json +89 -360
  32. package/dist/pipeline/flow-specs/auto-golang.json +58 -363
  33. package/dist/pipeline/flow-specs/auto-simple.json +141 -0
  34. package/dist/pipeline/flow-specs/bugz/bug-analyze.json +2 -0
  35. package/dist/pipeline/flow-specs/bugz/bug-fix.json +1 -0
  36. package/dist/pipeline/flow-specs/design-review/design-review-loop.json +304 -0
  37. package/dist/pipeline/flow-specs/design-review.json +249 -0
  38. package/dist/pipeline/flow-specs/gitlab/gitlab-diff-review.json +11 -0
  39. package/dist/pipeline/flow-specs/gitlab/gitlab-review.json +2 -0
  40. package/dist/pipeline/flow-specs/gitlab/mr-description.json +1 -0
  41. package/dist/pipeline/flow-specs/go/run-go-linter-loop.json +2 -0
  42. package/dist/pipeline/flow-specs/go/run-go-tests-loop.json +2 -0
  43. package/dist/pipeline/flow-specs/implement.json +24 -5
  44. package/dist/pipeline/flow-specs/instant-task.json +177 -0
  45. package/dist/pipeline/flow-specs/normalize-task-source.json +311 -0
  46. package/dist/pipeline/flow-specs/plan-revise.json +267 -0
  47. package/dist/pipeline/flow-specs/plan.json +48 -70
  48. package/dist/pipeline/flow-specs/review/review-fix.json +24 -4
  49. package/dist/pipeline/flow-specs/review/review-loop.json +351 -45
  50. package/dist/pipeline/flow-specs/review/review-project-loop.json +590 -0
  51. package/dist/pipeline/flow-specs/review/review-project.json +12 -0
  52. package/dist/pipeline/flow-specs/review/review.json +37 -31
  53. package/dist/pipeline/flow-specs/task-describe.json +62 -2
  54. package/dist/pipeline/flow-specs/task-source/jira-fetch.json +70 -0
  55. package/dist/pipeline/flow-specs/task-source/manual-input.json +216 -0
  56. package/dist/pipeline/node-registry.js +49 -1
  57. package/dist/pipeline/node-runner.js +3 -2
  58. package/dist/pipeline/nodes/build-review-fix-prompt-node.js +5 -1
  59. package/dist/pipeline/nodes/clear-ready-to-merge-node.js +11 -0
  60. package/dist/pipeline/nodes/commit-message-form-node.js +8 -0
  61. package/dist/pipeline/nodes/design-review-verdict-node.js +36 -0
  62. package/dist/pipeline/nodes/ensure-summary-json-node.js +70 -0
  63. package/dist/pipeline/nodes/fetch-gitlab-diff-node.js +19 -2
  64. package/dist/pipeline/nodes/fetch-gitlab-review-node.js +19 -2
  65. package/dist/pipeline/nodes/flow-run-node.js +226 -7
  66. package/dist/pipeline/nodes/git-commit-form-node.js +8 -0
  67. package/dist/pipeline/nodes/gitlab-review-artifacts-node.js +19 -2
  68. package/dist/pipeline/nodes/jira-fetch-node.js +50 -4
  69. package/dist/pipeline/nodes/llm-prompt-node.js +32 -12
  70. package/dist/pipeline/nodes/planning-bundle-node.js +10 -0
  71. package/dist/pipeline/nodes/review-verdict-node.js +86 -0
  72. package/dist/pipeline/nodes/select-files-form-node.js +8 -0
  73. package/dist/pipeline/nodes/structured-summary-node.js +24 -0
  74. package/dist/pipeline/nodes/user-input-node.js +38 -3
  75. package/dist/pipeline/nodes/write-selection-file-node.js +20 -4
  76. package/dist/pipeline/prompt-registry.js +5 -1
  77. package/dist/pipeline/prompt-runtime.js +4 -1
  78. package/dist/pipeline/review-iteration.js +26 -0
  79. package/dist/pipeline/spec-compiler.js +2 -0
  80. package/dist/pipeline/spec-types.js +5 -0
  81. package/dist/pipeline/spec-validator.js +14 -0
  82. package/dist/pipeline/value-resolver.js +84 -1
  83. package/dist/prompts.js +82 -13
  84. package/dist/review-severity.js +45 -0
  85. package/dist/runtime/artifact-registry.js +402 -0
  86. package/dist/runtime/design-review-input-contract.js +113 -0
  87. package/dist/runtime/env-loader.js +3 -0
  88. package/dist/runtime/execution-routing-store.js +134 -0
  89. package/dist/runtime/execution-routing.js +227 -0
  90. package/dist/runtime/interactive-execution-routing.js +462 -0
  91. package/dist/runtime/plan-revise-input-contract.js +147 -0
  92. package/dist/runtime/planning-bundle.js +123 -0
  93. package/dist/runtime/ready-to-merge.js +31 -0
  94. package/dist/runtime/review-input-contract.js +100 -0
  95. package/dist/scope.js +11 -2
  96. package/dist/structured-artifact-schema-registry.js +10 -0
  97. package/dist/structured-artifact-schemas.json +257 -1
  98. package/dist/structured-artifacts.js +83 -6
  99. package/dist/user-input.js +70 -3
  100. package/package.json +6 -3
package/README.md CHANGED
@@ -10,6 +10,8 @@ Typical usage looks like:
10
10
 
11
11
  The important part is not that exact chain. The point is that AgentWeaver lets you design, operate, and evolve durable agent harnesses instead of accumulating one-off prompts and shell glue.
12
12
 
13
+ For planning-heavy work, a typical path can now include `plan -> design-review -> implement`, where `design-review` critiques planning artifacts before coding starts.
14
+
13
15
  ## What It Does
14
16
 
15
17
  - Fetches Jira issue context by issue key or browse URL
@@ -60,7 +62,7 @@ This keeps workflow design in JSON while keeping implementation details in typed
60
62
  - `src/pipeline/` — declarative flow loading, compilation, validation, runtime, and built-in flow specs
61
63
  - `src/pipeline/nodes/` — reusable runtime nodes used by flow specs
62
64
  - `src/runtime/` — shared runtime services such as command resolution and subprocess execution
63
- - `src/interactive-ui.ts`full-screen interactive UI
65
+ - `src/interactive/`Ink-based interactive session, controller, state, and view-model logic
64
66
  - `src/markdown.ts` — markdown rendering for terminal output
65
67
  - `src/structured-artifact-schemas.json` — schemas for machine-readable artifacts
66
68
  - `tests/` — automated tests for pipeline behavior
@@ -70,6 +72,7 @@ This keeps workflow design in JSON while keeping implementation details in typed
70
72
  User-invokable built-in commands currently map to these flow specs:
71
73
 
72
74
  - `plan` — fetches Jira task with attachments, generates clarifying questions for the developer, collects answers, and produces design, implementation plan, and QA plan as structured JSON and markdown artifacts
75
+ - `design-review` — performs a structured critique of the latest planning artifacts and writes a dedicated `design-review/v1` artifact; `approved_with_warnings` is treated as ready to proceed and may still produce `ready-to-merge.md`
73
76
  - `task-describe` — generates a brief task description from a Jira issue or from manual input; when Jira is provided, fetches the issue and summarizes it; otherwise accepts free-form text and analyzes the codebase to produce a richer description
74
77
  - `implement` — runs LLM-backed implementation based on previously approved design and plan artifacts; executes code changes locally in the project working directory
75
78
  - `review` — performs code review of current changes against the task design and plan; produces structured review findings with severity levels and a ready-to-merge verdict
@@ -84,7 +87,8 @@ User-invokable built-in commands currently map to these flow specs:
84
87
  - `run-go-tests-loop` — runs `run_go_tests.py` and analyzes failures; if tests fail, sends the error output to LLM for a fix and retries; repeats up to 5 attempts, stopping early on success
85
88
  - `run-go-linter-loop` — runs `run_go_linter.py` and analyzes output; if the linter reports issues, sends them to LLM for a fix and retries; repeats up to 5 attempts, stopping early on success
86
89
  - `auto-golang` — end-to-end resumable pipeline for Go projects: plan → implement → linter loop → test loop → review loop → final linter loop → final test loop; supports `--from` to restart from a specific phase and `auto-status`/`auto-reset` for state management
87
- - `auto-common` — end-to-end resumable pipeline without language-specific checks: plan → implement → review loop; simplified alternative to auto-golang for projects that do not need Go linter/test loops
90
+ - `auto-common` — planning-aware pipeline with a mandatory design-review gate before implementation: plan → design-review loop → implement → review loop; design-review can iterate with `plan-revise` up to 3 times, and if the final verdict still requires revision the operator must explicitly choose whether to continue with the latest planning artifacts or stop
91
+ - `auto-simple` — preserved simplified pipeline equivalent to the legacy auto-common behavior: plan → implement → review loop; no planning review gate, suitable for projects that do not need design review before coding
88
92
  - `doctor` — diagnostics command that runs system, executor, and flow readiness health checks; supports filtering by category or check ID and JSON output
89
93
 
90
94
  There are also built-in nested/helper flows that are loaded declaratively but are not direct top-level CLI commands, for example `review-project` (project-level code review used internally when no prior design/plan artifacts are present).
@@ -201,6 +205,7 @@ Direct flow execution:
201
205
 
202
206
  ```bash
203
207
  agentweaver plan DEMO-1234
208
+ agentweaver design-review DEMO-1234
204
209
  agentweaver task-describe DEMO-1234
205
210
  agentweaver implement DEMO-1234
206
211
  agentweaver review DEMO-1234
@@ -216,6 +221,7 @@ agentweaver run-go-tests-loop DEMO-1234
216
221
  agentweaver run-go-linter-loop DEMO-1234
217
222
  agentweaver auto-golang DEMO-1234
218
223
  agentweaver auto-common DEMO-1234
224
+ agentweaver auto-simple DEMO-1234
219
225
  agentweaver doctor
220
226
  agentweaver doctor --json
221
227
  agentweaver doctor <category>|<check-id>
@@ -225,6 +231,7 @@ From a source checkout:
225
231
 
226
232
  ```bash
227
233
  node dist/index.js plan DEMO-1234
234
+ node dist/index.js design-review DEMO-1234
228
235
  node dist/index.js implement DEMO-1234
229
236
  node dist/index.js review DEMO-1234
230
237
  node dist/index.js auto-golang DEMO-1234
@@ -238,6 +245,7 @@ agentweaver --help
238
245
  agentweaver --version
239
246
  agentweaver auto-golang --help-phases
240
247
  agentweaver auto-common --help-phases
248
+ agentweaver auto-simple --help-phases
241
249
  agentweaver auto-golang --from <phase> DEMO-1234
242
250
  agentweaver auto-status DEMO-1234
243
251
  agentweaver auto-reset DEMO-1234
@@ -252,13 +260,13 @@ Notes:
252
260
  - `--prompt <text>` appends extra instructions to the prompt
253
261
  - `--scope <name>` is supported by scope-flexible flows such as `implement`, `review`, `review-fix`, `review-loop`, `run-go-tests-loop`, `run-go-linter-loop`, `gitlab-review`, and `gitlab-diff-review`
254
262
  - `--md-lang <en|ru>` currently applies to `plan`
255
- - `--force` only affects interactive mode and forces regeneration of task summary in Jira-backed flows
263
+ - `--force` only affects interactive mode: it skips loading cached summary-pane content on startup so Jira-backed flows that regenerate summary artifacts can repopulate it during the run
256
264
  - Jira-backed flows ask for Jira input interactively when it is omitted
257
265
  - `task-describe` can also work from manual task description input without Jira
258
266
  - `gitlab-review` and `gitlab-diff-review` ask for a GitLab merge request URL interactively
259
267
  - `auto-status` and `auto-reset` currently operate on persisted state for `auto-golang`
260
268
 
261
- ## `auto-golang` and `auto-common`
269
+ ## `auto-golang`, `auto-common`, and `auto-simple`
262
270
 
263
271
  `auto-golang` is the main resumable end-to-end automation flow. It stores persisted execution state and supports:
264
272
 
@@ -268,7 +276,9 @@ Notes:
268
276
  - reset via `auto-reset`
269
277
  - resume validation against saved launch profile and required artifacts
270
278
 
271
- `auto-common` is a separate built-in automation flow with its own phase list, but it does not currently have dedicated `auto-status` or `auto-reset` commands.
279
+ `auto-common` is the planning-aware built-in automation flow. After `plan`, it runs a `design-review` loop and blocks implementation until the verdict is `approved` or `approved_with_warnings`. When the verdict is `needs_revision`, it runs `plan-revise` and then another `design-review`, for up to 3 design-review iterations total. If the final verdict still requires revision, the pipeline asks the operator whether to continue with the latest planning artifacts or stop before `implement`.
280
+
281
+ `auto-simple` is the preserved simplified pipeline: `plan → implement → review loop`, with no planning review gate and no revise rounds. It is behaviorally equivalent to the legacy `auto-common` before the planning gate was introduced.
272
282
 
273
283
  ## Launch Profiles and Resume
274
284
 
@@ -295,7 +305,12 @@ The runtime uses artifacts as the contract between stages, including markdown ou
295
305
 
296
306
  ## Interactive TUI
297
307
 
298
- Running without a command opens the full-screen TUI. It acts as the operator console for the harness: browsing flows, launching them in scope, following activity, and reviewing summaries.
308
+ Running without a command opens the full-screen TUI. It acts as the operator console for the harness: browsing flows, launching them in scope, following current execution, and reviewing summaries.
309
+
310
+ Interactive mode is Ink-only. It requires:
311
+
312
+ - a real TTY for both stdin and stdout
313
+ - installed runtime dependencies from `npm install`
299
314
 
300
315
  Current navigation:
301
316
 
@@ -303,10 +318,17 @@ Current navigation:
303
318
  - `Left` / `Right` — collapse or expand folders
304
319
  - `Enter` — toggle folder or run selected flow
305
320
  - `Tab` / `Shift+Tab` — switch panes
306
- - `PgUp` / `PgDn` / `Home` / `End` — scroll focused pane
321
+ - `PgUp` / `PgDn` — scroll focused pane
307
322
  - `h` — open help
308
323
  - `q` or `Ctrl+C` — exit
309
324
 
325
+ Current layout:
326
+
327
+ - left column: `Flows`, `Flow Description`, `Status`
328
+ - right column: `Current Flow`, optional `Task Summary`, `Activity`
329
+ - `Current Flow` is intentionally tall and scrollable; in the current layout it uses the same height budget as `Flows`
330
+ - the `Task Summary` pane is runtime-driven and shows whichever markdown artifact the active flow publishes into summary state, such as a normalized task context or a cached task summary
331
+
310
332
  Flow discovery behavior:
311
333
 
312
334
  - built-in flows are loaded from `src/pipeline/flow-specs/`
@@ -0,0 +1,219 @@
1
+ import path from "node:path";
2
+ import { TaskRunnerError } from "./errors.js";
3
+ import { validateStructuredArtifactValue } from "./structured-artifacts.js";
4
+ export const ARTIFACT_MANIFEST_SCHEMA_ID = "artifact-manifest/v1";
5
+ export const ARTIFACT_MANIFEST_SCHEMA_VERSION = 1;
6
+ export const ARTIFACT_LIFECYCLE_STATUSES = ["ready", "superseded", "stale"];
7
+ export const ARTIFACT_PAYLOAD_FAMILIES = [
8
+ "structured-json",
9
+ "markdown",
10
+ "plain-text",
11
+ "helper-json",
12
+ "opaque-file",
13
+ ];
14
+ const STRUCTURED_JSON_SCHEMAS_BY_PREFIX = [
15
+ { prefix: "bug-analyze-", schemaId: "bug-analysis/v1" },
16
+ { prefix: "bug-fix-design-", schemaId: "bug-fix-design/v1" },
17
+ { prefix: "bug-fix-plan-", schemaId: "bug-fix-plan/v1" },
18
+ { prefix: "design-review-", schemaId: "design-review/v1" },
19
+ { prefix: "design-", schemaId: "implementation-design/v1" },
20
+ { prefix: "gitlab-diff-", schemaId: "gitlab-mr-diff/v1" },
21
+ { prefix: "gitlab-review-", schemaId: "gitlab-review/v1" },
22
+ { prefix: "jira-description-", schemaId: "jira-description/v1" },
23
+ { prefix: "mr-description-", schemaId: "mr-description/v1" },
24
+ { prefix: "plan-", schemaId: "implementation-plan/v1" },
25
+ { prefix: "planning-questions-", schemaId: "planning-questions/v1" },
26
+ { prefix: "qa-", schemaId: "qa-plan/v1" },
27
+ { prefix: "review-assessment-", schemaId: "review-assessment/v1" },
28
+ { prefix: "review-fix-", schemaId: "review-fix-report/v1" },
29
+ { prefix: "review-", schemaId: "review-findings/v1" },
30
+ { prefix: "task-context-", schemaId: "task-context/v1" },
31
+ { prefix: "task-", schemaId: "task-summary/v1" },
32
+ ];
33
+ const LOGICAL_KEY_PATTERN = "^[a-z0-9][a-z0-9._/-]*$";
34
+ const CONTENT_HASH_PATTERN = "^sha256:[a-f0-9]{64}$";
35
+ const ARTIFACT_ID_PATTERN = /^(?<scope>.+):(?<logicalKey>[a-z0-9][a-z0-9._/-]*):v(?<version>[1-9]\d*)$/;
36
+ const LOGICAL_REF_PATTERN = /^(?<logicalKey>[a-z0-9][a-z0-9._/-]*)@(?<selector>latest|v[1-9]\d*)$/;
37
+ export function parseSchemaVersion(schemaId) {
38
+ const match = /\/v(\d+)$/.exec(schemaId);
39
+ return match ? Number.parseInt(match[1] ?? "1", 10) : 1;
40
+ }
41
+ function normalizePathSeparators(value) {
42
+ return value.replace(/\\/g, "/");
43
+ }
44
+ function removeScopeSuffix(baseName, scopeKey) {
45
+ if (!scopeKey) {
46
+ return baseName;
47
+ }
48
+ const ext = path.extname(baseName);
49
+ const stem = ext ? baseName.slice(0, -ext.length) : baseName;
50
+ const escapedScope = scopeKey.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
51
+ const patterns = [
52
+ new RegExp(`-${escapedScope}-iter-\\d+$`),
53
+ new RegExp(`-${escapedScope}-\\d+$`),
54
+ new RegExp(`-${escapedScope}$`),
55
+ ];
56
+ for (const pattern of patterns) {
57
+ if (pattern.test(stem)) {
58
+ return `${stem.replace(pattern, "")}${ext}`;
59
+ }
60
+ }
61
+ if (stem === scopeKey) {
62
+ return `scope${ext}`;
63
+ }
64
+ return baseName;
65
+ }
66
+ export function buildLogicalKeyForPayload(scopeKey, payloadPath) {
67
+ const normalized = normalizePathSeparators(payloadPath);
68
+ const normalizedScopeKey = typeof scopeKey === "string" && scopeKey.trim().length > 0 ? scopeKey : null;
69
+ const scopeMarker = normalizedScopeKey
70
+ ? normalizePathSeparators(`/.agentweaver/scopes/${normalizedScopeKey}/`)
71
+ : null;
72
+ const markerIndex = scopeMarker ? normalized.lastIndexOf(scopeMarker) : -1;
73
+ const artifactsMarker = normalizePathSeparators("/.artifacts/");
74
+ const artifactsIndex = normalized.lastIndexOf(artifactsMarker);
75
+ const relative = markerIndex >= 0 && scopeMarker
76
+ ? normalized.slice(markerIndex + scopeMarker.length)
77
+ : artifactsIndex >= 0
78
+ ? normalized.slice(artifactsIndex + 1)
79
+ : path.basename(normalized);
80
+ const directory = path.posix.dirname(relative);
81
+ const baseName = path.posix.basename(relative);
82
+ const normalizedBaseName = removeScopeSuffix(baseName, normalizedScopeKey)
83
+ .replace(/-\d+(?=\.[^.]+$)/, "")
84
+ .replace(/[^a-zA-Z0-9._/-]+/g, "-")
85
+ .replace(/-+/g, "-")
86
+ .toLowerCase();
87
+ const combined = directory === "." ? normalizedBaseName : `${directory}/${normalizedBaseName}`;
88
+ return combined.replace(/^\.artifacts\//, "artifacts/");
89
+ }
90
+ export function buildPublicationKey(input) {
91
+ return `${input.publicationRunId ?? input.runId}:${input.flowId}:${input.phaseId}:${input.stepId}:${input.logicalKey}`;
92
+ }
93
+ export function buildArtifactId(scopeKey, logicalKey, version) {
94
+ return `${scopeKey}:${logicalKey}:v${version}`;
95
+ }
96
+ export function parseArtifactId(value) {
97
+ const match = ARTIFACT_ID_PATTERN.exec(value);
98
+ if (!match?.groups) {
99
+ return null;
100
+ }
101
+ const scopeKey = match.groups.scope;
102
+ const logicalKey = match.groups.logicalKey;
103
+ const versionText = match.groups.version;
104
+ if (!scopeKey || !logicalKey || !versionText) {
105
+ return null;
106
+ }
107
+ return {
108
+ scopeKey,
109
+ logicalKey,
110
+ version: Number.parseInt(versionText, 10),
111
+ };
112
+ }
113
+ export function parseArtifactReference(value) {
114
+ const parsedId = parseArtifactId(value);
115
+ if (parsedId) {
116
+ return {
117
+ kind: "artifact-id",
118
+ artifactId: value,
119
+ parsedId,
120
+ };
121
+ }
122
+ const match = LOGICAL_REF_PATTERN.exec(value);
123
+ if (!match?.groups) {
124
+ return null;
125
+ }
126
+ const logicalKey = match.groups.logicalKey;
127
+ const selector = match.groups.selector;
128
+ if (!logicalKey || !selector) {
129
+ return null;
130
+ }
131
+ return {
132
+ kind: "logical-ref",
133
+ logicalKey,
134
+ version: selector === "latest" ? "latest" : Number.parseInt(selector.slice(1), 10),
135
+ };
136
+ }
137
+ export function inferPayloadContract(scopeKey, payloadPath, override) {
138
+ if (override?.payloadFamily && override.schemaId && override.schemaVersion) {
139
+ return {
140
+ payloadFamily: override.payloadFamily,
141
+ schemaId: override.schemaId,
142
+ schemaVersion: override.schemaVersion,
143
+ };
144
+ }
145
+ const baseName = path.basename(payloadPath);
146
+ if (override?.schemaId) {
147
+ return {
148
+ payloadFamily: override.payloadFamily ?? "structured-json",
149
+ schemaId: override.schemaId,
150
+ schemaVersion: override.schemaVersion ?? parseSchemaVersion(override.schemaId),
151
+ };
152
+ }
153
+ if (payloadPath.endsWith(".json")) {
154
+ if (baseName === `${scopeKey}.json` || baseName === `${scopeKey}-enriched.json`) {
155
+ return { payloadFamily: "helper-json", schemaId: "helper-json/v1", schemaVersion: 1 };
156
+ }
157
+ if (baseName.startsWith("jira-attachments-")) {
158
+ return { payloadFamily: "helper-json", schemaId: "helper-json/v1", schemaVersion: 1 };
159
+ }
160
+ if (baseName.startsWith("planning-answers-")) {
161
+ return { payloadFamily: "structured-json", schemaId: "user-input/v1", schemaVersion: 1 };
162
+ }
163
+ if (baseName.startsWith("instant-task-input-")) {
164
+ return { payloadFamily: "structured-json", schemaId: "user-input/v1", schemaVersion: 1 };
165
+ }
166
+ for (const candidate of STRUCTURED_JSON_SCHEMAS_BY_PREFIX) {
167
+ if (baseName.startsWith(candidate.prefix)) {
168
+ return {
169
+ payloadFamily: "structured-json",
170
+ schemaId: candidate.schemaId,
171
+ schemaVersion: parseSchemaVersion(candidate.schemaId),
172
+ };
173
+ }
174
+ }
175
+ return { payloadFamily: "helper-json", schemaId: "helper-json/v1", schemaVersion: 1 };
176
+ }
177
+ if (payloadPath.endsWith(".md")) {
178
+ return { payloadFamily: "markdown", schemaId: "markdown/v1", schemaVersion: 1 };
179
+ }
180
+ if (payloadPath.endsWith(".txt")) {
181
+ return { payloadFamily: "plain-text", schemaId: "plain-text/v1", schemaVersion: 1 };
182
+ }
183
+ return { payloadFamily: "opaque-file", schemaId: "opaque-file/v1", schemaVersion: 1 };
184
+ }
185
+ export function createProducerSummary(input) {
186
+ const parts = [input.node];
187
+ if (input.executor) {
188
+ parts.push(`via ${input.executor}`);
189
+ }
190
+ if (input.model) {
191
+ parts.push(`model ${input.model}`);
192
+ }
193
+ return parts.join(" ");
194
+ }
195
+ export function validateArtifactManifest(manifest, label = "$") {
196
+ validateStructuredArtifactValue(manifest, ARTIFACT_MANIFEST_SCHEMA_ID, label);
197
+ if (!new RegExp(LOGICAL_KEY_PATTERN).test(manifest.logical_key)) {
198
+ throw new TaskRunnerError(`Structured artifact ${label} failed schema ${ARTIFACT_MANIFEST_SCHEMA_ID} validation:\n${label}.logical_key must be a string with the expected format`);
199
+ }
200
+ if (!new RegExp(CONTENT_HASH_PATTERN).test(manifest.content_hash)) {
201
+ throw new TaskRunnerError(`Structured artifact ${label} failed schema ${ARTIFACT_MANIFEST_SCHEMA_ID} validation:\n${label}.content_hash must be a string with the expected format`);
202
+ }
203
+ }
204
+ export function diagnosticsForManifest(manifest, validatePayload) {
205
+ try {
206
+ validatePayload(manifest.schema_id, manifest.payload_path);
207
+ return [];
208
+ }
209
+ catch (error) {
210
+ const message = error.message;
211
+ return [
212
+ {
213
+ code: message.includes("not registered") ? "missing-schema" : "invalid-schema",
214
+ severity: "error",
215
+ message,
216
+ },
217
+ ];
218
+ }
219
+ }
package/dist/artifacts.js CHANGED
@@ -2,7 +2,6 @@ import { existsSync, mkdirSync, readdirSync } from "node:fs";
2
2
  import path from "node:path";
3
3
  import process from "node:process";
4
4
  import { TaskRunnerError } from "./errors.js";
5
- export const REVIEW_FILE_RE = /^review-(.+)-(\d+)\.md$/;
6
5
  export const READY_TO_MERGE_FILE = "ready-to-merge.md";
7
6
  export function scopesRootDir() {
8
7
  return path.join(process.cwd(), ".agentweaver", "scopes");
@@ -25,6 +24,12 @@ export function scopeArtifactsDir(scopeKey) {
25
24
  export function scopeArtifactsFile(scopeKey, fileName) {
26
25
  return path.join(scopeArtifactsDir(scopeKey), fileName);
27
26
  }
27
+ export function artifactManifestSidecarPath(payloadPath) {
28
+ return `${payloadPath}.manifest.json`;
29
+ }
30
+ export function artifactIndexFile(scopeKey) {
31
+ return scopeArtifactsFile(scopeKey, "artifact-index.json");
32
+ }
28
33
  export function taskWorkspaceDir(taskKey) {
29
34
  return scopeWorkspaceDir(taskKey);
30
35
  }
@@ -152,9 +157,18 @@ export function jiraDescriptionFile(taskKey, iteration) {
152
157
  export function jiraDescriptionJsonFile(taskKey, iteration) {
153
158
  return versionedJsonArtifactFile(taskKey, "jira-description", iteration);
154
159
  }
160
+ export function taskContextFile(taskKey, iteration) {
161
+ return versionedMarkdownArtifactFile(taskKey, "task-context", iteration);
162
+ }
163
+ export function taskContextJsonFile(taskKey, iteration) {
164
+ return versionedJsonArtifactFile(taskKey, "task-context", iteration);
165
+ }
155
166
  export function taskDescribeInputJsonFile(taskKey) {
156
167
  return taskArtifactsFile(taskKey, `task-describe-input-${taskKey}.json`);
157
168
  }
169
+ export function instantTaskInputJsonFile(taskKey) {
170
+ return taskArtifactsFile(taskKey, `instant-task-input-${taskKey}.json`);
171
+ }
158
172
  export function gitStatusJsonFile(taskKey) {
159
173
  return taskArtifactsFile(taskKey, `git-status-${taskKey}.json`);
160
174
  }
@@ -219,6 +233,12 @@ export function reviewFile(taskKey, iteration) {
219
233
  export function reviewJsonFile(taskKey, iteration) {
220
234
  return artifactJsonFile("review", taskKey, iteration);
221
235
  }
236
+ export function designReviewFile(taskKey, iteration) {
237
+ return artifactFile("design-review", taskKey, iteration);
238
+ }
239
+ export function designReviewJsonFile(taskKey, iteration) {
240
+ return artifactJsonFile("design-review", taskKey, iteration);
241
+ }
222
242
  export function reviewFixFile(taskKey, iteration) {
223
243
  return artifactFile("review-fix", taskKey, iteration);
224
244
  }
@@ -1,7 +1,6 @@
1
1
  import { accessSync, constants, existsSync } from "node:fs";
2
- import { DoctorStatus } from "../types.js";
2
+ import { DoctorImpact, DoctorStatus } from "../types.js";
3
3
  import { CATEGORY } from "./category.js";
4
- const SOFT_CHECK_ID = "cwd-context-01";
5
4
  export const cwdContextCheck = {
6
5
  id: "cwd-context-01",
7
6
  category: CATEGORY.CWD_CONTEXT,
@@ -37,6 +36,7 @@ export const cwdContextCheck = {
37
36
  if (permissionStatus === DoctorStatus.Ok && gitStatus === DoctorStatus.Ok) {
38
37
  return {
39
38
  id: "cwd-context-01",
39
+ impact: DoctorImpact.Blocking,
40
40
  status: DoctorStatus.Ok,
41
41
  title: "cwd-context",
42
42
  message: `${permissionMessage}; ${gitStatusMessage}`,
@@ -46,6 +46,7 @@ export const cwdContextCheck = {
46
46
  if (permissionStatus === DoctorStatus.Ok && gitStatus === DoctorStatus.Warn) {
47
47
  return {
48
48
  id: "cwd-context-01",
49
+ impact: DoctorImpact.Advisory,
49
50
  status: DoctorStatus.Warn,
50
51
  title: "cwd-context",
51
52
  message: `${permissionMessage}; ${gitStatusMessage} (soft warning)`,
@@ -55,6 +56,7 @@ export const cwdContextCheck = {
55
56
  }
56
57
  const result = {
57
58
  id: "cwd-context-01",
59
+ impact: DoctorImpact.Blocking,
58
60
  status: permissionStatus,
59
61
  title: "cwd-context",
60
62
  message: permissionMessage,
@@ -66,4 +68,3 @@ export const cwdContextCheck = {
66
68
  return result;
67
69
  },
68
70
  };
69
- export const SOFT_CHECK_IDS = [SOFT_CHECK_ID];