opencode-plugin-flow 7.3.1 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +37 -2
- package/README.md +2 -2
- package/dist/index.js +198 -314
- package/dist/index.js.map +12 -12
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -187,19 +187,16 @@ Save one plan with:
|
|
|
187
187
|
- \`overview\`: the implementation approach and important boundaries.
|
|
188
188
|
- \`requirements\`: acceptance criteria, constraints, and non-goals.
|
|
189
189
|
- \`decisions\`: assumptions and architecture or scope choices already made.
|
|
190
|
-
- \`
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
satisfies it: final review and completed closure stay refused until then. A skipped
|
|
201
|
-
case exits zero and satisfies nothing, and recording the gap as a \`requirements\`
|
|
202
|
-
non-goal declares nothing.
|
|
190
|
+
- \`evidence\`: one \`scope: "gate"\` entry for the canonical whole-repository
|
|
191
|
+
command, plus \`scope: "extra"\` entries for observations this host may lack.
|
|
192
|
+
Each entry names \`requirement\`, \`environment\`, \`command\`, \`platform\`
|
|
193
|
+
(\`win32\`, \`darwin\`, \`linux\`, or \`other\`), and \`assertions\` (empty when the
|
|
194
|
+
evidence is not a test result). Broad observations run the gate command
|
|
195
|
+
byte-for-byte. Extra entries may be omitted when the goal is fully observable
|
|
196
|
+
here. Final review and completed closure stay refused until every extra
|
|
197
|
+
entry is satisfied on its declared platform with named cases passing. The
|
|
198
|
+
gate is the command every broad observation must run; a failed or
|
|
199
|
+
claimed-broad gate still vetoes review.
|
|
203
200
|
- \`features\`: ordered outcome slices, each with a stable \`id\`, \`title\`,
|
|
204
201
|
\`summary\`, bounded \`targets\`, concrete \`validation\`, and \`dependsOn\` ids.
|
|
205
202
|
|
|
@@ -406,14 +403,14 @@ description: Implement, validate, independently review, and record one approved
|
|
|
406
403
|
|
|
407
404
|
Work on exactly one approved feature.
|
|
408
405
|
|
|
409
|
-
## Start
|
|
406
|
+
## Start
|
|
410
407
|
|
|
411
408
|
1. Call \`flow_status { request: { view: "compact" } }\` first. Treat
|
|
412
|
-
\`nextAction\` as the durable default
|
|
409
|
+
\`nextAction\` as the durable default, not as permission.
|
|
413
410
|
2. If the top-level response status is \`error\`, report its exact summary and
|
|
414
411
|
recovery when present and, if \`workflowData.delivery\` exists, the handoff
|
|
415
|
-
below.
|
|
416
|
-
|
|
412
|
+
below. This read made no lifecycle, Git, or release mutation. Stop. Do not
|
|
413
|
+
route its \`nextAction\`.
|
|
417
414
|
3. If compact status contains \`archiveRetry\`, call \`flow_session_close\` once
|
|
418
415
|
with the projected request byte-for-byte. Report delivery under the contract
|
|
419
416
|
below. Refresh only if publication is unconfirmed. Stop after this cleanup
|
|
@@ -421,9 +418,9 @@ Work on exactly one approved feature.
|
|
|
421
418
|
4. When the projection contains an active goal, align it with the current
|
|
422
419
|
\`/flow-run\` request before another manager lifecycle mutation. Continue only
|
|
423
420
|
for the same goal or a method/emphasis narrowing that preserves all outcomes;
|
|
424
|
-
close completed work. Unless step
|
|
425
|
-
mutation: report that it has not started and offer continue, defer,
|
|
426
|
-
abandon.
|
|
421
|
+
close completed work. Unless the next step applies, new or expanded work
|
|
422
|
+
makes no mutation: report that it has not started and offer continue, defer,
|
|
423
|
+
or abandon.
|
|
427
424
|
5. If the aligned request explicitly chooses deferred or abandoned closure for
|
|
428
425
|
a non-completed session, call \`flow_session_close\` with compact session id and
|
|
429
426
|
revision, fresh operation id, that kind, and optional summary. Report delivery
|
|
@@ -432,227 +429,113 @@ Work on exactly one approved feature.
|
|
|
432
429
|
explain that \`/flow-run\` requires an approved feature, and stop without
|
|
433
430
|
mutation.
|
|
434
431
|
|
|
435
|
-
|
|
432
|
+
Delivery handoff: report \`workflowData.delivery.report\` verbatim. Map IDs only
|
|
433
|
+
from delivery \`outcomeSummary\`/\`terminalFindings\`. Requirements are \`verified\`,
|
|
434
|
+
\`incomplete\`, or explicitly \`deferred\`, and \`abandoned\` remains the kind. If
|
|
435
|
+
delivery is absent, report exact recovery and no map. On revision conflict,
|
|
436
|
+
refresh compact; retry only for the same session and goal while status still
|
|
437
|
+
permits the selected closure kind; never close a replacement.
|
|
438
|
+
|
|
439
|
+
## Route
|
|
440
|
+
|
|
441
|
+
Follow compact \`nextAction\` in this order:
|
|
436
442
|
|
|
437
443
|
- \`flow_session_close\`: close completed work with its projected session
|
|
438
|
-
id/revision, fresh operation id, and \`kind: "completed"\`. Report delivery
|
|
439
|
-
|
|
440
|
-
New work may enter planning afterward; do not fabricate a run.
|
|
444
|
+
id/revision, fresh operation id, and \`kind: "completed"\`. Report delivery,
|
|
445
|
+
follow one exact \`archiveRetry\` if needed, and stop.
|
|
441
446
|
- \`await-user-direction\` or blocked \`flow_feature_reset\`: call
|
|
442
|
-
\`flow_status { request: { view: "detail" } }\` exactly once, then
|
|
443
|
-
|
|
444
|
-
- Ready \`await-user-direction\` has no blocked run left to reset. Identify the
|
|
445
|
-
planned feature whose latest relevant reviewed outcome remains failed and
|
|
446
|
-
checkpoint unless the current aligned request explicitly authorizes its
|
|
447
|
-
retry. When authorized, call \`flow_run_start\` with that exact \`featureId\`;
|
|
448
|
-
never call \`flow_feature_reset\` from ready status or rely on default
|
|
449
|
-
selection.
|
|
450
|
-
- For blocked status, apply **Blocked review** below. If it permits another
|
|
451
|
-
feature run, pass that exact choice as \`nextFeatureId\` to
|
|
452
|
-
\`flow_feature_reset\` so reset and run start are atomic, then route its
|
|
453
|
-
returned projection; otherwise report the checkpoint and stop.
|
|
447
|
+
\`flow_status { request: { view: "detail" } }\` exactly once, then apply
|
|
448
|
+
**Blocked review**.
|
|
454
449
|
- Running \`flow_feature_reset\`: the pending review is source-stale. Reset with
|
|
455
|
-
the same feature as \`nextFeatureId\` when continuing it
|
|
456
|
-
|
|
450
|
+
the same feature as \`nextFeatureId\` when continuing it. Never redispatch that
|
|
451
|
+
assignment.
|
|
457
452
|
- \`dispatch-flow-reviewer\`: read execution status. If that read errors, report
|
|
458
|
-
its exact summary and recovery when present and stop
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
\`flow_feature_reset\`, follow the source-stale reset route and never dispatch
|
|
463
|
-
that assignment. Skip run start, implementation, and validation.
|
|
453
|
+
its exact summary and recovery when present and stop. Otherwise route that
|
|
454
|
+
refreshed projection. Dispatch under **Review** only if \`nextAction\` is still
|
|
455
|
+
\`dispatch-flow-reviewer\`. If it is now running \`flow_feature_reset\`, follow
|
|
456
|
+
the source-stale reset route.
|
|
464
457
|
- \`flow_run_start\`: start the ready feature, refresh compact status, and read
|
|
465
458
|
execution status.
|
|
466
|
-
- \`flow_validation_start\`: read execution status and resume
|
|
467
|
-
|
|
468
|
-
- \`flow_review_start\`: read execution status and continue at **Review
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
feature summary, targets, validation, dependencies, requirements, and decisions.
|
|
475
|
-
If a projected action fails an environment-sensitive guard, refresh compact and
|
|
476
|
-
handle that rejection; never force it.
|
|
477
|
-
|
|
478
|
-
Summaries keep plan/source IDs \`verified\` or \`incomplete\`.
|
|
479
|
-
Delivery handoff: report \`workflowData.delivery.report\` verbatim. Map IDs only from
|
|
480
|
-
delivery \`outcomeSummary\`/\`terminalFindings\`; requirements are \`verified\`,
|
|
481
|
-
\`incomplete\`, or explicitly \`deferred\`, and \`abandoned\` remains the kind.
|
|
482
|
-
If delivery is absent, report exact recovery and no map; never invent or read
|
|
483
|
-
detail solely for closure. On revision conflict, refresh compact; retry only for
|
|
484
|
-
the same session and goal while status still permits the selected closure kind;
|
|
485
|
-
never close a replacement.
|
|
486
|
-
|
|
487
|
-
Preserve unrelated work and stay inside the feature. Out-of-plan work stops;
|
|
488
|
-
finish or obtain explicit deferred/abandoned closure before a new plan. Never
|
|
489
|
-
replan in place. Use \`flow_feature_reset\` for a wrong design or assumption; do
|
|
490
|
-
not layer retries.
|
|
491
|
-
|
|
492
|
-
## Evidence and risk preflight
|
|
493
|
-
|
|
494
|
-
Before editing or dispatching a worker, perform one preflight from the approved
|
|
495
|
-
feature and current worktree:
|
|
496
|
-
|
|
497
|
-
- Preserve every named finding/requirement; map each to an observable acceptance
|
|
498
|
-
outcome.
|
|
499
|
-
- Inventory each \`externalEvidence\` command, its platform, and where it writes a
|
|
500
|
-
JUnit report: arm it with \`resultsPath\` naming that file, or its declared cases go
|
|
501
|
-
unobserved and the entry stays open on exit zero.
|
|
502
|
-
- Reuse one conversational run baseline of unrelated work, deletions, renames,
|
|
503
|
-
file types, and executable modes. Refresh changed facts; give each review only
|
|
504
|
-
facts the feature changes or depends on, and give final review the full
|
|
505
|
-
inventory.
|
|
506
|
-
- Write one concise adversarial checklist covering failure and cleanup ordering,
|
|
507
|
-
adjacent states, repetition, retry, interruption, concurrency, overlapping
|
|
508
|
-
invariants, and relevant platform or persistence risks. For concurrency or
|
|
509
|
-
state-machine work, express it as a compact matrix with \`state/interleaving\`,
|
|
510
|
-
\`event\`, \`expected outcome\`, \`cleanup/invariant\`, and \`evidence\` columns.
|
|
511
|
-
|
|
512
|
-
Carry the checklist/IDs through workers and review. Evidence needing user or
|
|
513
|
-
external authority stops before implementation.
|
|
459
|
+
- \`flow_validation_start\`: read execution status and resume from the current
|
|
460
|
+
worktree.
|
|
461
|
+
- \`flow_review_start\`: read execution status and continue at **Review**.
|
|
462
|
+
- Any other action: report it and stop.
|
|
463
|
+
|
|
464
|
+
Use execution status for active scope and revision. Stay inside the feature.
|
|
465
|
+
Out-of-plan work stops. Use \`flow_feature_reset\` for a wrong design; do not
|
|
466
|
+
layer retries.
|
|
514
467
|
|
|
515
468
|
## Implement
|
|
516
469
|
|
|
517
|
-
Make the smallest change
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
requires an explicit request.
|
|
470
|
+
Make the smallest change that satisfies the approved outcome. Create no
|
|
471
|
+
lifecycle or handoff sidecars. Do not stage, commit, push, publish, or mutate
|
|
472
|
+
releases unless asked separately.
|
|
521
473
|
|
|
522
|
-
|
|
474
|
+
Work serially. After a feature run is active, dispatch \`flow-worker\` only for
|
|
475
|
+
two or three genuinely independent slices with clear benefit. Workers call no
|
|
476
|
+
Flow tools, spawn no children, and run no Bash. Integrate and inspect the
|
|
477
|
+
combined diff before validation.
|
|
523
478
|
|
|
524
|
-
##
|
|
479
|
+
## Validate
|
|
525
480
|
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
host runs concurrent tasks, otherwise sequentially; report serial either way. Each
|
|
530
|
-
assignment names a stable id, exact outcome/read-write scope, coverage, manager
|
|
531
|
-
checks, dependencies, stop condition, and preflight risk checklist. The worker
|
|
532
|
-
must receive the checklist before it codes. Shared contracts, lockfiles, and generated
|
|
533
|
-
output stay manager-owned unless wholly assigned to one worker.
|
|
481
|
+
Arm each evidence Bash command with \`flow_validation_start\` (current revision,
|
|
482
|
+
feature id, exact command, \`scope\`) immediately before running it byte-for-byte.
|
|
483
|
+
Flow records the host observation; copy no host-observed fields.
|
|
534
484
|
|
|
535
|
-
|
|
536
|
-
status, scope/coverage, evidence/changed paths, manager checks, gaps/risks, and
|
|
537
|
-
integration notes; missing or blocked output is a coverage gap.
|
|
485
|
+
\`scope: "broad"\` runs the plan's gate evidence command and nothing else.
|
|
538
486
|
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
coordination ledger/sidecar. After interruption, inspect status/worktree and
|
|
543
|
-
treat partial worker edits as untrusted.
|
|
487
|
+
A failed, incomplete, or source-drifted observation of a plan-listed command or
|
|
488
|
+
of the declared gate command blocks review until that same command passes for
|
|
489
|
+
current source.
|
|
544
490
|
|
|
545
|
-
|
|
491
|
+
Every host-observed validation advances revision. The \`[flow-validation]\`
|
|
492
|
+
marker reports \`passed\`, \`recordedRevision\`, and declared \`assertions\`. Use
|
|
493
|
+
\`recordedRevision\` for the next \`flow_validation_start\`, or for
|
|
494
|
+
\`flow_review_start\` only when \`passed: true\`. If the marker is absent, refresh
|
|
495
|
+
compact status before mutating.
|
|
546
496
|
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
sufficient alone only for genuinely mechanical or documentation-only work.
|
|
555
|
-
- UI claims need visual inspection when a runnable target is available.
|
|
556
|
-
- Cleanup claims need behavior-preservation evidence, not formatting alone.
|
|
557
|
-
- \`scope: "broad"\` runs the plan's declared \`gate\` and nothing else; the runtime
|
|
558
|
-
refuses any other command at that scope.
|
|
559
|
-
|
|
560
|
-
Immediately before each evidence Bash command, call \`flow_validation_start\`
|
|
561
|
-
with current revision, feature id, exact command, and \`scope\` (\`focused\` or
|
|
562
|
-
\`broad\`). Run it byte-for-byte next and inspect the complete outcome. Flow
|
|
563
|
-
records the host observation; copy no host-observed fields into a later request.
|
|
564
|
-
The command is durable, so include no secrets.
|
|
565
|
-
|
|
566
|
-
A failed, incomplete, or source-drifted observation of a plan-listed command or of
|
|
567
|
-
the declared \`gate\` blocks review until that same command passes for current
|
|
568
|
-
source. No substitute discharges it; reverting the source revives nothing.
|
|
569
|
-
|
|
570
|
-
A gate or \`externalEvidence\` command that cannot pass withholds completed closure,
|
|
571
|
-
and reporting the blocker is half the move. Reach the passing command, or ask the
|
|
572
|
-
user to choose deferred or abandoned closure. Ending the turn having done neither
|
|
573
|
-
leaves the workflow with no next step, whatever the blocker was.
|
|
574
|
-
|
|
575
|
-
Every host-observed validation advances the session revision, so the revision
|
|
576
|
-
that armed a completed command is stale. The \`[flow-validation]\` marker reports
|
|
577
|
-
\`passed\`, \`recordedRevision\`, and any declared \`assertions\` with what the report
|
|
578
|
-
said about each. Use \`recordedRevision\` for the next
|
|
579
|
-
\`flow_validation_start\`, or for \`flow_review_start\` only when \`passed: true\`. If
|
|
580
|
-
the marker is absent or malformed, refresh compact status before mutating.
|
|
581
|
-
|
|
582
|
-
Use focused validation for ordinary features. For the final feature, run the
|
|
583
|
-
plan's declared \`gate\` at broad scope after the last relevant edit. A source edit
|
|
584
|
-
invalidates earlier applicability. Failed or unavailable checks are blockers, not
|
|
585
|
-
passing evidence.
|
|
586
|
-
|
|
587
|
-
Immediately before review admission, reconcile the preflight inventory against the
|
|
588
|
-
recorded current-source observations.
|
|
589
|
-
|
|
590
|
-
## Review and record
|
|
497
|
+
For the final feature, run the plan's gate command at broad scope after the
|
|
498
|
+
last relevant edit.
|
|
499
|
+
|
|
500
|
+
An evidence command that cannot pass withholds completed closure. Reach the
|
|
501
|
+
passing command, or ask the user to choose deferred or abandoned closure.
|
|
502
|
+
|
|
503
|
+
## Review
|
|
591
504
|
|
|
592
505
|
After successful applicable validation, call \`flow_review_start\` with a fresh
|
|
593
|
-
operation id, current revision, feature id, \`artifactsChanged
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
Keep the packet bounded. Map IDs to current-source commands or scenarios,
|
|
598
|
-
environment, and results. Put the feature-specific risk checklist under
|
|
599
|
-
\`Risks/Matrix:\`, representing it as a transition matrix for concurrency or
|
|
600
|
-
state-machine work. Include \`Baseline:\` facts only when this feature changes or
|
|
601
|
-
depends on them, except that final review receives the full inventory.
|
|
602
|
-
Ordinary-review plan/source IDs are limited to active-feature mappings or IDs
|
|
603
|
-
explicitly supplied for its packet; final review includes every approved
|
|
604
|
-
requirement/feature ID. Omit empty optional sections; state \`none\` only for a relevant
|
|
605
|
-
inspected absence. Never hide a gap.
|
|
606
|
-
|
|
607
|
-
Dispatch only to reserved \`flow-reviewer\`; never review, copy, or submit its
|
|
608
|
-
verdict in manager context. It reads the assignment/workspace and calls
|
|
609
|
-
\`flow_feature_complete\` directly; runtime verifies the caller. It stays
|
|
610
|
-
workspace-read-only, with that result submission as its sole lifecycle mutation.
|
|
506
|
+
operation id, current revision, feature id, \`artifactsChanged\`, and a bounded
|
|
507
|
+
packet. Dispatch only reserved \`flow-reviewer\`. Never review or submit its
|
|
508
|
+
verdict in manager context.
|
|
611
509
|
|
|
612
510
|
After dispatch, read compact status. On top-level error, report exact
|
|
613
|
-
summary/recovery
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
\`dispatch-flow-reviewer\` or running \`flow_feature_reset\` route above. If status
|
|
618
|
-
is blocked, load detail through the single blocked route above. A recorded pass
|
|
619
|
-
completes the feature.
|
|
511
|
+
summary/recovery and stop without further mutation. If status remains running,
|
|
512
|
+
apply the \`dispatch-flow-reviewer\` or running \`flow_feature_reset\` route. If
|
|
513
|
+
status is blocked, apply **Blocked review**. A recorded pass completes the
|
|
514
|
+
feature.
|
|
620
515
|
|
|
621
516
|
### Blocked review
|
|
622
517
|
|
|
623
518
|
Follow \`nextAction\` with the one detail projection. The runtime already weighs
|
|
624
519
|
\`failedReviewCount\` and \`blockedFeature.scopeBlocker\`.
|
|
625
520
|
|
|
626
|
-
- \`await-user-direction\`
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
521
|
+
- Ready \`await-user-direction\` has no blocked run left to reset. Identify the
|
|
522
|
+
planned feature whose latest relevant reviewed outcome remains failed and
|
|
523
|
+
checkpoint unless the current aligned request explicitly authorizes its
|
|
524
|
+
retry. When authorized, call \`flow_run_start\` with that exact \`featureId\`.
|
|
525
|
+
Never call \`flow_feature_reset\` from ready status.
|
|
526
|
+
- For blocked \`await-user-direction\`, checkpoint. Do not reset.
|
|
527
|
+
- For blocked \`flow_feature_reset\`, one automatic reset is allowed under
|
|
528
|
+
existing implementation authority. Pass the blocked \`featureId\` as
|
|
529
|
+
\`nextFeatureId\` so reset and run start are atomic. Fix only its blocking
|
|
630
530
|
findings, then run full validation and full independent review.
|
|
631
|
-
- A feature whose latest relevant reviewed outcome remains failed is never
|
|
632
|
-
selected implicitly. \`/flow-auto\` may still continue an untouched,
|
|
633
|
-
dependency-independent feature. When every runnable candidate requires a
|
|
634
|
-
retry, compact status is \`ready\` with \`await-user-direction\`, handled by the
|
|
635
|
-
ready route above.
|
|
636
531
|
- When \`failedReviewCount >= 2\`, retry only when the current aligned request
|
|
637
|
-
explicitly authorizes one additional attempt.
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
call \`flow_run_start\` separately, or rely on default selection.
|
|
645
|
-
|
|
646
|
-
When stopping blocked, label overall incomplete. Report the latest repair proved
|
|
647
|
-
pending a passing review; recurring and new blockers; goal/progress; blocked
|
|
648
|
-
feature, attempt, and failure count; completed/untouched features; latest
|
|
649
|
-
validations and \`artifactsChanged\` as Flow-reported artifact evidence; Git/release
|
|
650
|
-
mutation status; whether this request started and matched the goal; exact
|
|
651
|
-
\`nextAction\`; and whether another attempt requires explicit authorization.
|
|
652
|
-
|
|
653
|
-
Use that already-loaded compact status after every recorded outcome. Direct
|
|
654
|
-
\`/flow-run\` reports this one feature's cumulative outcome and \`nextAction\`, then
|
|
655
|
-
stops. Under \`/flow-auto\`, return to its lifecycle loop.
|
|
532
|
+
explicitly authorizes one additional attempt.
|
|
533
|
+
- If explicit direction selects another planned, dependency-independent
|
|
534
|
+
feature, pass that exact \`featureId\` as \`nextFeatureId\` on
|
|
535
|
+
\`flow_feature_reset\`.
|
|
536
|
+
|
|
537
|
+
Direct \`/flow-run\` reports this one feature's cumulative outcome and
|
|
538
|
+
\`nextAction\`, then stops. Under \`/flow-auto\`, return to its lifecycle loop.
|
|
656
539
|
`;
|
|
657
540
|
|
|
658
541
|
// src/guidance/ids.ts
|
|
@@ -725,9 +608,8 @@ var FLOW_WORKER_PROMPT = [
|
|
|
725
608
|
"- Never edit .flow or .git metadata paths; the host denies those paths.",
|
|
726
609
|
"- A read-only evidence slice must not edit files.",
|
|
727
610
|
[
|
|
728
|
-
"-
|
|
729
|
-
"
|
|
730
|
-
"If it is missing, stop without editing and report the gap."
|
|
611
|
+
"- If the assignment includes a risk checklist or matrix, apply it before coding.",
|
|
612
|
+
"If required work would escape the assigned paths, stop and report the gap."
|
|
731
613
|
].join(" "),
|
|
732
614
|
[
|
|
733
615
|
"- An implementation slice may edit only the exact, non-overlapping write paths explicitly assigned by the manager.",
|
|
@@ -738,13 +620,7 @@ var FLOW_WORKER_PROMPT = [
|
|
|
738
620
|
"- The manager owns integration, focused checks, and authoritative combined validation",
|
|
739
621
|
"after all workers have stopped."
|
|
740
622
|
].join(" "),
|
|
741
|
-
|
|
742
|
-
"Before editing, apply the supplied risk coverage through its matrix rows when present:",
|
|
743
|
-
"primary behavior, failure and cleanup ordering, adjacent state transitions,",
|
|
744
|
-
"repeated or interrupted operation, overlapping invariants, and relevant persistence,",
|
|
745
|
-
"concurrency, security, compatibility, or file-metadata risks.",
|
|
746
|
-
"Preserve every named finding, requirement, or prior review ID in your handoff."
|
|
747
|
-
].join(" "),
|
|
623
|
+
"- Preserve every named finding, requirement, or prior review ID in your handoff.",
|
|
748
624
|
"## Handoff",
|
|
749
625
|
[
|
|
750
626
|
"Return exactly one concise handoff with `Status` (success, partial, or blocked),",
|
|
@@ -1089,6 +965,51 @@ function isFeatureId(value) {
|
|
|
1089
965
|
return FEATURE_ID_PATTERN.test(value);
|
|
1090
966
|
}
|
|
1091
967
|
|
|
968
|
+
// src/domain/session.ts
|
|
969
|
+
function planEvidence(plan) {
|
|
970
|
+
return plan?.evidence ?? [];
|
|
971
|
+
}
|
|
972
|
+
function planGate(plan) {
|
|
973
|
+
return planEvidence(plan).find((entry) => entry.scope === "gate")?.command;
|
|
974
|
+
}
|
|
975
|
+
function reviewResultSemanticIssues(result) {
|
|
976
|
+
const issues = [];
|
|
977
|
+
const blocking = result.findings.some((finding) => finding.severity === "blocking");
|
|
978
|
+
for (const [index, finding] of result.findings.entries()) {
|
|
979
|
+
if (finding.severity === "blocking" && !finding.evidence?.trim()) {
|
|
980
|
+
issues.push({
|
|
981
|
+
path: ["findings", index, "evidence"],
|
|
982
|
+
message: "A blocking finding requires concrete evidence."
|
|
983
|
+
});
|
|
984
|
+
}
|
|
985
|
+
if (finding.scopeBlocker && finding.severity !== "blocking") {
|
|
986
|
+
issues.push({
|
|
987
|
+
path: ["findings", index, "scopeBlocker"],
|
|
988
|
+
message: "Only a blocking finding can be a scope blocker."
|
|
989
|
+
});
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
if (result.verdict === "failed" && !blocking) {
|
|
993
|
+
issues.push({
|
|
994
|
+
path: ["findings"],
|
|
995
|
+
message: "A failed review requires a blocking finding."
|
|
996
|
+
});
|
|
997
|
+
}
|
|
998
|
+
if (result.verdict === "passed" && blocking) {
|
|
999
|
+
issues.push({
|
|
1000
|
+
path: ["findings"],
|
|
1001
|
+
message: "A passed review cannot contain blocking findings."
|
|
1002
|
+
});
|
|
1003
|
+
}
|
|
1004
|
+
if (result.terminalDisposition === "observed_unsubmitted" && result.verdict !== "failed") {
|
|
1005
|
+
issues.push({
|
|
1006
|
+
path: ["terminalDisposition"],
|
|
1007
|
+
message: "Observed-but-unsubmitted review work must fail closed."
|
|
1008
|
+
});
|
|
1009
|
+
}
|
|
1010
|
+
return issues;
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1092
1013
|
// src/domain/test-results.ts
|
|
1093
1014
|
var TESTCASE = /<testcase\b([^>]*?)(\/>|>([\s\S]*?)<\/testcase\s*>)/g;
|
|
1094
1015
|
var ATTRIBUTE = /([\w:.-]+)\s*=\s*"([^"]*)"/g;
|
|
@@ -1202,7 +1123,7 @@ function narrowingArguments(command) {
|
|
|
1202
1123
|
}
|
|
1203
1124
|
function declaredAssertions(session, command) {
|
|
1204
1125
|
return [
|
|
1205
|
-
...new Set((session.plan
|
|
1126
|
+
...new Set(planEvidence(session.plan).filter((entry) => entry.command === command).flatMap((entry) => entry.assertions ?? []))
|
|
1206
1127
|
];
|
|
1207
1128
|
}
|
|
1208
1129
|
function sameAssertions(left, right) {
|
|
@@ -1241,7 +1162,7 @@ function recordValidation(session, input) {
|
|
|
1241
1162
|
if (narrowing.length > 0) {
|
|
1242
1163
|
throw new FlowTransitionError(`A broad observation cannot select which tests it runs (${narrowing.join(", ")}). Arm the repository's canonical gate, or record this command as focused.`);
|
|
1243
1164
|
}
|
|
1244
|
-
const gate = session.plan
|
|
1165
|
+
const gate = planGate(session.plan);
|
|
1245
1166
|
if (gate !== undefined && input.command !== gate) {
|
|
1246
1167
|
throw new FlowTransitionError(`A broad observation must run the plan-declared canonical gate (${gate}). Arm that exact command, or record this one as focused.`);
|
|
1247
1168
|
}
|
|
@@ -1282,7 +1203,7 @@ function isObservedOnDeclaredPlatform(entry, observation) {
|
|
|
1282
1203
|
return true;
|
|
1283
1204
|
return observation.hostPlatform === entry.platform;
|
|
1284
1205
|
}
|
|
1285
|
-
function
|
|
1206
|
+
function evidenceRefusal(session, entry, sourceDigest) {
|
|
1286
1207
|
const eligible = session.runs.flatMap((run) => run.validations).filter((observation) => observation.command === entry.command && isValidationEligible(observation, sourceDigest));
|
|
1287
1208
|
const wrongHosts = [
|
|
1288
1209
|
...new Set(eligible.filter((observation) => !isObservedOnDeclaredPlatform(entry, observation)).map((observation) => observation.hostPlatform ?? "an unrecorded host"))
|
|
@@ -1292,18 +1213,21 @@ function externalEvidenceRefusal(session, entry, sourceDigest) {
|
|
|
1292
1213
|
const detail = wrongHosts.length > 0 ? `passed on ${wrongHosts.join(", ")} but this entry declares ${entry.platform}, so that run observed something else — a skipped case exits zero too` : unmet ? `passed on ${entry.platform ?? "the declared host"} but reported no passing result for ${unmet.join(", ")}; arm it again with \`resultsPath\` naming the report the command writes, and make those cases run` : `needs ${needs}`;
|
|
1293
1214
|
return `${JSON.stringify(entry.command)} (${detail}, for ${entry.requirement})`;
|
|
1294
1215
|
}
|
|
1295
|
-
function
|
|
1296
|
-
const declared = session.plan
|
|
1216
|
+
function unsatisfiedEvidence(session, sourceDigest) {
|
|
1217
|
+
const declared = planEvidence(session.plan);
|
|
1297
1218
|
if (declared.length === 0)
|
|
1298
1219
|
return [];
|
|
1299
1220
|
const observed = session.runs.flatMap((run) => run.validations);
|
|
1300
1221
|
return declared.filter((entry) => !observed.some((observation) => observation.command === entry.command && isObservedOnDeclaredPlatform(entry, observation) && assertionsSatisfied(entry.assertions ?? [], observation.observedAssertions) && isValidationEligible(observation, sourceDigest)));
|
|
1301
1222
|
}
|
|
1223
|
+
function unsatisfiedExtraEvidence(session, sourceDigest) {
|
|
1224
|
+
return unsatisfiedEvidence(session, sourceDigest).filter((entry) => entry.scope === "extra");
|
|
1225
|
+
}
|
|
1302
1226
|
function isValidationFresh(session, run, observation) {
|
|
1303
1227
|
return session.runs.filter((candidate) => candidate.featureId === run.featureId).flatMap((candidate) => candidate.validations).every((candidate) => candidate.command !== observation.command || isValidationEligible(candidate) || candidate.recordedRevision < observation.recordedRevision);
|
|
1304
1228
|
}
|
|
1305
1229
|
function unresolvedVetoedCommands(session, run, sourceDigest) {
|
|
1306
|
-
const gate = session.plan
|
|
1230
|
+
const gate = planGate(session.plan);
|
|
1307
1231
|
const planned = session.approval === "approved" ? [
|
|
1308
1232
|
...session.plan?.features.find((candidate) => candidate.id === run.featureId)?.validation ?? [],
|
|
1309
1233
|
...gate === undefined ? [] : [gate]
|
|
@@ -1321,8 +1245,9 @@ function gateIssue(gate) {
|
|
|
1321
1245
|
return narrowing.length === 0 ? null : `The plan's canonical gate cannot select which tests it runs (${narrowing.join(", ")}).`;
|
|
1322
1246
|
}
|
|
1323
1247
|
function planIssue(plan) {
|
|
1324
|
-
|
|
1325
|
-
|
|
1248
|
+
const gate = planGate(plan);
|
|
1249
|
+
if (gate !== undefined) {
|
|
1250
|
+
const issue = gateIssue(gate);
|
|
1326
1251
|
if (issue)
|
|
1327
1252
|
return issue;
|
|
1328
1253
|
}
|
|
@@ -1436,45 +1361,6 @@ function droppedFindingIds(session, featureId, findings) {
|
|
|
1436
1361
|
return liveFindingIds(session, featureId).filter((id) => !submitted.has(id));
|
|
1437
1362
|
}
|
|
1438
1363
|
|
|
1439
|
-
// src/domain/session.ts
|
|
1440
|
-
function reviewResultSemanticIssues(result) {
|
|
1441
|
-
const issues = [];
|
|
1442
|
-
const blocking = result.findings.some((finding) => finding.severity === "blocking");
|
|
1443
|
-
for (const [index, finding] of result.findings.entries()) {
|
|
1444
|
-
if (finding.severity === "blocking" && !finding.evidence?.trim()) {
|
|
1445
|
-
issues.push({
|
|
1446
|
-
path: ["findings", index, "evidence"],
|
|
1447
|
-
message: "A blocking finding requires concrete evidence."
|
|
1448
|
-
});
|
|
1449
|
-
}
|
|
1450
|
-
if (finding.scopeBlocker && finding.severity !== "blocking") {
|
|
1451
|
-
issues.push({
|
|
1452
|
-
path: ["findings", index, "scopeBlocker"],
|
|
1453
|
-
message: "Only a blocking finding can be a scope blocker."
|
|
1454
|
-
});
|
|
1455
|
-
}
|
|
1456
|
-
}
|
|
1457
|
-
if (result.verdict === "failed" && !blocking) {
|
|
1458
|
-
issues.push({
|
|
1459
|
-
path: ["findings"],
|
|
1460
|
-
message: "A failed review requires a blocking finding."
|
|
1461
|
-
});
|
|
1462
|
-
}
|
|
1463
|
-
if (result.verdict === "passed" && blocking) {
|
|
1464
|
-
issues.push({
|
|
1465
|
-
path: ["findings"],
|
|
1466
|
-
message: "A passed review cannot contain blocking findings."
|
|
1467
|
-
});
|
|
1468
|
-
}
|
|
1469
|
-
if (result.terminalDisposition === "observed_unsubmitted" && result.verdict !== "failed") {
|
|
1470
|
-
issues.push({
|
|
1471
|
-
path: ["terminalDisposition"],
|
|
1472
|
-
message: "Observed-but-unsubmitted review work must fail closed."
|
|
1473
|
-
});
|
|
1474
|
-
}
|
|
1475
|
-
return issues;
|
|
1476
|
-
}
|
|
1477
|
-
|
|
1478
1364
|
// src/domain/transitions.ts
|
|
1479
1365
|
function fail(message) {
|
|
1480
1366
|
throw new FlowTransitionError(message);
|
|
@@ -1530,20 +1416,19 @@ function assertPlan(plan) {
|
|
|
1530
1416
|
if (issue)
|
|
1531
1417
|
fail(issue);
|
|
1532
1418
|
}
|
|
1533
|
-
function
|
|
1534
|
-
if (plan.
|
|
1535
|
-
fail(
|
|
1419
|
+
function assertDeclaredEvidence(plan) {
|
|
1420
|
+
if (plan.evidence === undefined) {
|
|
1421
|
+
fail('A saved plan must declare `evidence`: one `scope: "gate"` command that validates the whole repository, plus every extra observation this host may be unable to produce. Extra entries may be an empty list when the goal is fully observable here.');
|
|
1536
1422
|
}
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
fail("A saved plan must declare `externalEvidence`: every acceptance observation needing an environment this host may not be, each with the exact command whose passing is that observation. Declare an empty list when the goal is fully observable here.");
|
|
1423
|
+
const gates = planEvidence(plan).filter((entry) => entry.scope === "gate");
|
|
1424
|
+
if (gates.length !== 1) {
|
|
1425
|
+
fail('A saved plan must declare exactly one `evidence` entry with `scope: "gate"`: the exact canonical command every broad observation then has to run.');
|
|
1541
1426
|
}
|
|
1542
|
-
if (plan.
|
|
1543
|
-
fail("Every `
|
|
1427
|
+
if (plan.evidence.some((entry) => entry.platform === undefined)) {
|
|
1428
|
+
fail("Every `evidence` entry must declare `platform`: the operating system that can observe it (`win32`, `darwin`, or `linux`), or `other` when the missing environment is a service, credential, setting, or device rather than an OS.");
|
|
1544
1429
|
}
|
|
1545
|
-
if (plan.
|
|
1546
|
-
fail("Every `
|
|
1430
|
+
if (plan.evidence.some((entry) => entry.assertions === undefined)) {
|
|
1431
|
+
fail("Every `evidence` entry must declare `assertions`: the test case names whose passing is that observation. Declare an empty list when the evidence is not a test result.");
|
|
1547
1432
|
}
|
|
1548
1433
|
}
|
|
1549
1434
|
function assertArtifacts(artifacts) {
|
|
@@ -1578,8 +1463,7 @@ function sessionStatus(session) {
|
|
|
1578
1463
|
function savePlan(session, input, environment) {
|
|
1579
1464
|
assertPlan(input.plan);
|
|
1580
1465
|
if (!session) {
|
|
1581
|
-
|
|
1582
|
-
assertDeclaredExternalEvidence(input.plan);
|
|
1466
|
+
assertDeclaredEvidence(input.plan);
|
|
1583
1467
|
if (input.expectedRevision !== 0) {
|
|
1584
1468
|
fail("A new Flow session must start from expectedRevision 0.");
|
|
1585
1469
|
}
|
|
@@ -1609,8 +1493,7 @@ function savePlan(session, input, environment) {
|
|
|
1609
1493
|
const replay = existingOperation(session, "plan-save", input.operationId, input);
|
|
1610
1494
|
if (replay)
|
|
1611
1495
|
return { session, value: null, replayed: true };
|
|
1612
|
-
|
|
1613
|
-
assertDeclaredExternalEvidence(input.plan);
|
|
1496
|
+
assertDeclaredEvidence(input.plan);
|
|
1614
1497
|
assertRevision(session, input.expectedRevision);
|
|
1615
1498
|
assertMutable(session);
|
|
1616
1499
|
if (session.approval === "approved")
|
|
@@ -1753,9 +1636,9 @@ function startReview(session, input, environment) {
|
|
|
1753
1636
|
}
|
|
1754
1637
|
const kind = isFinalFeatureRun(session, run) ? "final" : "feature";
|
|
1755
1638
|
if (kind === "final") {
|
|
1756
|
-
const unsatisfied =
|
|
1639
|
+
const unsatisfied = unsatisfiedExtraEvidence(session, input.sourceDigest);
|
|
1757
1640
|
if (unsatisfied.length > 0) {
|
|
1758
|
-
fail(`Final review requires the plan's declared
|
|
1641
|
+
fail(`Final review requires the plan's declared evidence to pass for the current workspace content: ${unsatisfied.map((entry) => evidenceRefusal(session, entry, input.sourceDigest)).join(", ")}. A substitute observation cannot discharge it. If the environment is unavailable, ask the user to choose deferred or abandoned closure.`);
|
|
1759
1642
|
}
|
|
1760
1643
|
}
|
|
1761
1644
|
const applicable = run.validations.filter((validation) => isValidationEligible(validation, input.sourceDigest) && isValidationFresh(session, run, validation));
|
|
@@ -1935,9 +1818,9 @@ function closeSession(session, input) {
|
|
|
1935
1818
|
fail("A completed close requires every planned feature to pass review.");
|
|
1936
1819
|
}
|
|
1937
1820
|
if (input.kind === "completed") {
|
|
1938
|
-
const unsatisfied =
|
|
1821
|
+
const unsatisfied = unsatisfiedExtraEvidence(session);
|
|
1939
1822
|
if (unsatisfied.length > 0) {
|
|
1940
|
-
fail(`A completed close requires the plan's declared
|
|
1823
|
+
fail(`A completed close requires the plan's declared evidence to have passed: ${unsatisfied.map((entry) => evidenceRefusal(session, entry)).join(", ")}. Close deferred or abandoned instead.`);
|
|
1941
1824
|
}
|
|
1942
1825
|
}
|
|
1943
1826
|
let closure = null;
|
|
@@ -2169,12 +2052,13 @@ var PlanFeatureSchema = z.object({
|
|
|
2169
2052
|
validation: z.array(boundedText("Feature validation")).max(MAX_PLAN_FEATURES).default([]),
|
|
2170
2053
|
dependsOn: z.array(FeatureIdSchema).max(MAX_PLAN_FEATURES).default([])
|
|
2171
2054
|
}).strict();
|
|
2172
|
-
var
|
|
2173
|
-
requirement: boundedText("
|
|
2174
|
-
environment: boundedText("
|
|
2175
|
-
command: boundedText("
|
|
2055
|
+
var EvidenceEntrySchema = z.object({
|
|
2056
|
+
requirement: boundedText("Evidence requirement"),
|
|
2057
|
+
environment: boundedText("Evidence environment"),
|
|
2058
|
+
command: boundedText("Evidence command"),
|
|
2059
|
+
scope: z.enum(["gate", "extra"]),
|
|
2176
2060
|
platform: z.enum(EVIDENCE_PLATFORMS).optional(),
|
|
2177
|
-
assertions: z.array(boundedText("
|
|
2061
|
+
assertions: z.array(boundedText("Evidence assertion")).max(MAX_DECLARED_ASSERTIONS).optional()
|
|
2178
2062
|
}).strict();
|
|
2179
2063
|
var ObservedAssertionSchema = z.object({
|
|
2180
2064
|
name: boundedText("Observed assertion name"),
|
|
@@ -2186,8 +2070,7 @@ var PlanSchema = z.object({
|
|
|
2186
2070
|
requirements: z.array(boundedText("Plan requirement")).max(MAX_PLAN_FEATURES).default([]),
|
|
2187
2071
|
decisions: z.array(boundedText("Plan decision")).max(MAX_PLAN_FEATURES).default([]),
|
|
2188
2072
|
features: z.array(PlanFeatureSchema).min(1).max(MAX_PLAN_FEATURES),
|
|
2189
|
-
|
|
2190
|
-
externalEvidence: z.array(ExternalEvidenceSchema).max(MAX_PLAN_FEATURES).optional()
|
|
2073
|
+
evidence: z.array(EvidenceEntrySchema).max(MAX_PLAN_FEATURES).optional()
|
|
2191
2074
|
}).strict().superRefine((plan, context) => {
|
|
2192
2075
|
if (encoder.encode(JSON.stringify(plan)).byteLength > MAX_PLAN_BYTES) {
|
|
2193
2076
|
context.addIssue({
|
|
@@ -2413,23 +2296,23 @@ function assuranceProjection(session) {
|
|
|
2413
2296
|
check("recorded-completion", "Recorded completion", "ts-enforced", structural, `${completed}/${features.length} features and ${passing}/${features.length} independent reviews pass, including a final review with no terminal blocker.`),
|
|
2414
2297
|
check("accepted-validation", "Accepted validation", "host-attested", runs.length === features.length && runs.every((run) => accepted.some((observation) => observation.runId === run.id)), `${runs.filter((run) => accepted.some((item) => item.runId === run.id)).length}/${features.length} terminal runs have eligible host evidence accepted by review.`)
|
|
2415
2298
|
];
|
|
2416
|
-
const gate = session.plan
|
|
2299
|
+
const gate = planGate(session.plan);
|
|
2417
2300
|
checks.push(gate === undefined ? {
|
|
2418
2301
|
id: "canonical-gate",
|
|
2419
2302
|
label: "Canonical gate",
|
|
2420
2303
|
tier: "caller-declared",
|
|
2421
2304
|
status: "not-applicable",
|
|
2422
|
-
explanation: "This
|
|
2305
|
+
explanation: "This plan declared no canonical gate."
|
|
2423
2306
|
} : check("canonical-gate", "Canonical gate", "host-attested", accepted.some((observation) => observation.command === gate && observation.scope === "broad"), `${JSON.stringify(gate)} must have eligible broad evidence accepted by review.`));
|
|
2424
|
-
const declared = session.plan?.
|
|
2425
|
-
const missing =
|
|
2307
|
+
const declared = session.plan?.evidence;
|
|
2308
|
+
const missing = unsatisfiedEvidence(session).length;
|
|
2426
2309
|
checks.push(declared === undefined ? {
|
|
2427
|
-
id: "
|
|
2428
|
-
label: "Declared
|
|
2310
|
+
id: "declared-evidence",
|
|
2311
|
+
label: "Declared evidence",
|
|
2429
2312
|
tier: "caller-declared",
|
|
2430
2313
|
status: "not-applicable",
|
|
2431
|
-
explanation: "This
|
|
2432
|
-
} : check("
|
|
2314
|
+
explanation: "This plan declared no evidence obligations."
|
|
2315
|
+
} : check("declared-evidence", "Declared evidence", declared.length === 0 ? "caller-declared" : "host-attested", missing === 0, `${declared.length - missing}/${declared.length} declared obligations have eligible evidence on their declared host with named cases passing.`));
|
|
2433
2316
|
return {
|
|
2434
2317
|
conclusion: !complete ? "completion-not-claimed" : checks.some((item) => item.status === "unsatisfied") ? "completion-unsupported" : "completion-supported",
|
|
2435
2318
|
checks,
|
|
@@ -2637,9 +2520,8 @@ function reviewerProjection(session, assignmentId) {
|
|
|
2637
2520
|
validation: [...candidate.validation],
|
|
2638
2521
|
dependsOn: [...candidate.dependsOn]
|
|
2639
2522
|
})),
|
|
2640
|
-
...plan.
|
|
2641
|
-
|
|
2642
|
-
externalEvidence: plan.externalEvidence.map((entry) => ({
|
|
2523
|
+
...plan.evidence === undefined ? {} : {
|
|
2524
|
+
evidence: plan.evidence.map((entry) => ({
|
|
2643
2525
|
...entry
|
|
2644
2526
|
}))
|
|
2645
2527
|
}
|
|
@@ -4506,11 +4388,11 @@ var plan = host.object({
|
|
|
4506
4388
|
requirements: host.array(text).max(MAX_PLAN_FEATURES).default([]),
|
|
4507
4389
|
decisions: host.array(text).max(MAX_PLAN_FEATURES).default([]),
|
|
4508
4390
|
features: host.array(planFeature).min(1).max(MAX_PLAN_FEATURES),
|
|
4509
|
-
|
|
4510
|
-
externalEvidence: host.array(host.object({
|
|
4391
|
+
evidence: host.array(host.object({
|
|
4511
4392
|
requirement: text,
|
|
4512
4393
|
environment: text,
|
|
4513
4394
|
command: text,
|
|
4395
|
+
scope: host.enum(["gate", "extra"]),
|
|
4514
4396
|
platform: host.enum(EVIDENCE_PLATFORMS).optional(),
|
|
4515
4397
|
assertions: host.array(text).max(MAX_DECLARED_ASSERTIONS).optional()
|
|
4516
4398
|
}).strict()).max(MAX_PLAN_FEATURES).optional()
|
|
@@ -4617,12 +4499,14 @@ function toolError(error) {
|
|
|
4617
4499
|
}
|
|
4618
4500
|
});
|
|
4619
4501
|
}
|
|
4620
|
-
function withAutoContext(response, options) {
|
|
4502
|
+
function withAutoContext(response, options, view) {
|
|
4621
4503
|
let workflowData = response.workflowData;
|
|
4622
4504
|
try {
|
|
4623
|
-
|
|
4624
|
-
|
|
4625
|
-
|
|
4505
|
+
if (view === "detail") {
|
|
4506
|
+
const timing = options.autoTimingSnapshot?.();
|
|
4507
|
+
if (timing)
|
|
4508
|
+
workflowData = { ...workflowData, autoTiming: timing };
|
|
4509
|
+
}
|
|
4626
4510
|
} catch {}
|
|
4627
4511
|
try {
|
|
4628
4512
|
const support = options.autoContinuationSupport?.();
|
|
@@ -4669,7 +4553,7 @@ function createTools(_ctx, options) {
|
|
|
4669
4553
|
flow_status: tool({
|
|
4670
4554
|
description: "Read compact, execution, detail, or reviewer Flow state.",
|
|
4671
4555
|
args: StatusArgs,
|
|
4672
|
-
execute: (args, context) => execute(context, async (workspace) => withAutoContext(await flowStatus(workspace, args), options))
|
|
4556
|
+
execute: (args, context) => execute(context, async (workspace) => withAutoContext(await flowStatus(workspace, args), options, args.request.view))
|
|
4673
4557
|
}),
|
|
4674
4558
|
flow_plan_save: tool({
|
|
4675
4559
|
description: "Create or replace the active draft plan.",
|
|
@@ -5139,4 +5023,4 @@ export {
|
|
|
5139
5023
|
plugin_default as default
|
|
5140
5024
|
};
|
|
5141
5025
|
|
|
5142
|
-
//# debugId=
|
|
5026
|
+
//# debugId=84B9887B14A5141164756E2164756E21
|