@quantiya/codevibe-claude-plugin 2.0.42 → 2.0.44
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/.claude-plugin/plugin.json +1 -1
- package/node_modules/@quantiya/codevibe-core/dist/index.js +502 -491
- package/node_modules/@quantiya/codevibe-core/dist/local-executor/agentic-resolver-flag.d.ts +4 -7
- package/node_modules/@quantiya/codevibe-core/dist/local-executor/class-b-consumer.d.ts +5 -5
- package/node_modules/@quantiya/codevibe-core/dist/local-executor/hook-bridge.d.ts +1 -1
- package/node_modules/@quantiya/codevibe-core/dist/local-executor/index.d.ts +1 -1
- package/node_modules/@quantiya/codevibe-core/dist/local-executor/local-executor-impl.d.ts +52 -20
- package/node_modules/@quantiya/codevibe-core/dist/local-executor/merge-train.d.ts +1 -1
- package/node_modules/@quantiya/codevibe-core/dist/local-executor/reviewer-rationale-flag.d.ts +3 -8
- package/node_modules/@quantiya/codevibe-core/dist/local-executor/team-execution-flag.d.ts +0 -6
- package/node_modules/@quantiya/codevibe-core/dist/local-executor/types.d.ts +7 -2
- package/node_modules/@quantiya/codevibe-core/dist/local-executor/workspace-shadow.d.ts +16 -0
- package/node_modules/@quantiya/codevibe-core/dist/local-model/manager.d.ts +5 -3
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/cli.js +42310 -40649
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/components/ImplementorSetupWizard.d.ts +10 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/components/InputBar.d.ts +1 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/gate-decision-submit.d.ts +26 -5
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/implementor-preference.d.ts +24 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/index.d.ts +37 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/non-tty-fallback.d.ts +3 -4
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/quorum-loop.d.ts +248 -84
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/reducer.d.ts +7 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/slash-routes/continuation.d.ts +5 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/slash-routes/implementors.d.ts +17 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/task-label.d.ts +25 -0
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/team-decompose.d.ts +9 -8
- package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/types.d.ts +131 -0
- package/node_modules/@quantiya/codevibe-core/dist/planner/types.d.ts +2 -2
- package/node_modules/@quantiya/codevibe-core/dist/tool-activity/types.d.ts +12 -12
- package/node_modules/@quantiya/codevibe-core/package.json +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { ImplementorWizardState } from '../types';
|
|
3
|
+
import { type ImplementorPreference } from '../implementor-preference';
|
|
4
|
+
export declare const IMPLEMENTOR_WIZARD_MAX_ROWS = 12;
|
|
5
|
+
export interface ImplementorSetupWizardProps {
|
|
6
|
+
wizard: ImplementorWizardState;
|
|
7
|
+
onSubmit: (pref: ImplementorPreference) => void;
|
|
8
|
+
onCancel: () => void;
|
|
9
|
+
}
|
|
10
|
+
export declare function ImplementorSetupWizard(props: ImplementorSetupWizardProps): React.ReactElement;
|
package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/gate-decision-submit.d.ts
CHANGED
|
@@ -89,13 +89,34 @@ type GatePromptEntry = Extract<ConversationEntry, {
|
|
|
89
89
|
kind: 'gate-prompt';
|
|
90
90
|
}>;
|
|
91
91
|
/**
|
|
92
|
-
* §5.1 + #C8M-11 active-gate-prompt scan
|
|
93
|
-
*
|
|
92
|
+
* §5.1 + #C8M-11 active-gate-prompt scan: the OLDEST `kind:'gate-prompt'`
|
|
93
|
+
* entry with `final === false` (head-to-tail). Pure; safe to call from a
|
|
94
94
|
* render path. Returns the entry verbatim so callers can pattern-match the
|
|
95
|
-
* discriminated union directly. (Shared so the TTY component
|
|
96
|
-
* the identical scan.)
|
|
95
|
+
* discriminated union directly. (Shared so the TTY component, the mobile
|
|
96
|
+
* reply route and the non-TTY loop use the identical scan.)
|
|
97
|
+
*
|
|
98
|
+
* P46a (F-P46a-5): this used to be tail-to-head (the NEWEST open gate). With
|
|
99
|
+
* several tasks in flight, gates arrive in bursts, and the newest-wins rule
|
|
100
|
+
* moved the target under the user's fingers — the composer read `Task #2`,
|
|
101
|
+
* a gate for `#3` arrived, and the `1` that was typed for #2 approved #3
|
|
102
|
+
* (E2E r3 q1). Oldest-first keeps the active gate — its pinned card, the
|
|
103
|
+
* composer label `Type a number 1..N · Task #n`, and the gate a digit
|
|
104
|
+
* resolves — stable until the user answers it; newer gates wait their turn.
|
|
105
|
+
*
|
|
106
|
+
* Stage 1 r1 F2(b): an older open gate that is NOT answerable — stuck in
|
|
107
|
+
* `confirming` / `submitting` (the F-P46a-1 wedge) or `claimed` elsewhere —
|
|
108
|
+
* must not block every newer gate: the active gate is the oldest open gate in
|
|
109
|
+
* an ANSWERABLE phase (`awaiting-number` / `awaiting-notes`); when no open gate
|
|
110
|
+
* is answerable, the oldest open one (so the UI still shows its state).
|
|
111
|
+
*
|
|
112
|
+
* Stage 1 r2 F1: that choice is STICKY. Callers holding the store state pass
|
|
113
|
+
* `state.activeGatePromptId` (reducer-owned, see `normalizeActiveGatePrompt`):
|
|
114
|
+
* while that entry is open it stays the active gate, so an older gate whose
|
|
115
|
+
* submit rolled back to `awaiting-number` never takes the digits (or a
|
|
116
|
+
* half-typed note) back from the gate the user is answering. Without an id the
|
|
117
|
+
* scan above applies (pure callers and tests).
|
|
97
118
|
*/
|
|
98
|
-
export declare function findActiveGatePromptEntry(conversation: ReadonlyArray<ConversationEntry
|
|
119
|
+
export declare function findActiveGatePromptEntry(conversation: ReadonlyArray<ConversationEntry>, activeGatePromptId?: string | null): GatePromptEntry | null;
|
|
99
120
|
/**
|
|
100
121
|
* Submit a gate decision: dispatch SUBMIT_STARTED, fire the SDK, dispatch
|
|
101
122
|
* RESOLVED on success (and notify `onTerminalDecision`) or SUBMIT_FAILED on
|
package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/implementor-preference.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export type ActiveImplementorAgentKind = 'CLAUDE' | 'CODEX' | 'ANTIGRAVITY';
|
|
2
|
+
export declare const DEFAULT_IMPLEMENTOR_PRIORITY: readonly ActiveImplementorAgentKind[];
|
|
3
|
+
export interface ImplementorPreference {
|
|
4
|
+
schemaVersion: 1;
|
|
5
|
+
priorityOrder: ActiveImplementorAgentKind[];
|
|
6
|
+
confirmBeforeStart: boolean;
|
|
7
|
+
updatedAt: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function implementorPreferenceFilePath(): string;
|
|
10
|
+
export declare function defaultImplementorPreference(): ImplementorPreference;
|
|
11
|
+
export declare function normalizeImplementorAgent(val: string): ActiveImplementorAgentKind | null;
|
|
12
|
+
/**
|
|
13
|
+
* Synchronously reads the implementor preference. Fails soft: returns defaults
|
|
14
|
+
* if the file is absent or corrupt.
|
|
15
|
+
*/
|
|
16
|
+
export declare function readImplementorPreferenceSync(): ImplementorPreference;
|
|
17
|
+
/**
|
|
18
|
+
* Saves updated implementor preference to ~/.codevibe/implementor-preference.json.
|
|
19
|
+
*/
|
|
20
|
+
export declare function saveImplementorPreference(patch: {
|
|
21
|
+
priorityOrder?: ActiveImplementorAgentKind[];
|
|
22
|
+
confirmBeforeStart?: boolean;
|
|
23
|
+
}): Promise<ImplementorPreference>;
|
|
24
|
+
export declare function resetImplementorPreference(): Promise<ImplementorPreference>;
|
|
@@ -47,7 +47,30 @@ import type { EnsureFreshResult } from './context-store';
|
|
|
47
47
|
import { contextItemOccurrence, type ContextDurabilityReceipt } from './context-items';
|
|
48
48
|
import { renderRehydratedSessionContext } from './context-compaction';
|
|
49
49
|
import type { AgentKind as LocalExecutorAgentKind } from '../local-executor/types';
|
|
50
|
+
import type { OrchestrationState as OrchestrationStateType } from './types';
|
|
50
51
|
import { type TaskProgressEvent } from './task-progress';
|
|
52
|
+
import { taskLabel } from './task-label';
|
|
53
|
+
/**
|
|
54
|
+
* Gathers the implementor agents currently active across single-implementor running tasks
|
|
55
|
+
* and multi-track Agent Teams tracks. Used for multi-track priority allocation.
|
|
56
|
+
*/
|
|
57
|
+
export declare function getInFlightImplementorAgents(state: OrchestrationStateType): LocalExecutorAgentKind[];
|
|
58
|
+
/**
|
|
59
|
+
* P46a (Stage 1 r1 F2a) — the oldest unresolved continuation-offer gate
|
|
60
|
+
* prompt, whatever other gates are open. Pure.
|
|
61
|
+
*/
|
|
62
|
+
export declare function findActiveContinuationOfferEntry(conversation: ReadonlyArray<ConversationEntry>): (ConversationEntry & {
|
|
63
|
+
kind: 'gate-prompt';
|
|
64
|
+
}) | null;
|
|
65
|
+
/**
|
|
66
|
+
* P46a (Stage 1 r1 F2c) — a typed digit from the phone cannot choose between
|
|
67
|
+
* several open review gates (the phone shows no task label until P46b): the
|
|
68
|
+
* advisory to send back instead of answering the oldest gate, or null when the
|
|
69
|
+
* reply is not a bare digit or at most one gate is answerable. Pure.
|
|
70
|
+
*/
|
|
71
|
+
export declare function mobileGateReplyAmbiguity(state: Parameters<typeof taskLabel>[0] & {
|
|
72
|
+
conversation: ReadonlyArray<ConversationEntry>;
|
|
73
|
+
}, text: string): string | null;
|
|
51
74
|
export declare class OrchestrationShellStartupError extends Error {
|
|
52
75
|
readonly cause?: unknown;
|
|
53
76
|
constructor(message: string, cause?: unknown);
|
|
@@ -686,6 +709,20 @@ export declare function routeTeamDecompose(deps: {
|
|
|
686
709
|
/** Stage-2 R3 HIGH — the loop's durable store, so the live launch persists the retained spec + attachments. */
|
|
687
710
|
durableStore?: RevertManifestStore;
|
|
688
711
|
}): Promise<void>;
|
|
712
|
+
/**
|
|
713
|
+
* Shared helper for handling LaunchTeamOutcome for both unconfirmed (auto-launch)
|
|
714
|
+
* and confirmed ("yes" reply) team launches. Ensures parity across both paths:
|
|
715
|
+
* - 'accepted' -> clean return (success advisory already dispatched by launchTeamFromWorkItems)
|
|
716
|
+
* - 'disjointness_rejected' -> dispatch advisory, call fallbackToSingle (if provided)
|
|
717
|
+
* - 'unknown_create_error' -> retry ONCE with same idempotency key; if second attempt
|
|
718
|
+
* is disjointness_rejected -> fallbackToSingle; if second attempt is unknown_create_error ->
|
|
719
|
+
* dispatch "Couldn't confirm the team started — check /status or retry. Nothing was launched."
|
|
720
|
+
*/
|
|
721
|
+
export declare function handleTeamLaunchOutcome(deps: {
|
|
722
|
+
launch: () => Promise<LaunchTeamOutcome>;
|
|
723
|
+
store: OrchestrationStore;
|
|
724
|
+
fallbackToSingle?: () => Promise<void>;
|
|
725
|
+
}): Promise<void>;
|
|
689
726
|
/** Test seam — reset the module-level A1e and M7 composers (vitest-gated). */
|
|
690
727
|
export declare function resetDispatchContextComposerForTests(): void;
|
|
691
728
|
/** Test seam — install the M7 decomposer user-context composer (vitest-gated). */
|
|
@@ -38,9 +38,8 @@ export interface RunLineLogFallbackArgs {
|
|
|
38
38
|
/**
|
|
39
39
|
* Whether the internal planner-classification entry (`[planner] <action>:
|
|
40
40
|
* <rationale>` / the TTY "Planner classified …" node) is shown to the user.
|
|
41
|
-
* OFF by default — it's internal mechanics that duplicate the actual response
|
|
42
|
-
*
|
|
43
|
-
* Opt in with `CODEVIBE_PLANNER_DEBUG=1` when debugging the planner. The entry is
|
|
41
|
+
* OFF by default — it's internal mechanics that duplicate the actual response.
|
|
42
|
+
* Standardized to log level `CODEVIBE_LOG_LEVEL=debug`. The entry is
|
|
44
43
|
* ALWAYS kept in conversation state (audit / logic / tests) — only the VIEW is gated.
|
|
45
44
|
*/
|
|
46
45
|
export declare function plannerDecisionRenderEnabled(env?: NodeJS.ProcessEnv): boolean;
|
|
@@ -48,7 +47,7 @@ export declare function plannerDecisionRenderEnabled(env?: NodeJS.ProcessEnv): b
|
|
|
48
47
|
* Renders a single `ConversationEntry` as a line-prefixed text string.
|
|
49
48
|
* Strict text only — no ANSI escapes, no colors, no `\r` rewrites.
|
|
50
49
|
*/
|
|
51
|
-
export declare function renderEntryAsLine(entry: ConversationEntry): string;
|
|
50
|
+
export declare function renderEntryAsLine(entry: ConversationEntry, labelFor?: (taskId: string) => string | undefined): string;
|
|
52
51
|
/**
|
|
53
52
|
* Subscribes to the store and prints new conversation entries as
|
|
54
53
|
* line-prefixed text. Returns a promise that resolves on `EXIT` action
|
|
@@ -103,17 +103,18 @@ export declare function policyRejectionAdvisoryText(info: {
|
|
|
103
103
|
* - An explicit `override` (from `/task --agent claude|codex|antigravity`) wins, BUT only
|
|
104
104
|
* when that agent was actually detected on this host (else fail-closed to the
|
|
105
105
|
* default — we never spawn a binary the host doesn't have).
|
|
106
|
-
* -
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
106
|
+
* - Configurable implementor priority order via ~/.codevibe/implementor-preference.json
|
|
107
|
+
* (defaults to CLAUDE > CODEX > ANTIGRAVITY).
|
|
108
|
+
* - Multi-track priority allocation: when concurrent tracks run, allocates each track
|
|
109
|
+
* to the next idle agent in priority order. For hosts with a single installed agent,
|
|
110
|
+
* all tracks allocate to that agent.
|
|
111
|
+
* - Explicit override (@mention or --agent flag) always takes precedence if installed.
|
|
111
112
|
*
|
|
112
113
|
* Returns `{ agent, note }` — `note` is a non-null user-facing string ONLY when
|
|
113
114
|
* an explicit override could not be honored (so the shell can surface it); null
|
|
114
115
|
* when the selection was clean. NEVER throws.
|
|
115
116
|
*/
|
|
116
|
-
export declare function selectImplementorAgent(detected: readonly AgentKind[], override?: AgentKind | null): {
|
|
117
|
+
export declare function selectImplementorAgent(detected: readonly AgentKind[], override?: AgentKind | null, inFlightAgents?: readonly AgentKind[] | null, priorityOrder?: readonly AgentKind[] | null): {
|
|
117
118
|
agent: AgentKind;
|
|
118
119
|
note: string | null;
|
|
119
120
|
};
|
|
@@ -320,24 +321,10 @@ export interface QuorumLoopDeps {
|
|
|
320
321
|
/**
|
|
321
322
|
* CP-14 Wave A — the team execution model. `worktree_merge` makes each team
|
|
322
323
|
* track commit to a persistent branch (the merge-before-push spine) instead of
|
|
323
|
-
* the merge-train promote (the
|
|
324
|
-
* shipped path byte-identical
|
|
325
|
-
* unset (see {@link resolveTeamExecution}).
|
|
324
|
+
* the merge-train promote (the sole model since the §10 retirement). Omitted keeps the
|
|
325
|
+
* shipped path byte-identical (see {@link resolveTeamExecution}).
|
|
326
326
|
*/
|
|
327
327
|
teamExecution?: TeamExecution;
|
|
328
|
-
/**
|
|
329
|
-
* CP-7 Stage-2 r3 (Codex) HIGH — ARM the LE's current/authorized task id so
|
|
330
|
-
* the round-0 (and revise) implementor spawn engages the CP-7 trusted-execution
|
|
331
|
-
* substrate instead of the pre-TaskAuthorized reduced-trust path. `startTask`
|
|
332
|
-
* threads the minted taskId here BEFORE the round-0 spawn drains (and rolls it
|
|
333
|
-
* back to `null` on a START rejection); production wires it to
|
|
334
|
-
* `LocalExecutorImpl.setActiveTaskId`. ABSENT (legacy/tests) → the LE's task id
|
|
335
|
-
* is unchanged (the pre-fix behavior); production MUST wire it so the
|
|
336
|
-
* implementor never spawns unbadged/unsandboxed. The same state
|
|
337
|
-
* (`LocalExecutorImpl.taskId`) drives `engageSubstrateForSpawn` (local-executor-
|
|
338
|
-
* impl.ts:566) to call `substrateEngager` rather than emit a `tier:'none'` badge.
|
|
339
|
-
*/
|
|
340
|
-
armLeTaskId?: (taskId: string | null) => void;
|
|
341
328
|
/**
|
|
342
329
|
* CP-7 §8 (Stage-1-resolved) — engage the CP-7 trusted-execution substrate +
|
|
343
330
|
* broker for ONE reviewer seat. When wired (production via cli.ts →
|
|
@@ -345,11 +332,8 @@ export interface QuorumLoopDeps {
|
|
|
345
332
|
* agent reviewer runs INSIDE the sandbox with no ambient vendor creds and a
|
|
346
333
|
* broker-routed model call — closing the CP-14 §8/§13 reviewer-sandbox gap.
|
|
347
334
|
* ABSENT (legacy / companion / tests) → reviewers take the legacy unsandboxed
|
|
348
|
-
* path BYTE-IDENTICAL (§7 non-regression). Reviewer-sandboxing
|
|
349
|
-
* when this engager is wired (
|
|
350
|
-
* (`CODEVIBE_SANDBOX_REVIEWERS=0`, read in `engageSeatSubstrate` on the
|
|
351
|
-
* `spawnOneSeat` path — see `reviewerSandboxingEnabled`). The flag is
|
|
352
|
-
* independent of implementor sandboxing (which has its own engager).
|
|
335
|
+
* path BYTE-IDENTICAL (§7 non-regression). Reviewer-sandboxing is mandatory
|
|
336
|
+
* when this engager is wired (see `reviewerSandboxingEnabled`).
|
|
353
337
|
*/
|
|
354
338
|
engageReviewerSubstrate?: ReviewerSubstrateEngager;
|
|
355
339
|
/**
|
|
@@ -599,12 +583,59 @@ interface TeamRunAuthority {
|
|
|
599
583
|
* here closes packet-order races without extending or weakening the wire.
|
|
600
584
|
*/
|
|
601
585
|
export declare function teamRound0GateId(taskId: string, taskGroupId: string, trackIndex: number, dispatchGeneration: number): string;
|
|
586
|
+
/**
|
|
587
|
+
* P46a D1 — the reducer-owned in-session task numbering, reachable from the
|
|
588
|
+
* loop through this sink (installed by the shell after the store exists).
|
|
589
|
+
* `assign` returns the number the store assigned (undefined when unwired);
|
|
590
|
+
* `label` renders `#n` / `#n retry` / the short-id fallback for any task id.
|
|
591
|
+
*/
|
|
592
|
+
export interface TaskOrdinalSink {
|
|
593
|
+
assign(taskId: string, opts: {
|
|
594
|
+
kind: 'single' | 'group';
|
|
595
|
+
retryOf?: string;
|
|
596
|
+
}): number | undefined;
|
|
597
|
+
label(taskId: string): string;
|
|
598
|
+
}
|
|
599
|
+
/** P46a C3 — the desktop-local "could not apply" menu the loop asks the shell to present. */
|
|
600
|
+
export interface ApplyConflictMenu {
|
|
601
|
+
taskId: string;
|
|
602
|
+
taskLabel: string;
|
|
603
|
+
conflicts: Array<{
|
|
604
|
+
path: string;
|
|
605
|
+
cause: 'session-task' | 'external' | 'write-error';
|
|
606
|
+
byTaskLabel?: string;
|
|
607
|
+
}>;
|
|
608
|
+
autoRetried: boolean;
|
|
609
|
+
retryBrief: string;
|
|
610
|
+
/** The ROOT user request (Stage 1 r3 F1) — the menu's retry carries it (web-access decision, `/status`). */
|
|
611
|
+
request: string;
|
|
612
|
+
agent: AgentKind;
|
|
613
|
+
}
|
|
602
614
|
export declare class QuorumLoop {
|
|
603
615
|
private readonly deps;
|
|
604
616
|
private readonly sleep;
|
|
605
617
|
private workspaceOutcomeSink?;
|
|
606
|
-
/**
|
|
607
|
-
|
|
618
|
+
/**
|
|
619
|
+
* P46a B1 — the FOCUSED single task: the task the UI means when a command
|
|
620
|
+
* names none (`/continue`, `/review-reset`, the status "starting" row).
|
|
621
|
+
* Default = the most recently CONFIRMED START; `/task focus <n>` sets it
|
|
622
|
+
* explicitly; it advances to the newest remaining single task when the
|
|
623
|
+
* focused task ends; a rejected START never moves it. It replaces the three
|
|
624
|
+
* P45 singletons (`activeTaskId` / `activeBrief` / `activeImplementorAgent`):
|
|
625
|
+
* every reader now resolves through the task's OWN record
|
|
626
|
+
* (`singleTaskContextByTask`), never through "the latest task".
|
|
627
|
+
*/
|
|
628
|
+
private focusedTaskId;
|
|
629
|
+
/** P46a B1 — confirmed single tasks in START-confirmation order (focus fallback). */
|
|
630
|
+
private readonly confirmedSingleOrder;
|
|
631
|
+
/**
|
|
632
|
+
* P46a B1 — the most recent START still in flight (or null). A legacy
|
|
633
|
+
* GATE_DISPATCH with an EMPTY envelope task id can only belong to it (the P45
|
|
634
|
+
* rule); with no START in flight such a packet is a no-op left to recovery.
|
|
635
|
+
*/
|
|
636
|
+
private latestInFlightStart;
|
|
637
|
+
/** Stage 1 r1 F13 — every START still in flight, in issue order; `latestInFlightStart` is its last entry. */
|
|
638
|
+
private readonly startOrderInFlight;
|
|
608
639
|
/** Tasks whose next automatic revise round must start a fresh review baseline. */
|
|
609
640
|
private readonly reviewScopeResetTasks;
|
|
610
641
|
/** Non-terminal tasks for which `/review-reset` may arm the next revise round. */
|
|
@@ -613,16 +644,9 @@ export declare class QuorumLoop {
|
|
|
613
644
|
private readonly epochByTaskId;
|
|
614
645
|
private readonly tokensByTaskId;
|
|
615
646
|
private readonly tokensCountedGates;
|
|
616
|
-
/**
|
|
617
|
-
* The implementor brief for the active task (set at start_task). The
|
|
618
|
-
* GATE_DISPATCH consumer reads this to drive the round-0 implementor spawn —
|
|
619
|
-
* the brief is no longer threaded inline through the spawn call (the spawn
|
|
620
|
-
* moved out of `startTask` into the GATE_DISPATCH consumer, §3.C.20 FIX).
|
|
621
|
-
*/
|
|
622
|
-
private activeBrief;
|
|
623
647
|
/**
|
|
624
648
|
* IMAGE-ATTACHMENT-DESIGN.md §5 — TASK-SCOPED image attachments (parallel to
|
|
625
|
-
* `
|
|
649
|
+
* `singleTaskContextByTask`/`activeBriefByTask`). The single-impl path uses `activeAttachments`;
|
|
626
650
|
* the team path keys by the child `taskId` in `activeAttachmentsByTask` (armed at
|
|
627
651
|
* `registerTeamTaskBrief`, before its buffered GATE_DISPATCH drains). Re-copied
|
|
628
652
|
* into EACH round's shadow at `runImplementorRound` (round-0, revise, continuation,
|
|
@@ -677,20 +701,50 @@ export declare class QuorumLoop {
|
|
|
677
701
|
private readonly recoveredBriefsByAuthority;
|
|
678
702
|
private readonly activeBriefByTask;
|
|
679
703
|
/**
|
|
680
|
-
* P45 D1 (M7 E2E step 8, 2026-09-14) — the brief + agent of EVERY
|
|
681
|
-
* implementor task this loop started, keyed by task id.
|
|
682
|
-
*
|
|
683
|
-
*
|
|
684
|
-
*
|
|
685
|
-
*
|
|
686
|
-
*
|
|
687
|
-
*
|
|
688
|
-
* continuation context resolve through this map first; the singletons stay
|
|
689
|
-
* as the legacy fallback (an empty envelope task id, the test seam). Entries
|
|
690
|
-
* are removed with the task's other per-task state at its terminal cleanup.
|
|
704
|
+
* P45 D1 (M7 E2E step 8, 2026-09-14) / P46a B1 — the brief + agent of EVERY
|
|
705
|
+
* LIVE single-implementor task this loop started, keyed by task id. P45 added
|
|
706
|
+
* it beside the three "latest task" singletons (a second single task's
|
|
707
|
+
* request had replaced the first task's in its revise round); P46a deletes
|
|
708
|
+
* the singletons — round-0 spawns, revise rounds, the continuation context and
|
|
709
|
+
* every other reader resolve ONLY through this map. An entry exists from the
|
|
710
|
+
* START call (in flight) until the task's terminal cleanup; `retryOf` links a
|
|
711
|
+
* `#n retry` task to its `apply_failed` original (P46a C2/C3).
|
|
691
712
|
*/
|
|
692
713
|
private readonly singleTaskContextByTask;
|
|
714
|
+
/** Agent web browsing (upstream 2.0.37) — whether a task's ORIGINAL request needs web access; ends with the task (`forgetSingleTask`, team cleanup). */
|
|
693
715
|
private readonly webAccessByTask;
|
|
716
|
+
/**
|
|
717
|
+
* P46a D2 — append-only per-loop-life record of every single task this loop
|
|
718
|
+
* started (confirmed or in flight) with its terminal outcome once known, for
|
|
719
|
+
* `/status` (`describeTasks`). Never deleted (bounded by the session's tasks).
|
|
720
|
+
*/
|
|
721
|
+
private readonly singleTaskHistory;
|
|
722
|
+
/**
|
|
723
|
+
* P46a C1 — every single-task promote THIS session landed, by workspace-
|
|
724
|
+
* relative path: the promoting task + the post-image hash/mode the promote
|
|
725
|
+
* compare-and-set reads (`readRealMetadata`; `null` hash = a deletion). Used
|
|
726
|
+
* to attribute a later collision to a `session-task` (the path's current
|
|
727
|
+
* metadata equals a recorded post-image) or `external` (anything else —
|
|
728
|
+
* including a session-promoted file the user edited afterwards, and every
|
|
729
|
+
* promote by another session). In-memory, fail-safe: empty after a desktop
|
|
730
|
+
* restart, so every collision then classifies as `external`.
|
|
731
|
+
*/
|
|
732
|
+
private readonly promotedByPath;
|
|
733
|
+
/** P46a C2 — originals whose ONE automatic retry has been issued (never a second). */
|
|
734
|
+
private readonly autoRetryIssuedFor;
|
|
735
|
+
/**
|
|
736
|
+
* P46a C2 — retry STARTs planned inside the promote critical section and
|
|
737
|
+
* issued only after it (and the durable `apply_failed` record) completed:
|
|
738
|
+
* `startTask` runs the round-0 spawn before returning, so it must never run
|
|
739
|
+
* inside `promoteShadowLocked`.
|
|
740
|
+
*/
|
|
741
|
+
private readonly pendingPromoteRetries;
|
|
742
|
+
/** P46a D1 — the store-owned ordinal sink (installed by the shell after construction). */
|
|
743
|
+
private taskOrdinalSink?;
|
|
744
|
+
/** P46a C3 — the desktop-local apply-conflict menu sink (installed by the shell). */
|
|
745
|
+
private applyConflictSink?;
|
|
746
|
+
/** P46a C2 — notified when an automatic retry task started (the shell records its lifecycle row). */
|
|
747
|
+
private retryStartedSink?;
|
|
694
748
|
/**
|
|
695
749
|
* CP-1.f revise-context fix (dogfood task 2ac68708, 2026-06-11) — the BINDING
|
|
696
750
|
* user-requested changes for a task, accumulated across ALL revise rounds.
|
|
@@ -761,8 +815,8 @@ export declare class QuorumLoop {
|
|
|
761
815
|
* the stdin, NEVER the task_brief the reviewers see.
|
|
762
816
|
* 2. The agentic class-2 resolver brief (≤ RATIONALE_RESOLVER_MAX_BYTES,
|
|
763
817
|
* ungated — the resolver is intent-starved by design).
|
|
764
|
-
* 3. Reviewer packets
|
|
765
|
-
*
|
|
818
|
+
* 3. Reviewer packets NEVER receive implementor rationale (permanent
|
|
819
|
+
* diff-only review policy invariant).
|
|
766
820
|
* Lifecycle mirrors `userNotesByTask` (promote / terminal discard / restart
|
|
767
821
|
* clear; PRESERVED across the non-terminal quota-fork/takeover discards).
|
|
768
822
|
*/
|
|
@@ -1245,10 +1299,67 @@ export declare class QuorumLoop {
|
|
|
1245
1299
|
setWorkspaceOutcomeSink(sink: WorkspaceOutcomeSink | undefined): void;
|
|
1246
1300
|
isWorkspaceTaskTerminallyRetired(taskId: string): boolean;
|
|
1247
1301
|
isTaskTerminallyRetired(taskId: string): boolean;
|
|
1248
|
-
/**
|
|
1302
|
+
/**
|
|
1303
|
+
* P46a B1 — the FOCUSED single task (null when no single task is live). The
|
|
1304
|
+
* P45 `activeTask` name is kept for the shell's readers; it now means the
|
|
1305
|
+
* focused task, never "the latest task".
|
|
1306
|
+
*/
|
|
1249
1307
|
get activeTask(): string | null;
|
|
1250
|
-
/**
|
|
1251
|
-
|
|
1308
|
+
/** P46a B1 — every LIVE single task this loop started (in flight or confirmed). */
|
|
1309
|
+
knownSingleTasks(): string[];
|
|
1310
|
+
/**
|
|
1311
|
+
* P46a B1 — `/task focus <n>`: make `taskId` the focused task. Refused (false)
|
|
1312
|
+
* for a task this loop does not know as a live single task.
|
|
1313
|
+
*/
|
|
1314
|
+
setFocusedTask(taskId: string): boolean;
|
|
1315
|
+
/** P46a D1 — install the store-owned ordinal sink (the shell, after construction). */
|
|
1316
|
+
setTaskOrdinalSink(sink: TaskOrdinalSink | undefined): void;
|
|
1317
|
+
/** P46a C3 — install the desktop-local apply-conflict menu sink. */
|
|
1318
|
+
setApplyConflictSink(sink: ((menu: ApplyConflictMenu) => void) | undefined): void;
|
|
1319
|
+
/** P46a C2 — install the retry-started notifier (the shell records the lifecycle row). */
|
|
1320
|
+
setRetryStartedSink(sink: ((info: {
|
|
1321
|
+
taskId: string;
|
|
1322
|
+
retryOf: string;
|
|
1323
|
+
agent: AgentKind;
|
|
1324
|
+
}) => void) | undefined): void;
|
|
1325
|
+
/** P46a D1 — `#n` / `#n retry` / short id for any task id (never throws). */
|
|
1326
|
+
labelFor(taskId: string): string;
|
|
1327
|
+
/**
|
|
1328
|
+
* P46a D2 — every single task this loop started, for `/status`: its label,
|
|
1329
|
+
* agent, request (desktop-local plaintext — the user's own words), link to an
|
|
1330
|
+
* `apply_failed` original, loop state and whether it is the focused task.
|
|
1331
|
+
*/
|
|
1332
|
+
describeTasks(): Array<{
|
|
1333
|
+
taskId: string;
|
|
1334
|
+
label: string;
|
|
1335
|
+
agent: AgentKind;
|
|
1336
|
+
brief: string;
|
|
1337
|
+
retryOf?: string;
|
|
1338
|
+
outcome: 'running' | 'applied' | 'discarded' | 'apply_failed' | 'unresolved' | 'rejected';
|
|
1339
|
+
implementorActive: boolean;
|
|
1340
|
+
focused: boolean;
|
|
1341
|
+
}>;
|
|
1342
|
+
/** Stage 1 r1 F13 — a START confirmed or rejected: the newest START still in flight (if any) becomes the empty-envelope target. */
|
|
1343
|
+
private dropInFlightStart;
|
|
1344
|
+
/**
|
|
1345
|
+
* P46a B1 — a single task ended (promote, terminal discard, rejected START):
|
|
1346
|
+
* drop its live record and, when it was the focused task, advance the focus
|
|
1347
|
+
* to the newest remaining confirmed single task (or none).
|
|
1348
|
+
*/
|
|
1349
|
+
private forgetSingleTask;
|
|
1350
|
+
/**
|
|
1351
|
+
* Arm an explicit, one-shot comprehensive baseline for the FOCUSED task
|
|
1352
|
+
* (P46a B1). Refused with the candidate list when the focused task has no
|
|
1353
|
+
* eligible gate (or no single task is focused) — the shell renders the
|
|
1354
|
+
* `#n` candidates so the user can `/task focus <n>` first.
|
|
1355
|
+
*/
|
|
1356
|
+
requestReviewScopeReset(): {
|
|
1357
|
+
armed: true;
|
|
1358
|
+
taskId: string;
|
|
1359
|
+
} | {
|
|
1360
|
+
armed: false;
|
|
1361
|
+
candidates: string[];
|
|
1362
|
+
};
|
|
1252
1363
|
/**
|
|
1253
1364
|
* Audited-path fix (Fix 5) — the host's detected implementor agents
|
|
1254
1365
|
* (UPPERCASE `AgentKind`), as threaded into the loop at construction. Used by
|
|
@@ -1369,6 +1480,16 @@ export declare class QuorumLoop {
|
|
|
1369
1480
|
agent: AgentKind;
|
|
1370
1481
|
/** IMAGE-ATTACHMENT-DESIGN.md §5 — task-scoped image attachments, armed before the drain. */
|
|
1371
1482
|
attachments?: ImageAttachment[];
|
|
1483
|
+
/** P46a C2/C3 — the `apply_failed` original this task retries (renders `#n retry`). */
|
|
1484
|
+
retryOf?: string;
|
|
1485
|
+
/**
|
|
1486
|
+
* P46a C2/C3 (Stage 1 r3 F1) — the ROOT user request a retry carries. A
|
|
1487
|
+
* retry's `brief` is the COMPOSED retry brief (diffs + reviewed contents that
|
|
1488
|
+
* can hold any text — URLs included); decisions that must follow the user's
|
|
1489
|
+
* own words (the agent-web access decision, the next retry brief, `/status`)
|
|
1490
|
+
* read this instead. Omitted for an ordinary task (its brief IS the request).
|
|
1491
|
+
*/
|
|
1492
|
+
request?: string;
|
|
1372
1493
|
}): Promise<{
|
|
1373
1494
|
taskId: string;
|
|
1374
1495
|
} | null>;
|
|
@@ -1551,8 +1672,8 @@ export declare class QuorumLoop {
|
|
|
1551
1672
|
* `handleReviseFeedback` so the revise implementor does not re-derive its
|
|
1552
1673
|
* own reasoning. Appended to the STDIN payload ONLY (self-visibility) —
|
|
1553
1674
|
* NEVER to `args.brief`, which becomes the execute-first `task_brief`
|
|
1554
|
-
* rendered into the reviewer prompts (OQ-REVIEWER-RATIONALE:
|
|
1555
|
-
* see NO rationale
|
|
1675
|
+
* rendered into the reviewer prompts (OQ-REVIEWER-RATIONALE: reviewers
|
|
1676
|
+
* see NO rationale — permanent diff-only review policy invariant).
|
|
1556
1677
|
*/
|
|
1557
1678
|
priorRationale?: {
|
|
1558
1679
|
round: number;
|
|
@@ -1821,6 +1942,27 @@ export declare class QuorumLoop {
|
|
|
1821
1942
|
* half-applied tree.
|
|
1822
1943
|
*/
|
|
1823
1944
|
promoteShadow(taskId: string): Promise<void>;
|
|
1945
|
+
/** P46a C2 — start every planned automatic retry as a new linked task. */
|
|
1946
|
+
private drainPromoteRetries;
|
|
1947
|
+
/** P46a D2 — correct a task's recorded outcome after its terminal cleanup ran. */
|
|
1948
|
+
private markTaskOutcome;
|
|
1949
|
+
/**
|
|
1950
|
+
* P46a C1 — classify each conflicting path: `session-task` when its current
|
|
1951
|
+
* real-tree metadata equals a post-image a single-task promote of THIS
|
|
1952
|
+
* session recorded (`promotedByPath`), else `external`.
|
|
1953
|
+
*/
|
|
1954
|
+
private attributeConflicts;
|
|
1955
|
+
/**
|
|
1956
|
+
* P46a C2 — the retry brief: the original request, a "Files changed since
|
|
1957
|
+
* your first attempt" section (a unified diff from the failed task's REVIEWED
|
|
1958
|
+
* contents to the CURRENT real contents, per conflicting path, naming the
|
|
1959
|
+
* session task that changed it), and the reviewed contents themselves. Every
|
|
1960
|
+
* section is capped (`RETRY_BRIEF_SECTION_CAP` per path,
|
|
1961
|
+
* `RETRY_BRIEF_TOTAL_CAP` overall — the brief becomes the retry task's
|
|
1962
|
+
* durable `task_spec`, whose write is fire-and-forget) and secret-scrubbed
|
|
1963
|
+
* (`redactSecretShapesInText`) before insertion.
|
|
1964
|
+
*/
|
|
1965
|
+
private buildRetryBrief;
|
|
1824
1966
|
/**
|
|
1825
1967
|
* CP-12 W2.b (§3.C.2b (d) / H3-4) — promote-quiescence BARRIER for `taskId`.
|
|
1826
1968
|
* Enqueues an EMPTY critical section behind any in-flight shadow lifecycle op
|
|
@@ -1951,8 +2093,7 @@ export declare class QuorumLoop {
|
|
|
1951
2093
|
* path (that defeats the moat).
|
|
1952
2094
|
*
|
|
1953
2095
|
* TRI-STATE (decided here, mirroring the implementor LE):
|
|
1954
|
-
* 1. No engager wired
|
|
1955
|
-
* DEFAULTS ON — R7 A4) → LEGACY (byte-identical non-regression). No badge.
|
|
2096
|
+
* 1. No engager wired → LEGACY (byte-identical non-regression). No badge.
|
|
1956
2097
|
* 1b. No resolvable taskId (cannot scope a per-task broker) → LEGACY + a
|
|
1957
2098
|
* reduced-trust badge (Stage-2 r1 Codex LOW — a trust-downgrade must be
|
|
1958
2099
|
* VISIBLE, never a silent ambient-cred fallback; see
|
|
@@ -1999,7 +2140,7 @@ export declare class QuorumLoop {
|
|
|
1999
2140
|
private describeReviewShapeForDiagnostics;
|
|
2000
2141
|
/**
|
|
2001
2142
|
* Wave B §2.1 confinement TRI-STATE for a merge-gate model/reviewer invocation
|
|
2002
|
-
* (LOCK #C14-MOAT). Path A: the CP-7 substrate/broker (
|
|
2143
|
+
* (LOCK #C14-MOAT). Path A: the CP-7 substrate/broker (a Trusted
|
|
2003
2144
|
* agent + engage succeeds → a handle; no ambient vendor cred in the child). Path B: a
|
|
2004
2145
|
* trusted-container boundary (legacy spawn confined by the OUTER container — the
|
|
2005
2146
|
* dogfood/E2E path). Path C: neither → NOT confined. A path-A engage that
|
|
@@ -2043,13 +2184,11 @@ export declare class QuorumLoop {
|
|
|
2043
2184
|
* unwired, keeping today's IMMEDIATE legacy human-gate instead of
|
|
2044
2185
|
* converting it into a per-slot spawn-time fail-close.
|
|
2045
2186
|
*
|
|
2046
|
-
* Deliberately DECOUPLED from `engageWaveBConfinement`
|
|
2047
|
-
*
|
|
2048
|
-
*
|
|
2049
|
-
*
|
|
2050
|
-
*
|
|
2051
|
-
* The ladder select is side-effect-free (no launch, no broker); test seams
|
|
2052
|
-
* via `deps.resolverProbeDeps`.
|
|
2187
|
+
* Deliberately DECOUPLED from `engageWaveBConfinement` reviewer sandboxing:
|
|
2188
|
+
* that mechanism gates REVIEWER sandboxing (per-seat, `makeConflictModelCaller`,
|
|
2189
|
+
* Tier-2) — coupling it here made the A1d resolver row unreachable on the
|
|
2190
|
+
* default bare host. The ladder select is side-effect-free (no launch, no broker);
|
|
2191
|
+
* test seams via `deps.resolverProbeDeps`.
|
|
2053
2192
|
*/
|
|
2054
2193
|
private probeResolverDispatchConfinement;
|
|
2055
2194
|
/**
|
|
@@ -2063,11 +2202,9 @@ export declare class QuorumLoop {
|
|
|
2063
2202
|
* MED): `probeResolverDispatchConfinement` wires the closure iff the
|
|
2064
2203
|
* DISPATCH-time engage could establish a confining substrate on this
|
|
2065
2204
|
* host (a real §6 Q2 ladder tier, or the preserved trusted-container
|
|
2066
|
-
* posture). Deliberately DECOUPLED from `engageWaveBConfinement`
|
|
2067
|
-
*
|
|
2068
|
-
*
|
|
2069
|
-
* sandboxing (seat/`makeConflictModelCaller`/Tier-2, unchanged), and
|
|
2070
|
-
* riding it here made the A1d write-confined resolver row unreachable
|
|
2205
|
+
* posture). Deliberately DECOUPLED from `engageWaveBConfinement` — that
|
|
2206
|
+
* mechanism gates REVIEWER sandboxing (seat/`makeConflictModelCaller`/Tier-2),
|
|
2207
|
+
* and coupling it here made the A1d write-confined resolver row unreachable
|
|
2071
2208
|
* on the default bare-host path. Unwired → return `null` →
|
|
2072
2209
|
* `resolveAgentic` is NOT set on the context → a fresh class-2 conflict
|
|
2073
2210
|
* takes the legacy `caller` path (which on path C is the
|
|
@@ -2143,9 +2280,12 @@ export declare class QuorumLoop {
|
|
|
2143
2280
|
private submitVerdict;
|
|
2144
2281
|
/**
|
|
2145
2282
|
* On WS (re)connect/startup, poll for the seats assigned to this desktop for
|
|
2146
|
-
* any in_review gate of
|
|
2147
|
-
*
|
|
2148
|
-
*
|
|
2283
|
+
* any in_review gate of EVERY in-flight task (P46a B3: the live single tasks,
|
|
2284
|
+
* the tasks with an active implementor, and the registered team tracks — one
|
|
2285
|
+
* query each) and spawn any seat NEITHER already running-in-memory NOR already
|
|
2286
|
+
* verdict-submitted (double-guard). Without this, a REVIEWER_DISPATCH dropped
|
|
2287
|
+
* during a WS gap hangs the gate forever. Residual (unchanged): after a full
|
|
2288
|
+
* desktop restart the in-memory maps are empty.
|
|
2149
2289
|
*/
|
|
2150
2290
|
recoverInReviewAssignments(): Promise<void>;
|
|
2151
2291
|
/**
|
|
@@ -2333,17 +2473,37 @@ export declare class QuorumLoop {
|
|
|
2333
2473
|
*/
|
|
2334
2474
|
private reconstructRound0GateDispatch;
|
|
2335
2475
|
private handleReviseFeedback;
|
|
2336
|
-
/** The implementor agent the loop spawns (set at start_task). */
|
|
2337
|
-
private activeImplementorAgent;
|
|
2338
|
-
setActiveImplementorAgent(agent: AgentKind): void;
|
|
2339
2476
|
/**
|
|
2340
|
-
*
|
|
2341
|
-
*
|
|
2342
|
-
*
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2477
|
+
* P46a B1 — set a single task's implementor agent on ITS record (the only
|
|
2478
|
+
* caller is `resumeFromContinuation`, after the user chose a target agent).
|
|
2479
|
+
* Replaces the session-wide `setActiveImplementorAgent` singleton.
|
|
2480
|
+
*/
|
|
2481
|
+
private setTaskImplementorAgent;
|
|
2482
|
+
/**
|
|
2483
|
+
* #585 #C10M-9 / P46a B1 (OQ-1, decided) — resolve WHICH single task a
|
|
2484
|
+
* `/continue request` means: the FOCUSED task if it has an active implementor
|
|
2485
|
+
* round; else the single task that has one; else refuse — `ambiguous` lists
|
|
2486
|
+
* the candidates (the shell renders their `#n` so the user can
|
|
2487
|
+
* `/task focus <n>` first), `none` means no task is running a round. The
|
|
2488
|
+
* `gateId`/`roundNumber` come from the ACTIVE implementor registry (the round
|
|
2489
|
+
* currently running); the brief + source agent from the task's own record.
|
|
2346
2490
|
*/
|
|
2491
|
+
resolveContinuationRequest(): {
|
|
2492
|
+
kind: 'ok';
|
|
2493
|
+
ctx: {
|
|
2494
|
+
taskId: string;
|
|
2495
|
+
gateId: string;
|
|
2496
|
+
roundNumber: number;
|
|
2497
|
+
brief: string;
|
|
2498
|
+
sourceAgent: AgentKind;
|
|
2499
|
+
};
|
|
2500
|
+
} | {
|
|
2501
|
+
kind: 'ambiguous';
|
|
2502
|
+
candidates: string[];
|
|
2503
|
+
} | {
|
|
2504
|
+
kind: 'none';
|
|
2505
|
+
};
|
|
2506
|
+
/** The `ok` projection of {@link resolveContinuationRequest} (null otherwise). */
|
|
2347
2507
|
getActiveContinuationRequestContext(): {
|
|
2348
2508
|
taskId: string;
|
|
2349
2509
|
gateId: string;
|
|
@@ -2605,8 +2765,12 @@ export declare class QuorumLoop {
|
|
|
2605
2765
|
get _runningSeatsForTests(): ReadonlySet<string>;
|
|
2606
2766
|
/** @internal — test introspection. */
|
|
2607
2767
|
get _submittedSeatsForTests(): ReadonlySet<string>;
|
|
2608
|
-
/**
|
|
2609
|
-
|
|
2768
|
+
/**
|
|
2769
|
+
* @internal — test seam to register a single task (its record + focus)
|
|
2770
|
+
* without start_task. P46a B1: the record is what every reader resolves, so
|
|
2771
|
+
* the seam always creates one (an empty brief when none is given).
|
|
2772
|
+
*/
|
|
2773
|
+
_setActiveTaskForTests(taskId: string, brief?: string, agent?: AgentKind, gateIds?: string[]): void;
|
|
2610
2774
|
/** @internal — read a task's accumulated binding user notes. */
|
|
2611
2775
|
_userNotesForTests(taskId: string): readonly string[];
|
|
2612
2776
|
/** @internal — A1b: read a task's accumulated structured findings history. */
|