taskplane 0.22.10 → 0.22.12
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.
- package/bin/rpc-wrapper.mjs +205 -4
- package/extensions/task-runner.ts +10 -1
- package/extensions/taskplane/cleanup.ts +55 -7
- package/extensions/taskplane/diagnostics.ts +1 -1
- package/extensions/taskplane/engine-worker.ts +1 -1
- package/extensions/taskplane/engine.ts +3 -1
- package/extensions/taskplane/execution.ts +5 -5
- package/extensions/taskplane/extension.ts +118 -4
- package/extensions/taskplane/mailbox.ts +341 -0
- package/extensions/taskplane/merge.ts +11 -2
- package/extensions/taskplane/persistence.ts +166 -5
- package/extensions/taskplane/resume.ts +3 -1
- package/extensions/taskplane/supervisor-primer.md +3 -3
- package/extensions/taskplane/supervisor.ts +2 -2
- package/extensions/taskplane/types.ts +247 -9
- package/extensions/taskplane/verification.ts +14 -9
- package/package.json +1 -1
- package/templates/agents/supervisor.md +1 -1
- package/templates/agents/task-worker.md +40 -23
|
@@ -98,6 +98,26 @@ export interface ParsedTask {
|
|
|
98
98
|
resolvedRepoId?: string;
|
|
99
99
|
/** Optional explicit segment DAG metadata from `## Segment DAG`. */
|
|
100
100
|
explicitSegmentDag?: PromptSegmentDagMetadata;
|
|
101
|
+
/**
|
|
102
|
+
* Repo ID that owns task packet files (v4, TP-081).
|
|
103
|
+
* Populated by execution engine in workspace mode. Undefined in repo mode.
|
|
104
|
+
*/
|
|
105
|
+
packetRepoId?: string;
|
|
106
|
+
/**
|
|
107
|
+
* Absolute path to task folder in the packet repo worktree (v4, TP-081).
|
|
108
|
+
* Populated by execution engine. Undefined if not yet resolved.
|
|
109
|
+
*/
|
|
110
|
+
packetTaskPath?: string;
|
|
111
|
+
/**
|
|
112
|
+
* Segment IDs for this task (v4, TP-081).
|
|
113
|
+
* Populated from TaskSegmentPlan during execution.
|
|
114
|
+
*/
|
|
115
|
+
segmentIds?: string[];
|
|
116
|
+
/**
|
|
117
|
+
* Currently active segment ID (v4, TP-081).
|
|
118
|
+
* Null when no segment is active.
|
|
119
|
+
*/
|
|
120
|
+
activeSegmentId?: string | null;
|
|
101
121
|
}
|
|
102
122
|
|
|
103
123
|
/** Build a stable segment ID from task + repo identity (`<taskId>::<repoId>`). */
|
|
@@ -205,7 +225,7 @@ export interface TaskArea {
|
|
|
205
225
|
export interface TaskRunnerConfig {
|
|
206
226
|
task_areas: Record<string, TaskArea>;
|
|
207
227
|
reference_docs: Record<string, string>;
|
|
208
|
-
/** Named testing/verification commands (e.g., { test: "
|
|
228
|
+
/** Named testing/verification commands (e.g., { test: "node --test tests/*.test.ts" }). Used for baseline fingerprinting (TP-032). */
|
|
209
229
|
testing_commands?: Record<string, string>;
|
|
210
230
|
/**
|
|
211
231
|
* Model fallback behavior when a configured model becomes unavailable mid-batch.
|
|
@@ -1015,6 +1035,12 @@ export interface OrchBatchRuntimeState {
|
|
|
1015
1035
|
* Populated from persisted state on resume; defaults used for new batches.
|
|
1016
1036
|
*/
|
|
1017
1037
|
diagnostics?: BatchDiagnostics;
|
|
1038
|
+
/**
|
|
1039
|
+
* v4 segment records carried forward across resume cycles (TP-081).
|
|
1040
|
+
* Populated from persisted state on resume; empty for new batches
|
|
1041
|
+
* and repo-mode batches.
|
|
1042
|
+
*/
|
|
1043
|
+
segments?: PersistedSegmentRecord[];
|
|
1018
1044
|
/**
|
|
1019
1045
|
* Unknown top-level fields from loaded persisted state.
|
|
1020
1046
|
* Carried forward so they survive serialization roundtrips.
|
|
@@ -2304,15 +2330,22 @@ export function defaultBatchDiagnostics(): BatchDiagnostics {
|
|
|
2304
2330
|
* exit summaries, batch cost). Task records gain optional
|
|
2305
2331
|
* `exitDiagnostic` alongside legacy `exitReason`.
|
|
2306
2332
|
* Both new sections are optional for v1/v2 migration paths.
|
|
2333
|
+
* v4 — Segment execution (TP-081). Adds optional `segments` array
|
|
2334
|
+
* for persisting per-segment runtime state. Task records gain
|
|
2335
|
+
* optional `packetRepoId`, `packetTaskPath`, `segmentIds`, and
|
|
2336
|
+
* `activeSegmentId` fields. All v4-specific fields are optional
|
|
2337
|
+
* for backward compatibility with v1/v2/v3 migration paths.
|
|
2338
|
+
* When migrating from v3, `segments` defaults to `[]` and
|
|
2339
|
+
* task-level segment fields default to `undefined`.
|
|
2307
2340
|
*
|
|
2308
2341
|
* Compatibility policy:
|
|
2309
|
-
* - loadBatchState() accepts v1, v2, and
|
|
2310
|
-
* auto-upconverted
|
|
2342
|
+
* - loadBatchState() accepts v1, v2, v3, and v4 files. v1→v2→v3→v4
|
|
2343
|
+
* auto-upconverted in memory (chained).
|
|
2311
2344
|
* The on-disk file is NOT rewritten during load.
|
|
2312
|
-
* - saveBatchState() always writes
|
|
2313
|
-
* - Schema versions >
|
|
2345
|
+
* - saveBatchState() always writes v4.
|
|
2346
|
+
* - Schema versions > 4 are rejected with STATE_SCHEMA_INVALID.
|
|
2314
2347
|
*/
|
|
2315
|
-
export const BATCH_STATE_SCHEMA_VERSION =
|
|
2348
|
+
export const BATCH_STATE_SCHEMA_VERSION = 4;
|
|
2316
2349
|
|
|
2317
2350
|
/**
|
|
2318
2351
|
* Canonical file path for persisted batch state.
|
|
@@ -2431,6 +2464,99 @@ export interface PersistedTaskRecord {
|
|
|
2431
2464
|
* falling back to `exitReason` for display.
|
|
2432
2465
|
*/
|
|
2433
2466
|
exitDiagnostic?: TaskExitDiagnostic;
|
|
2467
|
+
/**
|
|
2468
|
+
* Repo ID that owns task packet files (PROMPT.md/STATUS.md/.DONE) (v4, TP-081).
|
|
2469
|
+
*
|
|
2470
|
+
* In workspace mode, this is the `taskPacketRepo` from routing config.
|
|
2471
|
+
* Undefined in repo mode or for pre-v4 state files.
|
|
2472
|
+
*/
|
|
2473
|
+
packetRepoId?: string;
|
|
2474
|
+
/**
|
|
2475
|
+
* Absolute path to the task folder in the packet repo worktree (v4, TP-081).
|
|
2476
|
+
*
|
|
2477
|
+
* Used by resume to locate packet files without re-running discovery.
|
|
2478
|
+
* Undefined in repo mode or for pre-v4 state files.
|
|
2479
|
+
*/
|
|
2480
|
+
packetTaskPath?: string;
|
|
2481
|
+
/**
|
|
2482
|
+
* Segment IDs belonging to this task (v4, TP-081).
|
|
2483
|
+
*
|
|
2484
|
+
* Array of segment ID strings (`<taskId>::<repoId>`).
|
|
2485
|
+
* Empty array for repo-mode tasks or single-repo tasks.
|
|
2486
|
+
* Undefined for pre-v4 state files.
|
|
2487
|
+
*/
|
|
2488
|
+
segmentIds?: string[];
|
|
2489
|
+
/**
|
|
2490
|
+
* Currently executing segment ID (v4, TP-081).
|
|
2491
|
+
*
|
|
2492
|
+
* Null when no segment is active (all completed or not started).
|
|
2493
|
+
* Undefined for pre-v4 state files.
|
|
2494
|
+
*/
|
|
2495
|
+
activeSegmentId?: string | null;
|
|
2496
|
+
}
|
|
2497
|
+
|
|
2498
|
+
// ── Segment-Level Persisted State (v4, TP-081) ──────────────────────
|
|
2499
|
+
|
|
2500
|
+
/**
|
|
2501
|
+
* Segment execution status within a batch.
|
|
2502
|
+
*
|
|
2503
|
+
* State machine mirrors `LaneTaskStatus` but applies at segment granularity:
|
|
2504
|
+
* pending → running → succeeded
|
|
2505
|
+
* → failed
|
|
2506
|
+
* → stalled
|
|
2507
|
+
* pending → skipped (prior segment failed, or task skipped)
|
|
2508
|
+
*
|
|
2509
|
+
* @since v4 (TP-081)
|
|
2510
|
+
*/
|
|
2511
|
+
export type PersistedSegmentStatus = "pending" | "running" | "succeeded" | "failed" | "stalled" | "skipped";
|
|
2512
|
+
|
|
2513
|
+
/**
|
|
2514
|
+
* Persisted record of a single segment's execution state.
|
|
2515
|
+
*
|
|
2516
|
+
* A segment is a repo-scoped execution unit within a task. Each task
|
|
2517
|
+
* may have one or more segments (one per repo the task touches).
|
|
2518
|
+
*
|
|
2519
|
+
* Contains everything `/orch-resume` needs to reconstruct segment-level
|
|
2520
|
+
* progress without re-running discovery.
|
|
2521
|
+
*
|
|
2522
|
+
* @since v4 (TP-081)
|
|
2523
|
+
*/
|
|
2524
|
+
export interface PersistedSegmentRecord {
|
|
2525
|
+
/** Stable segment identifier (`<taskId>::<repoId>`, e.g., "TP-002::api") */
|
|
2526
|
+
segmentId: string;
|
|
2527
|
+
/** Parent task identifier */
|
|
2528
|
+
taskId: string;
|
|
2529
|
+
/** Repo ID this segment targets */
|
|
2530
|
+
repoId: string;
|
|
2531
|
+
/** Segment execution status */
|
|
2532
|
+
status: PersistedSegmentStatus;
|
|
2533
|
+
/** Lane ID the segment executed on (e.g., "lane-1"), empty if not yet assigned */
|
|
2534
|
+
laneId: string;
|
|
2535
|
+
/** TMUX session name used for this segment */
|
|
2536
|
+
sessionName: string;
|
|
2537
|
+
/** Absolute path to the worktree used for this segment */
|
|
2538
|
+
worktreePath: string;
|
|
2539
|
+
/** Git branch name checked out for this segment */
|
|
2540
|
+
branch: string;
|
|
2541
|
+
/** Epoch ms when segment execution started (null if not yet started) */
|
|
2542
|
+
startedAt: number | null;
|
|
2543
|
+
/** Epoch ms when segment execution ended (null if still pending/running) */
|
|
2544
|
+
endedAt: number | null;
|
|
2545
|
+
/** Number of retry attempts for this segment */
|
|
2546
|
+
retries: number;
|
|
2547
|
+
/**
|
|
2548
|
+
* Segment IDs this segment depends on (intra-task DAG edges).
|
|
2549
|
+
* Empty array for the first segment in a task or for tasks with no intra-task deps.
|
|
2550
|
+
*/
|
|
2551
|
+
dependsOnSegmentIds: string[];
|
|
2552
|
+
/**
|
|
2553
|
+
* Structured exit diagnostic for this segment.
|
|
2554
|
+
* Optional: absent for segments that haven't exited yet.
|
|
2555
|
+
* Uses the same `TaskExitDiagnostic` shape from diagnostics.ts.
|
|
2556
|
+
*/
|
|
2557
|
+
exitDiagnostic?: TaskExitDiagnostic;
|
|
2558
|
+
/** Human-readable exit reason (legacy compat, same as task-level) */
|
|
2559
|
+
exitReason: string;
|
|
2434
2560
|
}
|
|
2435
2561
|
|
|
2436
2562
|
/**
|
|
@@ -2545,9 +2671,17 @@ export interface PersistedRepoMergeOutcome {
|
|
|
2545
2671
|
* data alongside legacy `exitReason` string).
|
|
2546
2672
|
* - Both sections are required in v3. Migration from v1/v2 fills
|
|
2547
2673
|
* conservative defaults (see `defaultResilienceState()` / `defaultBatchDiagnostics()`).
|
|
2674
|
+
*
|
|
2675
|
+
* v4 additions (TP-081):
|
|
2676
|
+
* - `segments` array (required): per-segment execution records for multi-repo
|
|
2677
|
+
* task execution. Empty array in repo mode or for pre-v4 migration.
|
|
2678
|
+
* - Task records gain optional `packetRepoId`, `packetTaskPath`, `segmentIds`,
|
|
2679
|
+
* and `activeSegmentId` for segment-level tracking.
|
|
2680
|
+
* - Migration from v3 fills `segments` as `[]` and leaves task-level segment
|
|
2681
|
+
* fields as `undefined`.
|
|
2548
2682
|
*/
|
|
2549
2683
|
export interface PersistedBatchState {
|
|
2550
|
-
/** Schema version — must equal BATCH_STATE_SCHEMA_VERSION (currently
|
|
2684
|
+
/** Schema version — must equal BATCH_STATE_SCHEMA_VERSION (currently 4) */
|
|
2551
2685
|
schemaVersion: number;
|
|
2552
2686
|
/** Current batch execution phase */
|
|
2553
2687
|
phase: OrchBatchPhase;
|
|
@@ -2596,14 +2730,24 @@ export interface PersistedBatchState {
|
|
|
2596
2730
|
errors: string[];
|
|
2597
2731
|
/**
|
|
2598
2732
|
* Resilience state for retry/recovery tracking (v3, TP-030).
|
|
2599
|
-
* Required in v3
|
|
2733
|
+
* Required in v3+. Migration from v1/v2 fills conservative defaults.
|
|
2600
2734
|
*/
|
|
2601
2735
|
resilience: ResilienceState;
|
|
2602
2736
|
/**
|
|
2603
2737
|
* Batch-level diagnostics for cost tracking and exit summaries (v3, TP-030).
|
|
2604
|
-
* Required in v3
|
|
2738
|
+
* Required in v3+. Migration from v1/v2 fills conservative defaults.
|
|
2605
2739
|
*/
|
|
2606
2740
|
diagnostics: BatchDiagnostics;
|
|
2741
|
+
/**
|
|
2742
|
+
* Per-segment execution records for multi-repo task execution (v4, TP-081).
|
|
2743
|
+
*
|
|
2744
|
+
* Each entry represents one repo-scoped segment of a task. In repo mode
|
|
2745
|
+
* or for single-repo tasks, this array is empty (segment tracking is
|
|
2746
|
+
* implicit via task records).
|
|
2747
|
+
*
|
|
2748
|
+
* Required in v4. Migration from v1/v2/v3 fills empty array.
|
|
2749
|
+
*/
|
|
2750
|
+
segments: PersistedSegmentRecord[];
|
|
2607
2751
|
/**
|
|
2608
2752
|
* Unknown top-level fields captured during deserialization.
|
|
2609
2753
|
* Preserved on roundtrip to avoid data loss from future schema extensions
|
|
@@ -3213,3 +3357,97 @@ export function createRepoModeContext(
|
|
|
3213
3357
|
};
|
|
3214
3358
|
}
|
|
3215
3359
|
|
|
3360
|
+
|
|
3361
|
+
// ── Agent Mailbox Types (TP-089) ─────────────────────────────────────
|
|
3362
|
+
|
|
3363
|
+
/**
|
|
3364
|
+
* Mailbox directory name under .pi/.
|
|
3365
|
+
* @since TP-089
|
|
3366
|
+
*/
|
|
3367
|
+
export const MAILBOX_DIR_NAME = "mailbox";
|
|
3368
|
+
|
|
3369
|
+
/**
|
|
3370
|
+
* Maximum content size in UTF-8 bytes.
|
|
3371
|
+
* Steering messages should be concise directives; larger context should be
|
|
3372
|
+
* written to a separate file and referenced by path.
|
|
3373
|
+
* @since TP-089
|
|
3374
|
+
*/
|
|
3375
|
+
export const MAILBOX_MAX_CONTENT_BYTES = 4096;
|
|
3376
|
+
|
|
3377
|
+
/**
|
|
3378
|
+
* Message types for the agent mailbox system.
|
|
3379
|
+
*
|
|
3380
|
+
* | Type | Direction | Purpose |
|
|
3381
|
+
* |------------|---------------------|--------------------------------------------|
|
|
3382
|
+
* | `steer` | supervisor → agent | Course correction. Agent must follow. |
|
|
3383
|
+
* | `query` | supervisor → agent | Request for status/info. Agent replies. |
|
|
3384
|
+
* | `abort` | supervisor → agent | Graceful stop. Agent wraps up and exits. |
|
|
3385
|
+
* | `info` | supervisor → agent | FYI context. No action required. |
|
|
3386
|
+
* | `reply` | agent → supervisor | Response to query or steer acknowledgment. |
|
|
3387
|
+
* | `escalate` | agent → supervisor | Agent-initiated: blocked or needs guidance. |
|
|
3388
|
+
*
|
|
3389
|
+
* @since TP-089
|
|
3390
|
+
*/
|
|
3391
|
+
export type MailboxMessageType = "steer" | "query" | "abort" | "info" | "reply" | "escalate";
|
|
3392
|
+
|
|
3393
|
+
/**
|
|
3394
|
+
* Set of valid mailbox message types for runtime validation.
|
|
3395
|
+
* @since TP-089
|
|
3396
|
+
*/
|
|
3397
|
+
export const MAILBOX_MESSAGE_TYPES: ReadonlySet<string> = new Set<MailboxMessageType>([
|
|
3398
|
+
"steer", "query", "abort", "info", "reply", "escalate",
|
|
3399
|
+
]);
|
|
3400
|
+
|
|
3401
|
+
/**
|
|
3402
|
+
* Message format for the file-based agent mailbox.
|
|
3403
|
+
*
|
|
3404
|
+
* Messages are written as JSON files in batch-scoped, session-scoped
|
|
3405
|
+
* directories. The rpc-wrapper checks the inbox on every `message_end`
|
|
3406
|
+
* event and injects pending messages into the agent's LLM context via
|
|
3407
|
+
* pi's `steer` RPC command.
|
|
3408
|
+
*
|
|
3409
|
+
* @see docs/specifications/taskplane/agent-mailbox-steering.md
|
|
3410
|
+
* @since TP-089
|
|
3411
|
+
*/
|
|
3412
|
+
export interface MailboxMessage {
|
|
3413
|
+
/** Unique message ID: `{timestamp}-{5char-hex-nonce}` */
|
|
3414
|
+
id: string;
|
|
3415
|
+
/** Batch ID — must match current batch for validation */
|
|
3416
|
+
batchId: string;
|
|
3417
|
+
/** Sender identifier: `"supervisor"` or session name */
|
|
3418
|
+
from: string;
|
|
3419
|
+
/** Target session name or `"_broadcast"` */
|
|
3420
|
+
to: string;
|
|
3421
|
+
/** Epoch milliseconds (Date.now()) */
|
|
3422
|
+
timestamp: number;
|
|
3423
|
+
/** Message type */
|
|
3424
|
+
type: MailboxMessageType;
|
|
3425
|
+
/** Message body (max 4KB UTF-8 bytes) */
|
|
3426
|
+
content: string;
|
|
3427
|
+
/** Whether the sender expects a reply (default: false) */
|
|
3428
|
+
expectsReply?: boolean;
|
|
3429
|
+
/** Reference to a previous message ID for threading (default: null) */
|
|
3430
|
+
replyTo?: string | null;
|
|
3431
|
+
}
|
|
3432
|
+
|
|
3433
|
+
/**
|
|
3434
|
+
* Input options for writeMailboxMessage.
|
|
3435
|
+
*
|
|
3436
|
+
* The caller provides these fields; the utility generates `id`, `batchId`,
|
|
3437
|
+
* `to`, and `timestamp` from its own arguments.
|
|
3438
|
+
*
|
|
3439
|
+
* @since TP-089
|
|
3440
|
+
*/
|
|
3441
|
+
export interface WriteMailboxMessageOpts {
|
|
3442
|
+
/** Sender identifier: `"supervisor"` or session name */
|
|
3443
|
+
from: string;
|
|
3444
|
+
/** Message type */
|
|
3445
|
+
type: MailboxMessageType;
|
|
3446
|
+
/** Message body (max 4KB UTF-8 bytes) */
|
|
3447
|
+
content: string;
|
|
3448
|
+
/** Whether the sender expects a reply (default: false) */
|
|
3449
|
+
expectsReply?: boolean;
|
|
3450
|
+
/** Reference to a previous message ID for threading (default: null) */
|
|
3451
|
+
replyTo?: string | null;
|
|
3452
|
+
}
|
|
3453
|
+
|
|
@@ -27,10 +27,15 @@
|
|
|
27
27
|
* 6. Truncate to 512 chars (bound fingerprint size)
|
|
28
28
|
*
|
|
29
29
|
* **Fallback for non-JSON output:**
|
|
30
|
-
* If
|
|
31
|
-
* single fingerprint with kind: "command_error" and the first 512 chars
|
|
30
|
+
* If legacy Vitest JSON parsing fails (truncated, missing, non-JSON), produce
|
|
31
|
+
* a single fingerprint with kind: "command_error" and the first 512 chars
|
|
32
32
|
* of stderr (or stdout) as messageNorm.
|
|
33
33
|
*
|
|
34
|
+
* **Compatibility note:**
|
|
35
|
+
* Taskplane's default tests use Node.js native `node:test`. The Vitest parser
|
|
36
|
+
* in this module is retained only for backward compatibility when projects
|
|
37
|
+
* provide custom `testing.commands` that still emit Vitest JSON.
|
|
38
|
+
*
|
|
34
39
|
* @module orch/verification
|
|
35
40
|
*/
|
|
36
41
|
import { spawnSync } from "child_process";
|
|
@@ -300,20 +305,20 @@ function classifyFailureKind(message: string): TestFingerprint["kind"] {
|
|
|
300
305
|
}
|
|
301
306
|
|
|
302
307
|
/**
|
|
303
|
-
* Parse
|
|
308
|
+
* Parse legacy Vitest JSON reporter output into test fingerprints.
|
|
304
309
|
*
|
|
305
|
-
* Expects
|
|
310
|
+
* Expects stdout to contain a JSON object matching Vitest's JSON reporter format.
|
|
306
311
|
* Only failed tests produce fingerprints (passed tests are irrelevant for baseline diffing).
|
|
307
312
|
*
|
|
308
313
|
* If JSON parsing fails or the structure is unexpected, returns null to signal
|
|
309
314
|
* that the caller should use fallback fingerprinting.
|
|
310
315
|
*
|
|
311
316
|
* @param commandId - The command that produced this output
|
|
312
|
-
* @param stdout - Raw stdout from the
|
|
317
|
+
* @param stdout - Raw stdout from the Vitest command (legacy compatibility path)
|
|
313
318
|
* @returns Array of fingerprints for failed tests, or null if parsing fails
|
|
314
319
|
*/
|
|
315
320
|
export function parseVitestOutput(commandId: string, stdout: string): TestFingerprint[] | null {
|
|
316
|
-
// Try to extract JSON from stdout (
|
|
321
|
+
// Try to extract JSON from stdout (Vitest may prepend/append non-JSON lines)
|
|
317
322
|
let json: VitestJsonResult;
|
|
318
323
|
try {
|
|
319
324
|
// First attempt: parse the whole stdout as JSON
|
|
@@ -363,7 +368,7 @@ export function parseVitestOutput(commandId: string, stdout: string): TestFinger
|
|
|
363
368
|
}
|
|
364
369
|
|
|
365
370
|
// Suite-level failures: testResults[].status === "failed" with no assertion-level details.
|
|
366
|
-
// This covers setup/import/runtime-at-file-load errors where
|
|
371
|
+
// This covers setup/import/runtime-at-file-load errors where Vitest marks the file as
|
|
367
372
|
// failed but produces no assertionResults (or only non-failed ones).
|
|
368
373
|
if (testFile.status === "failed") {
|
|
369
374
|
const hasFailedAssertions = hasAssertions && assertions!.some(a => a.status === "failed");
|
|
@@ -388,7 +393,7 @@ export function parseVitestOutput(commandId: string, stdout: string): TestFinger
|
|
|
388
393
|
* Parse test output into normalized fingerprints.
|
|
389
394
|
*
|
|
390
395
|
* Strategy:
|
|
391
|
-
* 1. Try
|
|
396
|
+
* 1. Try legacy Vitest JSON adapter
|
|
392
397
|
* 2. If parsing fails: produce a fallback command_error fingerprint
|
|
393
398
|
*
|
|
394
399
|
* The adapter pattern is extensible — future parsers for jest, pytest, etc.
|
|
@@ -416,7 +421,7 @@ export function parseTestOutput(commandResult: CommandResult): TestFingerprint[]
|
|
|
416
421
|
return [];
|
|
417
422
|
}
|
|
418
423
|
|
|
419
|
-
// Try
|
|
424
|
+
// Try legacy Vitest JSON adapter
|
|
420
425
|
const vitestFingerprints = parseVitestOutput(commandId, stdout);
|
|
421
426
|
if (vitestFingerprints !== null && vitestFingerprints.length > 0) {
|
|
422
427
|
return vitestFingerprints;
|
package/package.json
CHANGED
|
@@ -68,7 +68,7 @@ Every action you take falls into one of three categories:
|
|
|
68
68
|
### Diagnostic (always allowed — no confirmation needed)
|
|
69
69
|
- Reading batch-state.json, STATUS.md, events.jsonl, merge results
|
|
70
70
|
- Running `git status`, `git log`, `git diff`
|
|
71
|
-
- Running test suites (`
|
|
71
|
+
- Running test suites (`node --experimental-strip-types --experimental-test-module-mocks --no-warnings --import ./tests/loader.mjs --test ...`, etc.)
|
|
72
72
|
- Listing tmux sessions (`tmux list-sessions`)
|
|
73
73
|
- Checking worktree health (`git worktree list`)
|
|
74
74
|
- Reading any file for diagnostics
|
|
@@ -201,8 +201,29 @@ a reviewer agent. The tool takes two parameters: `step` (number) and `type`
|
|
|
201
201
|
documentation/delivery). These are low-risk steps where review overhead exceeds
|
|
202
202
|
value.
|
|
203
203
|
|
|
204
|
+
### ⚠️ CRITICAL: Plan review happens BEFORE implementation
|
|
205
|
+
|
|
206
|
+
**The plan review MUST happen BEFORE you write any code for that step.**
|
|
207
|
+
The entire purpose of plan review is to catch design issues, missing cases, and
|
|
208
|
+
wrong approaches BEFORE you spend tokens implementing them. If you implement
|
|
209
|
+
first and then request plan review, the reviewer's feedback is wasted — the
|
|
210
|
+
code is already written.
|
|
211
|
+
|
|
212
|
+
**Correct sequence:**
|
|
213
|
+
1. Hydrate step checkboxes (expand the plan)
|
|
214
|
+
2. Commit the hydrated STATUS.md
|
|
215
|
+
3. **Call `review_step(step=N, type="plan")` — BEFORE writing any code**
|
|
216
|
+
4. Handle verdict (APPROVE → implement; REVISE → fix plan, re-review)
|
|
217
|
+
5. Implement the step (write code, check off items)
|
|
218
|
+
6. Commit implementation
|
|
219
|
+
7. Call `review_step(step=N, type="code")` — AFTER implementation
|
|
220
|
+
|
|
221
|
+
**WRONG sequence (violates the protocol):**
|
|
222
|
+
1. ~~Hydrate, implement, check off, commit, THEN call plan review~~ ❌
|
|
223
|
+
This makes plan review pointless — the work is already done.
|
|
224
|
+
|
|
204
225
|
**Handling verdicts:**
|
|
205
|
-
- **APPROVE** → proceed to next step
|
|
226
|
+
- **APPROVE** → proceed (to implementation after plan review; to next step after code review)
|
|
206
227
|
- **RETHINK** → reconsider your plan approach, adjust, then implement
|
|
207
228
|
- **REVISE** → read the review file in `.reviews/` for detailed feedback,
|
|
208
229
|
address the issues, commit fixes, then **call `review_step` again** for re-review.
|
|
@@ -211,14 +232,16 @@ value.
|
|
|
211
232
|
|
|
212
233
|
**Example flow for a Review Level 2 task, Step 3:**
|
|
213
234
|
1. Read Step 3 requirements
|
|
214
|
-
2.
|
|
215
|
-
3.
|
|
216
|
-
4.
|
|
217
|
-
5.
|
|
218
|
-
6.
|
|
219
|
-
7.
|
|
220
|
-
8.
|
|
221
|
-
9.
|
|
235
|
+
2. Hydrate Step 3 checkboxes, commit STATUS.md
|
|
236
|
+
3. Call `review_step(step=3, type="plan")` → get plan feedback (**NO CODE YET**)
|
|
237
|
+
4. If REVISE: adjust plan, re-request plan review
|
|
238
|
+
5. If APPROVE: capture baseline SHA (`git rev-parse HEAD`)
|
|
239
|
+
6. Implement Step 3 (write code, check off items)
|
|
240
|
+
7. Commit changes
|
|
241
|
+
8. Call `review_step(step=3, type="code", baseline="<saved SHA>")` → get code feedback
|
|
242
|
+
9. If REVISE: fix issues, commit, call `review_step(step=3, type="code")` again
|
|
243
|
+
10. Repeat 9 until APPROVE (max 2 code review cycles per step)
|
|
244
|
+
11. Move to Step 4
|
|
222
245
|
|
|
223
246
|
If the `review_step` tool is not available (e.g., non-orchestrated mode), skip
|
|
224
247
|
this protocol entirely — the task-runner handles reviews externally.
|
|
@@ -252,30 +275,24 @@ Run tests at two different scopes depending on where you are in the task:
|
|
|
252
275
|
|
|
253
276
|
### During implementation steps (targeted tests)
|
|
254
277
|
|
|
255
|
-
After implementing each step, run **targeted tests** for fast feedback
|
|
278
|
+
After implementing each step, run **targeted tests** for fast feedback.
|
|
279
|
+
Use file-targeted runs for the test files that cover your changes:
|
|
256
280
|
|
|
257
281
|
```bash
|
|
258
|
-
cd extensions &&
|
|
282
|
+
cd extensions && node --experimental-strip-types --experimental-test-module-mocks --no-warnings --import ./tests/loader.mjs --test tests/some-specific.test.ts
|
|
259
283
|
```
|
|
260
284
|
|
|
261
|
-
-
|
|
262
|
-
|
|
263
|
-
-
|
|
264
|
-
|
|
265
|
-
- Alternatively, run specific test files that cover the code you modified:
|
|
266
|
-
`npx vitest run tests/some-specific.test.ts`
|
|
267
|
-
- **If `--changed` returns no tests:** That's fine — it means your changes don't
|
|
268
|
-
have directly related test files. The full suite in the Testing step will catch
|
|
269
|
-
any indirect regressions.
|
|
270
|
-
- **If targeted tests fail:** Fix the failure before proceeding. Don't accumulate
|
|
271
|
-
failures across steps.
|
|
285
|
+
- Node's native runner does not provide a reliable project-level `--changed`
|
|
286
|
+
equivalent; select targeted files explicitly.
|
|
287
|
+
- If multiple files are relevant, pass multiple `--test` paths.
|
|
288
|
+
- **If targeted tests fail:** fix them before proceeding. Don't accumulate failures.
|
|
272
289
|
|
|
273
290
|
### During the Testing & Verification step (full suite)
|
|
274
291
|
|
|
275
292
|
Run the **full test suite** as a quality gate:
|
|
276
293
|
|
|
277
294
|
```bash
|
|
278
|
-
cd extensions &&
|
|
295
|
+
cd extensions && node --experimental-strip-types --experimental-test-module-mocks --no-warnings --import ./tests/loader.mjs --test tests/*.test.ts
|
|
279
296
|
```
|
|
280
297
|
|
|
281
298
|
- ALL tests must pass — zero failures allowed.
|