@ordewell/core 0.7.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{IFileSystem-DgpX0BU7.d.mts → IFileSystem-BnLh-_SK.d.mts} +1 -1
- package/dist/{IFileSystem-D4ADfTrX.d.ts → IFileSystem-DofiRcCo.d.ts} +1 -1
- package/dist/{ModeResolver-Cv01ZDd9.d.mts → ModeResolver-DZzJSdIU.d.mts} +1 -1
- package/dist/{ModeResolver-BEcRAz1c.d.ts → ModeResolver-DkMYf4uS.d.ts} +1 -1
- package/dist/{Task-CoKhvBa1.d.mts → Task-BnLxkVQF.d.mts} +140 -21
- package/dist/{Task-CoKhvBa1.d.ts → Task-BnLxkVQF.d.ts} +140 -21
- package/dist/{chunk-YU4UKKKI.mjs → chunk-LGQNXPBX.mjs} +10 -2
- package/dist/chunk-LGQNXPBX.mjs.map +1 -0
- package/dist/{chunk-N66ZHFGN.mjs → chunk-OYUSADFM.mjs} +11 -1
- package/dist/chunk-OYUSADFM.mjs.map +1 -0
- package/dist/{chunk-HPNUFBIT.mjs → chunk-V3JHS7AX.mjs} +9 -1
- package/dist/chunk-V3JHS7AX.mjs.map +1 -0
- package/dist/{chunk-LSGY7AIZ.mjs → chunk-Y36NIASW.mjs} +183 -11
- package/dist/chunk-Y36NIASW.mjs.map +1 -0
- package/dist/{chunk-J3YSTPCE.mjs → chunk-ZV5LDNCO.mjs} +5 -4
- package/dist/chunk-ZV5LDNCO.mjs.map +1 -0
- package/dist/index.d.mts +287 -223
- package/dist/index.d.ts +287 -223
- package/dist/index.js +2111 -1086
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1973 -1117
- package/dist/index.mjs.map +1 -1
- package/dist/order-labels.d.mts +15 -2
- package/dist/order-labels.d.ts +15 -2
- package/dist/order-labels.js +12 -2
- package/dist/order-labels.js.map +1 -1
- package/dist/order-labels.mjs +7 -3
- package/dist/{parsing-B4OCHH1_.d.mts → parsing-B6ctfF80.d.mts} +2 -2
- package/dist/{parsing-DMdOq-BV.d.ts → parsing-ddZXZFP4.d.ts} +2 -2
- package/dist/parsing.d.mts +3 -3
- package/dist/parsing.d.ts +3 -3
- package/dist/parsing.js +6 -3
- package/dist/parsing.js.map +1 -1
- package/dist/parsing.mjs +3 -3
- package/dist/{plan-utils-BdYPRBno.d.ts → plan-utils--kQRzSE-.d.ts} +226 -7
- package/dist/{plan-utils-CD1Xu65s.d.mts → plan-utils-CKgNtDwQ.d.mts} +226 -7
- package/dist/plan-utils.d.mts +4 -3
- package/dist/plan-utils.d.ts +4 -3
- package/dist/plan-utils.js +202 -3
- package/dist/plan-utils.js.map +1 -1
- package/dist/plan-utils.mjs +40 -3
- package/dist/testing.d.mts +17 -5
- package/dist/testing.d.ts +17 -5
- package/dist/testing.js +45 -2
- package/dist/testing.js.map +1 -1
- package/dist/testing.mjs +45 -4
- package/dist/testing.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-HPNUFBIT.mjs.map +0 -1
- package/dist/chunk-J3YSTPCE.mjs.map +0 -1
- package/dist/chunk-LSGY7AIZ.mjs.map +0 -1
- package/dist/chunk-N66ZHFGN.mjs.map +0 -1
- package/dist/chunk-YU4UKKKI.mjs.map +0 -1
package/dist/testing.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/testing.ts"],"sourcesContent":["import type { IConfig } from './interfaces/IConfig';\nimport type { IFileSystem, ToolOutcome } from './interfaces/IFileSystem';\nimport type { ITerminalSession, QueuedTaskMessage, StructuredEvent, StructuredSessionCapability, StructuredTurnEnd } from './interfaces/ITerminalRunner';\nimport type { ApprovalDecision } from './interfaces/IApproval';\nimport type { CheckpointAnswer, TaskCompleteArgs } from './services/mcp/tools';\nimport type {\n IsolationAvailability,\n IsolationHandoff,\n IsolationMergeResult,\n IsolationOutcome,\n IsolationPruneResult,\n IsolationRun,\n IntegrationDisposal,\n PreparedTask,\n IWorktreeIsolation,\n RepairEvidence,\n TreeSnapshot,\n} from './interfaces/IWorktreeIsolation';\nimport type { Task } from './models/Task';\nimport { handoffOf, integrationBranchFor, SELF_REPO } from './services/isolationRecord';\n\n/**\n * Let an already-queued promise chain run to its next await before asserting,\n * without a wall-clock sleep. For a chain whose length is not known, drain the\n * microtask queue repeatedly. Only helps a chain that does not wait on a timer.\n */\nexport async function flushMicrotasks(rounds = 20): Promise<void> {\n for (let i = 0; i < rounds; i += 1) await Promise.resolve();\n}\n\nexport function fakeConfig(overrides: Partial<IConfig> = {}): IConfig {\n return {\n aiProvider: 'openrouter',\n apiKey: 'sk-test',\n planningModel: 'test-model',\n enabledRunners: ['claude-code'],\n maxParallelSessions: 3,\n researchEnabled: false,\n researchMaxSteps: 10,\n researchMaxFileSize: 100_000,\n openAiBaseUrl: 'https://api.openai.com/v1',\n openAiApiKey: '',\n openrouterKey: '',\n geminiKey: '',\n openaiCompatibleBaseUrl: '',\n openaiCompatibleApiKey: '',\n orchestratorModel: '',\n researchSubagentModel: '',\n geminiModel: '',\n planMapEnabled: true,\n autonomousMode: true,\n // Off so an orchestrator built without an injected isolation never runs\n // real git against whatever repository the tests happen to run in.\n worktreeIsolation: false,\n workspaceRepos: [],\n worktreeLinks: [],\n // Off so a scripted conflict stays a conflict unless a test opts into repairing it.\n conflictRepairAttempts: 0,\n approvalMode: 'ask',\n approvalPreApproved: [],\n setProviderModelLists: () => {},\n getProviderBaseUrl: () => '',\n getProviderApiKey: () => '',\n ...overrides,\n };\n}\n\nconst EMPTY_OUTCOME: ToolOutcome = { success: false, output: '', truncated: false };\n\n/**\n * A complete {@link IFileSystem} stub. Lives here rather than in each package's\n * test folder so adding a tool to the interface is one edit, not one per suite.\n */\nexport function fakeFileSystem(overrides: Partial<IFileSystem> = {}): IFileSystem {\n return {\n readFile: async () => EMPTY_OUTCOME,\n readFiles: async () => EMPTY_OUTCOME,\n glob: async () => EMPTY_OUTCOME,\n grep: async () => EMPTY_OUTCOME,\n findSymbol: async () => EMPTY_OUTCOME,\n listDir: async () => EMPTY_OUTCOME,\n bash: async () => EMPTY_OUTCOME,\n getWorkspaceRoot: () => '/workspace',\n ...overrides,\n };\n}\n\nexport class FakeTerminalSession implements ITerminalSession {\n private outputCbs: Array<(text: string) => void> = [];\n private exitCbs: Array<(code: number) => void> = [];\n output = '';\n written: string[] = [];\n killed = false;\n\n constructor(public id = 's1', public taskId = 't1') {}\n\n onOutput(cb: (text: string) => void): void { this.outputCbs.push(cb); }\n onExit(cb: (code: number) => void): void { this.exitCbs.push(cb); }\n kill(): void { this.killed = true; }\n getOutput(): string { return this.output; }\n write(text: string): void { this.written.push(text); }\n\n emitOutput(text: string): void {\n this.output += text;\n for (const cb of this.outputCbs) cb(text);\n }\n emitExit(code: number): void {\n for (const cb of this.exitCbs) cb(code);\n }\n}\n\n/**\n * A {@link FakeTerminalSession} that is feature-detected as structured\n * (ADR-0018): the turn, queue and native-session calls a test drives, with\n * no protocol behind them. It queues and delivers as `StructuredSession`\n * does — a message to an idle session starts a turn at once, one sent\n * mid-turn goes out as that turn ends, without passing through idle.\n */\nexport class FakeStructuredSession extends FakeTerminalSession implements StructuredSessionCapability {\n readonly transport = 'structured' as const;\n state: 'working' | 'idle' = 'working';\n messages: QueuedTaskMessage[] = [];\n /** Every message a turn was started with, in order. */\n delivered: string[] = [];\n interrupts = 0;\n private messageCount = 0;\n private turnEndCbs: Array<(reason: StructuredTurnEnd) => void> = [];\n private eventCbs: Array<(event: StructuredEvent) => void> = [];\n private completeCbs: Array<(report: TaskCompleteArgs) => void> = [];\n private checkpointHandler: ((question: string, signal: AbortSignal) => Promise<CheckpointAnswer>) | null = null;\n\n constructor(id = 's1', taskId = 't1', public sessionId: string | null = 'native-1') {\n super(id, taskId);\n }\n\n override write(text: string): void {\n super.write(text);\n const message = text.trim();\n if (message) this.sendMessage(message);\n }\n\n turnState(): 'working' | 'idle' { return this.state; }\n onTurnEnd(cb: (reason: StructuredTurnEnd) => void): void { this.turnEndCbs.push(cb); }\n onEvent(cb: (event: StructuredEvent) => void): void { this.eventCbs.push(cb); }\n onTaskComplete(cb: (report: TaskCompleteArgs) => void): void { this.completeCbs.push(cb); }\n /** The runner calls `task_complete`, as `StructuredSession` relays it. */\n reportComplete(report: TaskCompleteArgs): void {\n for (const cb of this.completeCbs) cb(report);\n }\n onToolCheckpoint(handler: (question: string, signal: AbortSignal) => Promise<CheckpointAnswer>): void { this.checkpointHandler = handler; }\n /** The runner calls `checkpoint`, as `StructuredSession` relays it; settles with the answer. */\n callCheckpoint(question: string, signal: AbortSignal = new AbortController().signal): Promise<CheckpointAnswer> {\n if (!this.checkpointHandler) throw new Error('no checkpoint handler attached');\n return this.checkpointHandler(question, signal);\n }\n sendMessage(text: string): string {\n this.messageCount += 1;\n const id = `msg-${this.messageCount}`;\n if (this.state === 'idle') this.deliver(text);\n else this.messages.push({ id, text });\n return id;\n }\n removeQueued(id: string): boolean {\n const before = this.messages.length;\n this.messages = this.messages.filter((m) => m.id !== id);\n return this.messages.length < before;\n }\n queued(): QueuedTaskMessage[] { return this.messages.map((m) => ({ ...m })); }\n async interrupt(): Promise<void> {\n this.interrupts += 1;\n if (this.state === 'working') this.emitTurnEnd('interrupted');\n }\n nativeSessionId(): string | null { return this.sessionId; }\n\n /** Every answer this session was given, in order. */\n answers: Array<{ id: string; decision: ApprovalDecision }> = [];\n private readonly openPermissions = new Set<string>();\n\n /** The runner asks to use a tool, as `StructuredSession` announces it. */\n requestPermission(id: string, name: string, input: Record<string, unknown>, suggestions: unknown[] = []): void {\n this.openPermissions.add(id);\n this.emitEvent({ type: 'permission_request', id, name, detail: JSON.stringify(input), input, suggestions });\n }\n /** The runner gives up on a request, as an interrupt makes it. */\n withdrawPermission(id: string): void {\n if (this.openPermissions.delete(id)) this.emitEvent({ type: 'permission_withdrawn', id });\n }\n answerPermission(id: string, decision: ApprovalDecision): boolean {\n if (!this.openPermissions.delete(id)) return false;\n this.answers.push({ id, decision });\n this.emitEvent({ type: 'permission_decided', id, decision });\n return true;\n }\n\n emitEvent(event: StructuredEvent): void {\n for (const cb of this.eventCbs) cb(event);\n }\n emitTurnEnd(reason: StructuredTurnEnd): void {\n const next = this.messages.shift();\n if (!next) this.state = 'idle';\n for (const cb of this.turnEndCbs) cb(reason);\n if (next) this.deliver(next.text);\n }\n\n private deliver(text: string): void {\n this.state = 'working';\n this.delivered.push(text);\n this.emitEvent({ type: 'turn_start', text });\n }\n}\n\nexport type FakeIsolationCall =\n | { op: 'isActive'; workspaceRoot: string }\n | { op: 'stash'; workspaceRoot: string }\n | { op: 'startRun'; workspaceRoot: string }\n | { op: 'prepare' | 'reopen' | 'verifyRepair'; taskId: string }\n | { op: 'integrate'; taskId: string }\n | { op: 'release'; taskId: string; keep: boolean }\n | { op: 'handoff' | 'pruneOrphans' | 'reviewDiff' | 'mergeIntoCheckedOut' | 'sweep' | 'findInHead' | 'snapshotTree' | 'changedSince' }\n | { op: 'discard'; integration: IntegrationDisposal };\n\n/**\n * An in-memory {@link IWorktreeIsolation} for scheduling tests: no git, no\n * filesystem. Every call is logged in `calls`; `prepare` hands back a\n * deterministic fake cwd. Set `availability` to exercise the fallbacks, `outcomes`\n * to script a conflict, and `holdIntegration` to keep a task un-integrated so a\n * test can observe that its dependents wait. `repos` makes the run a group of\n * several; `changes` and `stopsIn` say which of them a task changes and where\n * its landing stops. `repairEvidence` scripts what a conflict repair's\n * evidence check finds.\n */\nexport class FakeWorktreeIsolation implements IWorktreeIsolation {\n availability: IsolationAvailability = { active: true };\n /** The repo paths `startRun` groups: a group of one at `.` unless set. */\n repos: string[] = [SELF_REPO];\n /** Per task id, the repos it changes; every repo of the group when not listed. */\n changes = new Map<string, string[]>();\n /** Per task id, the repo its landing stops in when its outcome is not `merged`; its first changed repo when not listed. */\n stopsIn = new Map<string, string>();\n /** Per task id, the files a `conflict` outcome names; empty when not listed. */\n conflictFiles = new Map<string, string[]>();\n /** What `mergeIntoCheckedOut` answers; a `merged` one also puts every landed task in HEAD, as git would. */\n mergeResult: IsolationMergeResult = { outcome: 'merged' };\n /** Task ids whose landed work `findInHead` finds in HEAD besides those a merge put there, as a merge by hand would. */\n mergedByHand = new Set<string>();\n /** What `snapshotTree` answers; null as for a workspace with no repo. */\n treeSnapshot: TreeSnapshot | null = {};\n /** What `changedSince` answers: the tracked files an ops task changed. */\n changedFiles: string[] = [];\n /** What `startRun` shares and `prepare` copies, to exercise their notices. */\n shared: string[] = [];\n sharedRepos: string[] = [];\n copied: string[] = [];\n /** Set to make `startRun` throw, as git does when no repo of the group can be isolated. */\n startRunError: Error | null = null;\n /** Set to make `discard` / `sweep` throw after logging the call. */\n discardError: Error | null = null;\n sweepError: Error | null = null;\n /** What `pruneOrphans` reports as kept back from the sweep. */\n keptOnPrune: IsolationPruneResult['kept'] = [];\n /** Per task id; a task not listed integrates as `merged`. */\n outcomes = new Map<string, IsolationOutcome>();\n /** Per task id, what `verifyRepair` finds; a task not listed passes. */\n repairEvidence = new Map<string, RepairEvidence>();\n calls: FakeIsolationCall[] = [];\n private holds = new Map<string, Promise<void>>();\n private runCount = 0;\n\n private log(call: FakeIsolationCall): void { this.calls.push(call); }\n\n /** Task ids in the order `op` was called for them. */\n taskIdsFor(op: 'prepare' | 'reopen' | 'verifyRepair' | 'integrate' | 'release'): string[] {\n return this.calls.flatMap((c) => (c.op === op && 'taskId' in c ? [c.taskId] : []));\n }\n\n /** Make `integrate` for this task wait until the returned function is called. */\n holdIntegration(taskId: string): () => void {\n let open!: () => void;\n this.holds.set(taskId, new Promise<void>((resolve) => { open = resolve; }));\n return open;\n }\n\n async isActive(workspaceRoot: string): Promise<IsolationAvailability> {\n this.log({ op: 'isActive', workspaceRoot });\n return this.availability;\n }\n\n /** Like git: once the tracked changes are stashed, the tree is no longer dirty. */\n async stash(workspaceRoot: string): Promise<void> {\n this.log({ op: 'stash', workspaceRoot });\n if (!this.availability.active && this.availability.reason === 'dirty') this.availability = { active: true };\n }\n\n async startRun(workspaceRoot: string): Promise<IsolationRun> {\n this.log({ op: 'startRun', workspaceRoot });\n if (this.startRunError) throw this.startRunError;\n const id = `run${++this.runCount}`;\n return {\n id,\n workspaceRoot,\n repos: this.repos.map((repo) => ({\n path: repo, root: `${workspaceRoot}/${repo}`.replace(/\\/\\.$/, ''), baseRef: 'base0000', baseBranch: 'main', integrationBranch: integrationBranchFor(id),\n })),\n shared: [...this.shared],\n sharedRepos: [...this.sharedRepos],\n tasks: {},\n };\n }\n\n async prepare(task: Task, run: IsolationRun): Promise<PreparedTask> {\n this.log({ op: 'prepare', taskId: task.id });\n const name = `${task.order}-${task.id}`;\n const cwd = `/fake-worktrees/${run.id}/${name}`;\n const branch = `ordewell/${run.id}/${name}`;\n run.tasks[task.id] = {\n taskId: task.id, order: task.order, title: task.title, branch, workspace: cwd, status: 'active',\n repos: Object.fromEntries(run.repos.map((r) => [r.path, { worktree: r.path === SELF_REPO ? cwd : `${cwd}/${r.path}`, linked: [] }])),\n };\n return { cwd, branch, copied: [...this.copied] };\n }\n\n /** Like git: the same cwd, each changed repo's tip recorded, the repair counted. */\n async reopen(task: Task, run: IsolationRun): Promise<PreparedTask> {\n this.log({ op: 'reopen', taskId: task.id });\n const record = run.tasks[task.id];\n if (record?.status !== 'conflict') throw new Error(`Task ${task.order} has no conflict to repair`);\n const changed = Object.entries(record.repos).filter(([repo, entry]) => entry.changed || repo === record.conflictRepo).map(([repo]) => repo);\n const files = (record.conflictFiles ?? []).map((file) => (record.conflictRepo && record.conflictRepo !== SELF_REPO ? `${record.conflictRepo}/${file}` : file));\n record.repairs = (record.repairs ?? 0) + 1;\n record.repairBase = Object.fromEntries(changed.map((repo) => [repo, `tip-${repo}`]));\n record.repairedFiles = [...new Set([...(record.repairedFiles ?? []), ...files])];\n record.status = 'repairing';\n return { cwd: record.workspace, branch: record.branch, copied: [] };\n }\n\n async verifyRepair(task: Task, _run: IsolationRun): Promise<RepairEvidence> {\n this.log({ op: 'verifyRepair', taskId: task.id });\n return this.repairEvidence.get(task.id) ?? { ok: true };\n }\n\n /** Like git: the landing is recorded and persisted before the (held) merge, and cleared once it settles. */\n async integrate(task: Task, run: IsolationRun, persist: () => void = () => undefined): Promise<IsolationOutcome> {\n this.log({ op: 'integrate', taskId: task.id });\n const record = run.tasks[task.id];\n if (!record) return 'failed';\n const changed = this.changes.get(task.id) ?? run.repos.map((r) => r.path);\n for (const [repo, entry] of Object.entries(record.repos)) entry.changed = changed.includes(repo) || (entry.changed ?? false);\n if (changed.length > 0) {\n run.landing = { taskId: task.id, tips: Object.fromEntries(changed.map((repo) => [repo, `tip-${repo}`])) };\n persist();\n }\n await this.holds.get(task.id);\n delete run.landing;\n const outcome = this.outcomes.get(task.id) ?? 'merged';\n record.status = outcome;\n delete record.repairBase;\n if (outcome === 'merged') {\n delete record.conflictRepo;\n delete record.conflictFiles;\n } else {\n record.conflictRepo = this.stopsIn.get(task.id) ?? changed[0] ?? SELF_REPO;\n const files = this.conflictFiles.get(task.id);\n if (files) record.conflictFiles = files;\n else delete record.conflictFiles;\n }\n return outcome;\n }\n\n async release(run: IsolationRun, taskId: string, opts: { keep: boolean }): Promise<void> {\n this.log({ op: 'release', taskId, keep: opts.keep });\n const record = run.tasks[taskId];\n if (!opts.keep) delete run.tasks[taskId];\n else if (record?.status === 'active') record.status = 'kept';\n else if (record?.status === 'repairing') {\n record.status = 'conflict';\n delete record.repairBase;\n }\n }\n\n async handoff(run: IsolationRun): Promise<IsolationHandoff> {\n this.log({ op: 'handoff' });\n return handoffOf(run);\n }\n\n async pruneOrphans(): Promise<IsolationPruneResult> {\n this.log({ op: 'pruneOrphans' });\n return { kept: [...this.keptOnPrune] };\n }\n async reviewDiff(): Promise<string> { this.log({ op: 'reviewDiff' }); return ''; }\n async mergeIntoCheckedOut(run: IsolationRun): Promise<IsolationMergeResult> {\n this.log({ op: 'mergeIntoCheckedOut' });\n if (this.mergeResult.outcome === 'merged') {\n for (const record of Object.values(run.tasks)) if (record.status === 'merged') this.mergedByHand.add(record.taskId);\n }\n return this.mergeResult;\n }\n async findInHead(run: IsolationRun): Promise<string[]> {\n this.log({ op: 'findInHead' });\n const found: string[] = [];\n for (const record of Object.values(run.tasks)) {\n if (record.status !== 'merged' || record.inHead || !this.mergedByHand.has(record.taskId)) continue;\n record.inHead = true;\n found.push(record.taskId);\n }\n return found;\n }\n async snapshotTree(): Promise<TreeSnapshot | null> { this.log({ op: 'snapshotTree' }); return this.treeSnapshot; }\n async changedSince(): Promise<string[]> { this.log({ op: 'changedSince' }); return [...this.changedFiles]; }\n async discard(_run: IsolationRun, opts: { integration: IntegrationDisposal }): Promise<void> {\n this.log({ op: 'discard', integration: opts.integration });\n if (this.discardError) throw this.discardError;\n }\n async sweep(): Promise<void> {\n this.log({ op: 'sweep' });\n if (this.sweepError) throw this.sweepError;\n }\n}\n"],"mappings":";;;;;;;AA0BA,eAAsB,gBAAgB,SAAS,IAAmB;AAChE,WAAS,IAAI,GAAG,IAAI,QAAQ,KAAK,EAAG,OAAM,QAAQ,QAAQ;AAC5D;AAEO,SAAS,WAAW,YAA8B,CAAC,GAAY;AACpE,SAAO;AAAA,IACL,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,eAAe;AAAA,IACf,gBAAgB,CAAC,aAAa;AAAA,IAC9B,qBAAqB;AAAA,IACrB,iBAAiB;AAAA,IACjB,kBAAkB;AAAA,IAClB,qBAAqB;AAAA,IACrB,eAAe;AAAA,IACf,cAAc;AAAA,IACd,eAAe;AAAA,IACf,WAAW;AAAA,IACX,yBAAyB;AAAA,IACzB,wBAAwB;AAAA,IACxB,mBAAmB;AAAA,IACnB,uBAAuB;AAAA,IACvB,aAAa;AAAA,IACb,gBAAgB;AAAA,IAChB,gBAAgB;AAAA;AAAA;AAAA,IAGhB,mBAAmB;AAAA,IACnB,gBAAgB,CAAC;AAAA,IACjB,eAAe,CAAC;AAAA;AAAA,IAEhB,wBAAwB;AAAA,IACxB,cAAc;AAAA,IACd,qBAAqB,CAAC;AAAA,IACtB,uBAAuB,MAAM;AAAA,IAAC;AAAA,IAC9B,oBAAoB,MAAM;AAAA,IAC1B,mBAAmB,MAAM;AAAA,IACzB,GAAG;AAAA,EACL;AACF;AAEA,IAAM,gBAA6B,EAAE,SAAS,OAAO,QAAQ,IAAI,WAAW,MAAM;AAM3E,SAAS,eAAe,YAAkC,CAAC,GAAgB;AAChF,SAAO;AAAA,IACL,UAAU,YAAY;AAAA,IACtB,WAAW,YAAY;AAAA,IACvB,MAAM,YAAY;AAAA,IAClB,MAAM,YAAY;AAAA,IAClB,YAAY,YAAY;AAAA,IACxB,SAAS,YAAY;AAAA,IACrB,MAAM,YAAY;AAAA,IAClB,kBAAkB,MAAM;AAAA,IACxB,GAAG;AAAA,EACL;AACF;AAEO,IAAM,sBAAN,MAAsD;AAAA,EAO3D,YAAmB,KAAK,MAAa,SAAS,MAAM;AAAjC;AAAkB;AAAA,EAAgB;AAAA,EAAlC;AAAA,EAAkB;AAAA,EAN7B,YAA2C,CAAC;AAAA,EAC5C,UAAyC,CAAC;AAAA,EAClD,SAAS;AAAA,EACT,UAAoB,CAAC;AAAA,EACrB,SAAS;AAAA,EAIT,SAAS,IAAkC;AAAE,SAAK,UAAU,KAAK,EAAE;AAAA,EAAG;AAAA,EACtE,OAAO,IAAkC;AAAE,SAAK,QAAQ,KAAK,EAAE;AAAA,EAAG;AAAA,EAClE,OAAa;AAAE,SAAK,SAAS;AAAA,EAAM;AAAA,EACnC,YAAoB;AAAE,WAAO,KAAK;AAAA,EAAQ;AAAA,EAC1C,MAAM,MAAoB;AAAE,SAAK,QAAQ,KAAK,IAAI;AAAA,EAAG;AAAA,EAErD,WAAW,MAAoB;AAC7B,SAAK,UAAU;AACf,eAAW,MAAM,KAAK,UAAW,IAAG,IAAI;AAAA,EAC1C;AAAA,EACA,SAAS,MAAoB;AAC3B,eAAW,MAAM,KAAK,QAAS,IAAG,IAAI;AAAA,EACxC;AACF;AASO,IAAM,wBAAN,cAAoC,oBAA2D;AAAA,EAapG,YAAY,KAAK,MAAM,SAAS,MAAa,YAA2B,YAAY;AAClF,UAAM,IAAI,MAAM;AAD2B;AAAA,EAE7C;AAAA,EAF6C;AAAA,EAZpC,YAAY;AAAA,EACrB,QAA4B;AAAA,EAC5B,WAAgC,CAAC;AAAA;AAAA,EAEjC,YAAsB,CAAC;AAAA,EACvB,aAAa;AAAA,EACL,eAAe;AAAA,EACf,aAAyD,CAAC;AAAA,EAC1D,WAAoD,CAAC;AAAA,EACrD,cAAyD,CAAC;AAAA,EAC1D,oBAAmG;AAAA,EAMlG,MAAM,MAAoB;AACjC,UAAM,MAAM,IAAI;AAChB,UAAM,UAAU,KAAK,KAAK;AAC1B,QAAI,QAAS,MAAK,YAAY,OAAO;AAAA,EACvC;AAAA,EAEA,YAAgC;AAAE,WAAO,KAAK;AAAA,EAAO;AAAA,EACrD,UAAU,IAA+C;AAAE,SAAK,WAAW,KAAK,EAAE;AAAA,EAAG;AAAA,EACrF,QAAQ,IAA4C;AAAE,SAAK,SAAS,KAAK,EAAE;AAAA,EAAG;AAAA,EAC9E,eAAe,IAA8C;AAAE,SAAK,YAAY,KAAK,EAAE;AAAA,EAAG;AAAA;AAAA,EAE1F,eAAe,QAAgC;AAC7C,eAAW,MAAM,KAAK,YAAa,IAAG,MAAM;AAAA,EAC9C;AAAA,EACA,iBAAiB,SAAqF;AAAE,SAAK,oBAAoB;AAAA,EAAS;AAAA;AAAA,EAE1I,eAAe,UAAkB,SAAsB,IAAI,gBAAgB,EAAE,QAAmC;AAC9G,QAAI,CAAC,KAAK,kBAAmB,OAAM,IAAI,MAAM,gCAAgC;AAC7E,WAAO,KAAK,kBAAkB,UAAU,MAAM;AAAA,EAChD;AAAA,EACA,YAAY,MAAsB;AAChC,SAAK,gBAAgB;AACrB,UAAM,KAAK,OAAO,KAAK,YAAY;AACnC,QAAI,KAAK,UAAU,OAAQ,MAAK,QAAQ,IAAI;AAAA,QACvC,MAAK,SAAS,KAAK,EAAE,IAAI,KAAK,CAAC;AACpC,WAAO;AAAA,EACT;AAAA,EACA,aAAa,IAAqB;AAChC,UAAM,SAAS,KAAK,SAAS;AAC7B,SAAK,WAAW,KAAK,SAAS,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE;AACvD,WAAO,KAAK,SAAS,SAAS;AAAA,EAChC;AAAA,EACA,SAA8B;AAAE,WAAO,KAAK,SAAS,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE;AAAA,EAAG;AAAA,EAC7E,MAAM,YAA2B;AAC/B,SAAK,cAAc;AACnB,QAAI,KAAK,UAAU,UAAW,MAAK,YAAY,aAAa;AAAA,EAC9D;AAAA,EACA,kBAAiC;AAAE,WAAO,KAAK;AAAA,EAAW;AAAA;AAAA,EAG1D,UAA6D,CAAC;AAAA,EAC7C,kBAAkB,oBAAI,IAAY;AAAA;AAAA,EAGnD,kBAAkB,IAAY,MAAc,OAAgC,cAAyB,CAAC,GAAS;AAC7G,SAAK,gBAAgB,IAAI,EAAE;AAC3B,SAAK,UAAU,EAAE,MAAM,sBAAsB,IAAI,MAAM,QAAQ,KAAK,UAAU,KAAK,GAAG,OAAO,YAAY,CAAC;AAAA,EAC5G;AAAA;AAAA,EAEA,mBAAmB,IAAkB;AACnC,QAAI,KAAK,gBAAgB,OAAO,EAAE,EAAG,MAAK,UAAU,EAAE,MAAM,wBAAwB,GAAG,CAAC;AAAA,EAC1F;AAAA,EACA,iBAAiB,IAAY,UAAqC;AAChE,QAAI,CAAC,KAAK,gBAAgB,OAAO,EAAE,EAAG,QAAO;AAC7C,SAAK,QAAQ,KAAK,EAAE,IAAI,SAAS,CAAC;AAClC,SAAK,UAAU,EAAE,MAAM,sBAAsB,IAAI,SAAS,CAAC;AAC3D,WAAO;AAAA,EACT;AAAA,EAEA,UAAU,OAA8B;AACtC,eAAW,MAAM,KAAK,SAAU,IAAG,KAAK;AAAA,EAC1C;AAAA,EACA,YAAY,QAAiC;AAC3C,UAAM,OAAO,KAAK,SAAS,MAAM;AACjC,QAAI,CAAC,KAAM,MAAK,QAAQ;AACxB,eAAW,MAAM,KAAK,WAAY,IAAG,MAAM;AAC3C,QAAI,KAAM,MAAK,QAAQ,KAAK,IAAI;AAAA,EAClC;AAAA,EAEQ,QAAQ,MAAoB;AAClC,SAAK,QAAQ;AACb,SAAK,UAAU,KAAK,IAAI;AACxB,SAAK,UAAU,EAAE,MAAM,cAAc,KAAK,CAAC;AAAA,EAC7C;AACF;AAsBO,IAAM,wBAAN,MAA0D;AAAA,EAC/D,eAAsC,EAAE,QAAQ,KAAK;AAAA;AAAA,EAErD,QAAkB,CAAC,SAAS;AAAA;AAAA,EAE5B,UAAU,oBAAI,IAAsB;AAAA;AAAA,EAEpC,UAAU,oBAAI,IAAoB;AAAA;AAAA,EAElC,gBAAgB,oBAAI,IAAsB;AAAA;AAAA,EAE1C,cAAoC,EAAE,SAAS,SAAS;AAAA;AAAA,EAExD,eAAe,oBAAI,IAAY;AAAA;AAAA,EAE/B,eAAoC,CAAC;AAAA;AAAA,EAErC,eAAyB,CAAC;AAAA;AAAA,EAE1B,SAAmB,CAAC;AAAA,EACpB,cAAwB,CAAC;AAAA,EACzB,SAAmB,CAAC;AAAA;AAAA,EAEpB,gBAA8B;AAAA;AAAA,EAE9B,eAA6B;AAAA,EAC7B,aAA2B;AAAA;AAAA,EAE3B,cAA4C,CAAC;AAAA;AAAA,EAE7C,WAAW,oBAAI,IAA8B;AAAA;AAAA,EAE7C,iBAAiB,oBAAI,IAA4B;AAAA,EACjD,QAA6B,CAAC;AAAA,EACtB,QAAQ,oBAAI,IAA2B;AAAA,EACvC,WAAW;AAAA,EAEX,IAAI,MAA+B;AAAE,SAAK,MAAM,KAAK,IAAI;AAAA,EAAG;AAAA;AAAA,EAGpE,WAAW,IAA+E;AACxF,WAAO,KAAK,MAAM,QAAQ,CAAC,MAAO,EAAE,OAAO,MAAM,YAAY,IAAI,CAAC,EAAE,MAAM,IAAI,CAAC,CAAE;AAAA,EACnF;AAAA;AAAA,EAGA,gBAAgB,QAA4B;AAC1C,QAAI;AACJ,SAAK,MAAM,IAAI,QAAQ,IAAI,QAAc,CAAC,YAAY;AAAE,aAAO;AAAA,IAAS,CAAC,CAAC;AAC1E,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,SAAS,eAAuD;AACpE,SAAK,IAAI,EAAE,IAAI,YAAY,cAAc,CAAC;AAC1C,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,MAAM,MAAM,eAAsC;AAChD,SAAK,IAAI,EAAE,IAAI,SAAS,cAAc,CAAC;AACvC,QAAI,CAAC,KAAK,aAAa,UAAU,KAAK,aAAa,WAAW,QAAS,MAAK,eAAe,EAAE,QAAQ,KAAK;AAAA,EAC5G;AAAA,EAEA,MAAM,SAAS,eAA8C;AAC3D,SAAK,IAAI,EAAE,IAAI,YAAY,cAAc,CAAC;AAC1C,QAAI,KAAK,cAAe,OAAM,KAAK;AACnC,UAAM,KAAK,MAAM,EAAE,KAAK,QAAQ;AAChC,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,OAAO,KAAK,MAAM,IAAI,CAAC,UAAU;AAAA,QAC/B,MAAM;AAAA,QAAM,MAAM,GAAG,aAAa,IAAI,IAAI,GAAG,QAAQ,SAAS,EAAE;AAAA,QAAG,SAAS;AAAA,QAAY,YAAY;AAAA,QAAQ,mBAAmB,qBAAqB,EAAE;AAAA,MACxJ,EAAE;AAAA,MACF,QAAQ,CAAC,GAAG,KAAK,MAAM;AAAA,MACvB,aAAa,CAAC,GAAG,KAAK,WAAW;AAAA,MACjC,OAAO,CAAC;AAAA,IACV;AAAA,EACF;AAAA,EAEA,MAAM,QAAQ,MAAY,KAA0C;AAClE,SAAK,IAAI,EAAE,IAAI,WAAW,QAAQ,KAAK,GAAG,CAAC;AAC3C,UAAM,OAAO,GAAG,KAAK,KAAK,IAAI,KAAK,EAAE;AACrC,UAAM,MAAM,mBAAmB,IAAI,EAAE,IAAI,IAAI;AAC7C,UAAM,SAAS,YAAY,IAAI,EAAE,IAAI,IAAI;AACzC,QAAI,MAAM,KAAK,EAAE,IAAI;AAAA,MACnB,QAAQ,KAAK;AAAA,MAAI,OAAO,KAAK;AAAA,MAAO,OAAO,KAAK;AAAA,MAAO;AAAA,MAAQ,WAAW;AAAA,MAAK,QAAQ;AAAA,MACvF,OAAO,OAAO,YAAY,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,YAAY,MAAM,GAAG,GAAG,IAAI,EAAE,IAAI,IAAI,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;AAAA,IACrI;AACA,WAAO,EAAE,KAAK,QAAQ,QAAQ,CAAC,GAAG,KAAK,MAAM,EAAE;AAAA,EACjD;AAAA;AAAA,EAGA,MAAM,OAAO,MAAY,KAA0C;AACjE,SAAK,IAAI,EAAE,IAAI,UAAU,QAAQ,KAAK,GAAG,CAAC;AAC1C,UAAM,SAAS,IAAI,MAAM,KAAK,EAAE;AAChC,QAAI,QAAQ,WAAW,WAAY,OAAM,IAAI,MAAM,QAAQ,KAAK,KAAK,4BAA4B;AACjG,UAAM,UAAU,OAAO,QAAQ,OAAO,KAAK,EAAE,OAAO,CAAC,CAAC,MAAM,KAAK,MAAM,MAAM,WAAW,SAAS,OAAO,YAAY,EAAE,IAAI,CAAC,CAAC,IAAI,MAAM,IAAI;AAC1I,UAAM,SAAS,OAAO,iBAAiB,CAAC,GAAG,IAAI,CAAC,SAAU,OAAO,gBAAgB,OAAO,iBAAiB,YAAY,GAAG,OAAO,YAAY,IAAI,IAAI,KAAK,IAAK;AAC7J,WAAO,WAAW,OAAO,WAAW,KAAK;AACzC,WAAO,aAAa,OAAO,YAAY,QAAQ,IAAI,CAAC,SAAS,CAAC,MAAM,OAAO,IAAI,EAAE,CAAC,CAAC;AACnF,WAAO,gBAAgB,CAAC,GAAG,oBAAI,IAAI,CAAC,GAAI,OAAO,iBAAiB,CAAC,GAAI,GAAG,KAAK,CAAC,CAAC;AAC/E,WAAO,SAAS;AAChB,WAAO,EAAE,KAAK,OAAO,WAAW,QAAQ,OAAO,QAAQ,QAAQ,CAAC,EAAE;AAAA,EACpE;AAAA,EAEA,MAAM,aAAa,MAAY,MAA6C;AAC1E,SAAK,IAAI,EAAE,IAAI,gBAAgB,QAAQ,KAAK,GAAG,CAAC;AAChD,WAAO,KAAK,eAAe,IAAI,KAAK,EAAE,KAAK,EAAE,IAAI,KAAK;AAAA,EACxD;AAAA;AAAA,EAGA,MAAM,UAAU,MAAY,KAAmB,UAAsB,MAAM,QAAsC;AAC/G,SAAK,IAAI,EAAE,IAAI,aAAa,QAAQ,KAAK,GAAG,CAAC;AAC7C,UAAM,SAAS,IAAI,MAAM,KAAK,EAAE;AAChC,QAAI,CAAC,OAAQ,QAAO;AACpB,UAAM,UAAU,KAAK,QAAQ,IAAI,KAAK,EAAE,KAAK,IAAI,MAAM,IAAI,CAAC,MAAM,EAAE,IAAI;AACxE,eAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,OAAO,KAAK,EAAG,OAAM,UAAU,QAAQ,SAAS,IAAI,MAAM,MAAM,WAAW;AACtH,QAAI,QAAQ,SAAS,GAAG;AACtB,UAAI,UAAU,EAAE,QAAQ,KAAK,IAAI,MAAM,OAAO,YAAY,QAAQ,IAAI,CAAC,SAAS,CAAC,MAAM,OAAO,IAAI,EAAE,CAAC,CAAC,EAAE;AACxG,cAAQ;AAAA,IACV;AACA,UAAM,KAAK,MAAM,IAAI,KAAK,EAAE;AAC5B,WAAO,IAAI;AACX,UAAM,UAAU,KAAK,SAAS,IAAI,KAAK,EAAE,KAAK;AAC9C,WAAO,SAAS;AAChB,WAAO,OAAO;AACd,QAAI,YAAY,UAAU;AACxB,aAAO,OAAO;AACd,aAAO,OAAO;AAAA,IAChB,OAAO;AACL,aAAO,eAAe,KAAK,QAAQ,IAAI,KAAK,EAAE,KAAK,QAAQ,CAAC,KAAK;AACjE,YAAM,QAAQ,KAAK,cAAc,IAAI,KAAK,EAAE;AAC5C,UAAI,MAAO,QAAO,gBAAgB;AAAA,UAC7B,QAAO,OAAO;AAAA,IACrB;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,QAAQ,KAAmB,QAAgB,MAAwC;AACvF,SAAK,IAAI,EAAE,IAAI,WAAW,QAAQ,MAAM,KAAK,KAAK,CAAC;AACnD,UAAM,SAAS,IAAI,MAAM,MAAM;AAC/B,QAAI,CAAC,KAAK,KAAM,QAAO,IAAI,MAAM,MAAM;AAAA,aAC9B,QAAQ,WAAW,SAAU,QAAO,SAAS;AAAA,aAC7C,QAAQ,WAAW,aAAa;AACvC,aAAO,SAAS;AAChB,aAAO,OAAO;AAAA,IAChB;AAAA,EACF;AAAA,EAEA,MAAM,QAAQ,KAA8C;AAC1D,SAAK,IAAI,EAAE,IAAI,UAAU,CAAC;AAC1B,WAAO,UAAU,GAAG;AAAA,EACtB;AAAA,EAEA,MAAM,eAA8C;AAClD,SAAK,IAAI,EAAE,IAAI,eAAe,CAAC;AAC/B,WAAO,EAAE,MAAM,CAAC,GAAG,KAAK,WAAW,EAAE;AAAA,EACvC;AAAA,EACA,MAAM,aAA8B;AAAE,SAAK,IAAI,EAAE,IAAI,aAAa,CAAC;AAAG,WAAO;AAAA,EAAI;AAAA,EACjF,MAAM,oBAAoB,KAAkD;AAC1E,SAAK,IAAI,EAAE,IAAI,sBAAsB,CAAC;AACtC,QAAI,KAAK,YAAY,YAAY,UAAU;AACzC,iBAAW,UAAU,OAAO,OAAO,IAAI,KAAK,EAAG,KAAI,OAAO,WAAW,SAAU,MAAK,aAAa,IAAI,OAAO,MAAM;AAAA,IACpH;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EACA,MAAM,WAAW,KAAsC;AACrD,SAAK,IAAI,EAAE,IAAI,aAAa,CAAC;AAC7B,UAAM,QAAkB,CAAC;AACzB,eAAW,UAAU,OAAO,OAAO,IAAI,KAAK,GAAG;AAC7C,UAAI,OAAO,WAAW,YAAY,OAAO,UAAU,CAAC,KAAK,aAAa,IAAI,OAAO,MAAM,EAAG;AAC1F,aAAO,SAAS;AAChB,YAAM,KAAK,OAAO,MAAM;AAAA,IAC1B;AACA,WAAO;AAAA,EACT;AAAA,EACA,MAAM,eAA6C;AAAE,SAAK,IAAI,EAAE,IAAI,eAAe,CAAC;AAAG,WAAO,KAAK;AAAA,EAAc;AAAA,EACjH,MAAM,eAAkC;AAAE,SAAK,IAAI,EAAE,IAAI,eAAe,CAAC;AAAG,WAAO,CAAC,GAAG,KAAK,YAAY;AAAA,EAAG;AAAA,EAC3G,MAAM,QAAQ,MAAoB,MAA2D;AAC3F,SAAK,IAAI,EAAE,IAAI,WAAW,aAAa,KAAK,YAAY,CAAC;AACzD,QAAI,KAAK,aAAc,OAAM,KAAK;AAAA,EACpC;AAAA,EACA,MAAM,QAAuB;AAC3B,SAAK,IAAI,EAAE,IAAI,QAAQ,CAAC;AACxB,QAAI,KAAK,WAAY,OAAM,KAAK;AAAA,EAClC;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/testing.ts"],"sourcesContent":["import type { IConfig } from './interfaces/IConfig';\nimport type { IFileSystem, ToolOutcome } from './interfaces/IFileSystem';\nimport type { ITerminalSession, QueuedTaskMessage, StructuredEvent, StructuredSessionCapability, StructuredTurnEnd } from './interfaces/ITerminalRunner';\nimport type { ApprovalDecision } from './interfaces/IApproval';\nimport type { CheckpointAnswer, TaskCompleteArgs } from './services/mcp/tools';\nimport type {\n IsolationAvailability,\n IsolationHandoff,\n IsolationMergeResult,\n IsolationOutcome,\n IsolationPruneResult,\n IsolationRemoval,\n IsolationRun,\n IntegrationDisposal,\n PreparedTask,\n IWorktreeIsolation,\n RepairEvidence,\n TreeSnapshot,\n} from './interfaces/IWorktreeIsolation';\nimport type { Task } from './models/Task';\nimport { handoffOf, integrationBranchFor, noRemoval, SELF_REPO } from './services/isolationRecord';\n\n/**\n * Let an already-queued promise chain run to its next await before asserting,\n * without a wall-clock sleep. For a chain whose length is not known, drain the\n * microtask queue repeatedly. Only helps a chain that does not wait on a timer.\n */\nexport async function flushMicrotasks(rounds = 20): Promise<void> {\n for (let i = 0; i < rounds; i += 1) await Promise.resolve();\n}\n\nexport function fakeConfig(overrides: Partial<IConfig> = {}): IConfig {\n return {\n aiProvider: 'openrouter',\n apiKey: 'sk-test',\n planningModel: 'test-model',\n enabledRunners: ['claude-code'],\n maxParallelSessions: 3,\n researchEnabled: false,\n researchMaxSteps: 10,\n researchMaxFileSize: 100_000,\n openAiBaseUrl: 'https://api.openai.com/v1',\n openAiApiKey: '',\n openrouterKey: '',\n geminiKey: '',\n openaiCompatibleBaseUrl: '',\n openaiCompatibleApiKey: '',\n orchestratorModel: '',\n researchSubagentModel: '',\n geminiModel: '',\n planMapEnabled: true,\n autonomousMode: true,\n // Off so an orchestrator built without an injected isolation never runs\n // real git against whatever repository the tests happen to run in.\n worktreeIsolation: false,\n workspaceRepos: [],\n worktreeLinks: [],\n // Off so a scripted conflict stays a conflict unless a test opts into repairing it.\n conflictRepairAttempts: 0,\n approvalMode: 'ask',\n approvalPreApproved: [],\n setProviderModelLists: () => {},\n getProviderBaseUrl: () => '',\n getProviderApiKey: () => '',\n ...overrides,\n };\n}\n\nconst EMPTY_OUTCOME: ToolOutcome = { success: false, output: '', truncated: false };\n\n/**\n * A complete {@link IFileSystem} stub. Lives here rather than in each package's\n * test folder so adding a tool to the interface is one edit, not one per suite.\n */\nexport function fakeFileSystem(overrides: Partial<IFileSystem> = {}): IFileSystem {\n return {\n readFile: async () => EMPTY_OUTCOME,\n readFiles: async () => EMPTY_OUTCOME,\n glob: async () => EMPTY_OUTCOME,\n grep: async () => EMPTY_OUTCOME,\n findSymbol: async () => EMPTY_OUTCOME,\n listDir: async () => EMPTY_OUTCOME,\n bash: async () => EMPTY_OUTCOME,\n getWorkspaceRoot: () => '/workspace',\n ...overrides,\n };\n}\n\nexport class FakeTerminalSession implements ITerminalSession {\n private outputCbs: Array<(text: string) => void> = [];\n private exitCbs: Array<(code: number) => void> = [];\n output = '';\n written: string[] = [];\n killed = false;\n\n constructor(public id = 's1', public taskId = 't1') {}\n\n onOutput(cb: (text: string) => void): void { this.outputCbs.push(cb); }\n onExit(cb: (code: number) => void): void { this.exitCbs.push(cb); }\n kill(): void { this.killed = true; }\n getOutput(): string { return this.output; }\n write(text: string): void { this.written.push(text); }\n\n emitOutput(text: string): void {\n this.output += text;\n for (const cb of this.outputCbs) cb(text);\n }\n emitExit(code: number): void {\n for (const cb of this.exitCbs) cb(code);\n }\n}\n\n/**\n * A {@link FakeTerminalSession} that is feature-detected as structured\n * (ADR-0018): the turn, queue and native-session calls a test drives, with\n * no protocol behind them. It queues and delivers as `StructuredSession`\n * does — a message to an idle session starts a turn at once, one sent\n * mid-turn goes out as that turn ends, without passing through idle.\n */\nexport class FakeStructuredSession extends FakeTerminalSession implements StructuredSessionCapability {\n readonly transport = 'structured' as const;\n state: 'working' | 'idle' = 'working';\n messages: QueuedTaskMessage[] = [];\n /** Every message a turn was started with, in order. */\n delivered: string[] = [];\n interrupts = 0;\n private messageCount = 0;\n private turnEndCbs: Array<(reason: StructuredTurnEnd) => void> = [];\n private eventCbs: Array<(event: StructuredEvent) => void> = [];\n private completeCbs: Array<(report: TaskCompleteArgs) => void> = [];\n private checkpointHandler: ((question: string, signal: AbortSignal) => Promise<CheckpointAnswer>) | null = null;\n\n constructor(id = 's1', taskId = 't1', public sessionId: string | null = 'native-1') {\n super(id, taskId);\n }\n\n override write(text: string): void {\n super.write(text);\n const message = text.trim();\n if (message) this.sendMessage(message);\n }\n\n turnState(): 'working' | 'idle' { return this.state; }\n onTurnEnd(cb: (reason: StructuredTurnEnd) => void): void { this.turnEndCbs.push(cb); }\n onEvent(cb: (event: StructuredEvent) => void): void { this.eventCbs.push(cb); }\n onTaskComplete(cb: (report: TaskCompleteArgs) => void): void { this.completeCbs.push(cb); }\n /** The runner calls `task_complete`, as `StructuredSession` relays it. */\n reportComplete(report: TaskCompleteArgs): void {\n for (const cb of this.completeCbs) cb(report);\n }\n onToolCheckpoint(handler: (question: string, signal: AbortSignal) => Promise<CheckpointAnswer>): void { this.checkpointHandler = handler; }\n /** The runner calls `checkpoint`, as `StructuredSession` relays it; settles with the answer. */\n callCheckpoint(question: string, signal: AbortSignal = new AbortController().signal): Promise<CheckpointAnswer> {\n if (!this.checkpointHandler) throw new Error('no checkpoint handler attached');\n return this.checkpointHandler(question, signal);\n }\n sendMessage(text: string): string {\n this.messageCount += 1;\n const id = `msg-${this.messageCount}`;\n if (this.state === 'idle') this.deliver(text);\n else this.messages.push({ id, text });\n return id;\n }\n /** Interrupts, and the turn that replaces the interrupted one opens with the forced message. */\n forceSend(text: string): string {\n if (this.state === 'idle') return this.sendMessage(text);\n this.messageCount += 1;\n const id = `msg-${this.messageCount}`;\n this.putForced({ id, text, forced: true });\n void this.interrupt();\n return id;\n }\n forceSendQueued(id: string): boolean {\n const message = this.messages.find((m) => m.id === id);\n if (!message || message.handedOver) return false;\n this.messages = this.messages.filter((m) => m !== message);\n this.putForced({ ...message, forced: true });\n if (this.state === 'working') void this.interrupt();\n return true;\n }\n private putForced(message: QueuedTaskMessage): void {\n const at = this.messages.findIndex((m) => !m.forced);\n this.messages.splice(at < 0 ? this.messages.length : at, 0, message);\n }\n removeQueued(id: string): boolean {\n const before = this.messages.length;\n this.messages = this.messages.filter((m) => m.id !== id);\n return this.messages.length < before;\n }\n queued(): QueuedTaskMessage[] { return this.messages.map((m) => ({ ...m })); }\n async interrupt(): Promise<void> {\n this.interrupts += 1;\n if (this.state === 'working') this.emitTurnEnd('interrupted');\n }\n nativeSessionId(): string | null { return this.sessionId; }\n\n /** Every answer this session was given, in order. */\n answers: Array<{ id: string; decision: ApprovalDecision }> = [];\n private readonly openPermissions = new Set<string>();\n\n /** The runner asks to use a tool, as `StructuredSession` announces it. */\n requestPermission(id: string, name: string, input: Record<string, unknown>, suggestions: unknown[] = []): void {\n this.openPermissions.add(id);\n this.emitEvent({ type: 'permission_request', id, name, detail: JSON.stringify(input), input, suggestions });\n }\n /** The runner gives up on a request, as an interrupt makes it. */\n withdrawPermission(id: string): void {\n if (this.openPermissions.delete(id)) this.emitEvent({ type: 'permission_withdrawn', id });\n }\n answerPermission(id: string, decision: ApprovalDecision): boolean {\n if (!this.openPermissions.delete(id)) return false;\n this.answers.push({ id, decision });\n this.emitEvent({ type: 'permission_decided', id, decision });\n return true;\n }\n\n emitEvent(event: StructuredEvent): void {\n for (const cb of this.eventCbs) cb(event);\n }\n /** The runner reads a queued message inside the running turn, as `StructuredSession` reports it (ADR-0023). */\n deliverMidTurn(id: string): void {\n const message = this.messages.find((m) => m.id === id);\n if (!message) return;\n this.messages = this.messages.filter((m) => m !== message);\n this.emitEvent({ type: 'message_delivered', messageId: id, text: message.text });\n }\n emitTurnEnd(reason: StructuredTurnEnd): void {\n const next = this.messages.shift();\n if (!next) this.state = 'idle';\n for (const cb of this.turnEndCbs) cb(reason);\n if (next) this.deliver(next.text);\n }\n\n private deliver(text: string): void {\n this.state = 'working';\n this.delivered.push(text);\n this.emitEvent({ type: 'turn_start', text });\n }\n}\n\nexport type FakeIsolationCall =\n | { op: 'isActive'; workspaceRoot: string }\n | { op: 'stash'; workspaceRoot: string }\n | { op: 'startRun'; workspaceRoot: string }\n | { op: 'prepare' | 'reopen' | 'verifyRepair'; taskId: string }\n | { op: 'integrate'; taskId: string }\n | { op: 'release'; taskId: string; keep: boolean }\n | { op: 'handoff' | 'pruneOrphans' | 'reviewDiff' | 'mergeIntoCheckedOut' | 'sweep' | 'findInHead' | 'snapshotTree' | 'changedSince' }\n | { op: 'discard'; integration: IntegrationDisposal };\n\n/**\n * An in-memory {@link IWorktreeIsolation} for scheduling tests: no git, no\n * filesystem. Every call is logged in `calls`; `prepare` hands back a\n * deterministic fake cwd. Set `availability` to exercise the fallbacks, `outcomes`\n * to script a conflict, and `holdIntegration` to keep a task un-integrated so a\n * test can observe that its dependents wait. `repos` makes the run a group of\n * several; `changes` and `stopsIn` say which of them a task changes and where\n * its landing stops. `repairEvidence` scripts what a conflict repair's\n * evidence check finds, and `removal` what a removal kept back.\n */\nexport class FakeWorktreeIsolation implements IWorktreeIsolation {\n availability: IsolationAvailability = { active: true };\n /** The repo paths `startRun` groups: a group of one at `.` unless set. */\n repos: string[] = [SELF_REPO];\n /** Per task id, the repos it changes; every repo of the group when not listed. */\n changes = new Map<string, string[]>();\n /** Per task id, the repo its landing stops in when its outcome is not `merged`; its first changed repo when not listed. */\n stopsIn = new Map<string, string>();\n /** Per task id, the files a `conflict` outcome names; empty when not listed. */\n conflictFiles = new Map<string, string[]>();\n /** What `mergeIntoCheckedOut` answers; a `merged` one also puts every landed task in HEAD, as git would. */\n mergeResult: IsolationMergeResult = { outcome: 'merged' };\n /** Task ids whose landed work `findInHead` finds in HEAD besides those a merge put there, as a merge by hand would. */\n mergedByHand = new Set<string>();\n /** What `snapshotTree` answers; null as for a workspace with no repo. */\n treeSnapshot: TreeSnapshot | null = {};\n /** What `changedSince` answers: the tracked files an ops task changed. */\n changedFiles: string[] = [];\n /** What `startRun` shares and `prepare` copies, to exercise their notices. */\n shared: string[] = [];\n sharedRepos: string[] = [];\n copied: string[] = [];\n /** Set to make `startRun` throw, as git does when no repo of the group can be isolated. */\n startRunError: Error | null = null;\n /** Set to make `discard` / `sweep` throw after logging the call. */\n discardError: Error | null = null;\n sweepError: Error | null = null;\n /** What `pruneOrphans` reports as kept back from the sweep. */\n keptOnPrune: IsolationPruneResult['kept'] = [];\n /**\n * What every removal — a `release` that removes, `discard`, `pruneOrphans` —\n * reports it kept back. A refused task keeps its record, as git's does.\n */\n removal: IsolationRemoval = noRemoval();\n /** Per task id; a task not listed integrates as `merged`. */\n outcomes = new Map<string, IsolationOutcome>();\n /** Per task id, what `verifyRepair` finds; a task not listed passes. */\n repairEvidence = new Map<string, RepairEvidence>();\n calls: FakeIsolationCall[] = [];\n private holds = new Map<string, Promise<void>>();\n private runCount = 0;\n\n private log(call: FakeIsolationCall): void { this.calls.push(call); }\n\n /** Task ids in the order `op` was called for them. */\n taskIdsFor(op: 'prepare' | 'reopen' | 'verifyRepair' | 'integrate' | 'release'): string[] {\n return this.calls.flatMap((c) => (c.op === op && 'taskId' in c ? [c.taskId] : []));\n }\n\n /** Make `integrate` for this task wait until the returned function is called. */\n holdIntegration(taskId: string): () => void {\n let open!: () => void;\n this.holds.set(taskId, new Promise<void>((resolve) => { open = resolve; }));\n return open;\n }\n\n async isActive(workspaceRoot: string): Promise<IsolationAvailability> {\n this.log({ op: 'isActive', workspaceRoot });\n return this.availability;\n }\n\n /** Like git: once the tracked changes are stashed, the tree is no longer dirty. */\n async stash(workspaceRoot: string): Promise<void> {\n this.log({ op: 'stash', workspaceRoot });\n if (!this.availability.active && this.availability.reason === 'dirty') this.availability = { active: true };\n }\n\n async startRun(workspaceRoot: string): Promise<IsolationRun> {\n this.log({ op: 'startRun', workspaceRoot });\n if (this.startRunError) throw this.startRunError;\n const id = `run${++this.runCount}`;\n return {\n id,\n workspaceRoot,\n repos: this.repos.map((repo) => ({\n path: repo, root: `${workspaceRoot}/${repo}`.replace(/\\/\\.$/, ''), baseRef: 'base0000', baseBranch: 'main', integrationBranch: integrationBranchFor(id),\n })),\n shared: [...this.shared],\n sharedRepos: [...this.sharedRepos],\n tasks: {},\n };\n }\n\n async prepare(task: Task, run: IsolationRun): Promise<PreparedTask> {\n this.log({ op: 'prepare', taskId: task.id });\n const name = `${task.order}-${task.id}`;\n const cwd = `/fake-worktrees/${run.id}/${name}`;\n const branch = `ordewell/${run.id}/${name}`;\n run.tasks[task.id] = {\n taskId: task.id, order: task.order, title: task.title, branch, workspace: cwd, status: 'active',\n repos: Object.fromEntries(run.repos.map((r) => [r.path, { worktree: r.path === SELF_REPO ? cwd : `${cwd}/${r.path}`, linked: [] }])),\n };\n return { cwd, branch, copied: [...this.copied] };\n }\n\n /** Like git: the same cwd, each changed repo's tip recorded, the repair counted. */\n async reopen(task: Task, run: IsolationRun): Promise<PreparedTask> {\n this.log({ op: 'reopen', taskId: task.id });\n const record = run.tasks[task.id];\n if (record?.status !== 'conflict') throw new Error(`Task ${task.order} has no conflict to repair`);\n const changed = Object.entries(record.repos).filter(([repo, entry]) => entry.changed || repo === record.conflictRepo).map(([repo]) => repo);\n const files = (record.conflictFiles ?? []).map((file) => (record.conflictRepo && record.conflictRepo !== SELF_REPO ? `${record.conflictRepo}/${file}` : file));\n record.repairs = (record.repairs ?? 0) + 1;\n record.repairBase = Object.fromEntries(changed.map((repo) => [repo, `tip-${repo}`]));\n record.repairedFiles = [...new Set([...(record.repairedFiles ?? []), ...files])];\n record.status = 'repairing';\n return { cwd: record.workspace, branch: record.branch, copied: [] };\n }\n\n async verifyRepair(task: Task, _run: IsolationRun): Promise<RepairEvidence> {\n this.log({ op: 'verifyRepair', taskId: task.id });\n return this.repairEvidence.get(task.id) ?? { ok: true };\n }\n\n /** Like git: the landing is recorded and persisted before the (held) merge, and cleared once it settles. */\n async integrate(task: Task, run: IsolationRun, persist: () => void = () => undefined): Promise<IsolationOutcome> {\n this.log({ op: 'integrate', taskId: task.id });\n const record = run.tasks[task.id];\n if (!record) return 'failed';\n const changed = this.changes.get(task.id) ?? run.repos.map((r) => r.path);\n for (const [repo, entry] of Object.entries(record.repos)) entry.changed = changed.includes(repo) || (entry.changed ?? false);\n if (changed.length > 0) {\n run.landing = { taskId: task.id, tips: Object.fromEntries(changed.map((repo) => [repo, `tip-${repo}`])) };\n persist();\n }\n await this.holds.get(task.id);\n delete run.landing;\n const outcome = this.outcomes.get(task.id) ?? 'merged';\n record.status = outcome;\n delete record.repairBase;\n if (outcome === 'merged') {\n delete record.conflictRepo;\n delete record.conflictFiles;\n } else {\n record.conflictRepo = this.stopsIn.get(task.id) ?? changed[0] ?? SELF_REPO;\n const files = this.conflictFiles.get(task.id);\n if (files) record.conflictFiles = files;\n else delete record.conflictFiles;\n }\n return outcome;\n }\n\n async release(run: IsolationRun, taskId: string, opts: { keep: boolean }): Promise<IsolationRemoval> {\n this.log({ op: 'release', taskId, keep: opts.keep });\n const record = run.tasks[taskId];\n const removal = opts.keep || !record ? noRemoval() : this.removed();\n const refused = removal.refused.some((r) => r.task?.taskId === taskId);\n if (!opts.keep && !refused) delete run.tasks[taskId];\n else if (record?.status === 'active') record.status = 'kept';\n else if (record?.status === 'repairing') {\n record.status = 'conflict';\n delete record.repairBase;\n }\n return removal;\n }\n\n private removed(): IsolationRemoval {\n return { preserved: [...this.removal.preserved], refused: [...this.removal.refused] };\n }\n\n async handoff(run: IsolationRun): Promise<IsolationHandoff> {\n this.log({ op: 'handoff' });\n return handoffOf(run);\n }\n\n async pruneOrphans(): Promise<IsolationPruneResult> {\n this.log({ op: 'pruneOrphans' });\n return { kept: [...this.keptOnPrune], ...this.removed() };\n }\n async reviewDiff(): Promise<string> { this.log({ op: 'reviewDiff' }); return ''; }\n async mergeIntoCheckedOut(run: IsolationRun): Promise<IsolationMergeResult> {\n this.log({ op: 'mergeIntoCheckedOut' });\n if (this.mergeResult.outcome === 'merged') {\n for (const record of Object.values(run.tasks)) if (record.status === 'merged') this.mergedByHand.add(record.taskId);\n }\n return this.mergeResult;\n }\n async findInHead(run: IsolationRun): Promise<string[]> {\n this.log({ op: 'findInHead' });\n const found: string[] = [];\n for (const record of Object.values(run.tasks)) {\n if (record.status !== 'merged' || record.inHead || !this.mergedByHand.has(record.taskId)) continue;\n record.inHead = true;\n found.push(record.taskId);\n }\n return found;\n }\n async snapshotTree(): Promise<TreeSnapshot | null> { this.log({ op: 'snapshotTree' }); return this.treeSnapshot; }\n async changedSince(): Promise<string[]> { this.log({ op: 'changedSince' }); return [...this.changedFiles]; }\n async discard(_run: IsolationRun, opts: { integration: IntegrationDisposal }): Promise<IsolationRemoval> {\n this.log({ op: 'discard', integration: opts.integration });\n if (this.discardError) throw this.discardError;\n return this.removed();\n }\n async sweep(): Promise<void> {\n this.log({ op: 'sweep' });\n if (this.sweepError) throw this.sweepError;\n }\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/order-labels.ts"],"sourcesContent":["import type { Task } from './models/Task';\n\n/**\n * Parent-scoped dotted order label for a task, e.g. \"2.1\" for the first subtask\n * of task 2. Kept in its own module (no Node imports) so a browser-bundled\n * surface — the VS Code webview — can import it via `@ordewell/core/order-labels`\n * without dragging the rest of core in.\n */\nexport function taskOrderLabel(task: { order: number }, parent?: { order: number }): string {\n return parent ? `${parent.order}.${task.order}` : String(task.order);\n}\n\n/** Resolve a dotted label to a task in a plan's top-level task list. */\nexport function resolveOrderLabel(tasks: Task[], label: string): Task | undefined {\n const parts = label.split('.');\n if (parts.length > 2 || parts.some((p) => !/^\\d+$/.test(p))) return undefined;\n const [topOrder, childOrder] = parts.map(Number);\n const top = tasks.find((t) => t.order === topOrder);\n if (!top) return undefined;\n if (childOrder === undefined) return top;\n return top.subtasks.find((s) => s.order === childOrder);\n}"],"mappings":";AAQO,SAAS,eAAe,MAAyB,QAAoC;AAC1F,SAAO,SAAS,GAAG,OAAO,KAAK,IAAI,KAAK,KAAK,KAAK,OAAO,KAAK,KAAK;AACrE;AAGO,SAAS,kBAAkB,OAAe,OAAiC;AAChF,QAAM,QAAQ,MAAM,MAAM,GAAG;AAC7B,MAAI,MAAM,SAAS,KAAK,MAAM,KAAK,CAAC,MAAM,CAAC,QAAQ,KAAK,CAAC,CAAC,EAAG,QAAO;AACpE,QAAM,CAAC,UAAU,UAAU,IAAI,MAAM,IAAI,MAAM;AAC/C,QAAM,MAAM,MAAM,KAAK,CAAC,MAAM,EAAE,UAAU,QAAQ;AAClD,MAAI,CAAC,IAAK,QAAO;AACjB,MAAI,eAAe,OAAW,QAAO;AACrC,SAAO,IAAI,SAAS,KAAK,CAAC,MAAM,EAAE,UAAU,UAAU;AACxD;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/services/ModeResolver.ts","../src/services/PlanValidator.ts","../src/services/PartialPlanParser.ts"],"sourcesContent":["import type { RunnerId } from '../models/Task';\n\nexport interface RunnerModeInfo {\n id: string;\n label: string;\n description: string;\n autonomous?: boolean;\n safe?: boolean;\n}\n\n/** The slice of RunnerRegistry this module needs — structural, so nothing here depends on the plugin layer. */\nexport interface ManifestLookup {\n getManifest(runner: RunnerId): { modes?: RunnerModeInfo[] } | undefined;\n}\n\n/**\n * A runner's modes are declared only in its manifest, never through a service,\n * so every caller that needs them fuses registry and runner list by hand. This\n * is that fusion, in one place: the planner prompt, the mode pickers on each\n * surface, and the runner-change retarget all read modes the same way.\n *\n * A runner with no modes maps to `[]` rather than being dropped — callers\n * distinguish \"declares no modes\" from \"not asked about\".\n */\nexport function runnerModesFrom(registry: ManifestLookup, runners: RunnerId[]): Record<RunnerId, RunnerModeInfo[]> {\n return Object.fromEntries(runners.map((r) => [r, registry.getManifest(r)?.modes ?? []] as const));\n}\n\n/**\n * Find the mode ID a runner resolves to under the given toggle state.\n * Tag-based first (autonomous/safe); falls back to positional last non-plan\n * if no tag is present on any mode (degrades gracefully on untagged manifests).\n * Returns undefined if `modes` is empty or undefined.\n */\nexport function resolveDefaultMode(\n modes: RunnerModeInfo[] | undefined,\n autonomousDefault = true,\n): string | undefined {\n if (!modes || modes.length === 0) return undefined;\n const tag: 'autonomous' | 'safe' = autonomousDefault ? 'autonomous' : 'safe';\n const tagged = modes.find((m) => m[tag]);\n if (tagged) return tagged.id;\n for (let i = modes.length - 1; i >= 0; i--) {\n if (modes[i].id !== 'plan') return modes[i].id;\n }\n return undefined;\n}\n\nfunction isDefaultMode(m: RunnerModeInfo, autonomousDefault: boolean): boolean {\n return autonomousDefault ? !!m.autonomous : !!m.safe;\n}\n\nfunction modeConflictsWithToggle(\n mode: RunnerModeInfo,\n autonomousDefault: boolean,\n): boolean {\n if (autonomousDefault) return !!mode.safe && !mode.autonomous;\n return !!mode.autonomous && !mode.safe;\n}\n\n/**\n * Build modes compatible with the current toggle. Plan is excluded from the\n * build-mode list (it is never a default for implementation tasks). Modes\n * tagged exclusively for the OPPOSITE toggle are hidden — the LLM cannot see\n * or select them. A dual-tagged mode (both autonomous + safe) is shown under\n * either toggle.\n */\nexport function filteredBuildModes(modes: RunnerModeInfo[], autonomousDefault: boolean): RunnerModeInfo[] {\n const buildModes = modes.filter((m) => m.id !== 'plan' && !modeConflictsWithToggle(m, autonomousDefault));\n const defaultIdx = buildModes.findIndex((m) => isDefaultMode(m, autonomousDefault));\n if (defaultIdx > 0) {\n const [def] = buildModes.splice(defaultIdx, 1);\n buildModes.unshift(def);\n }\n return buildModes;\n}\n\n/** The user-facing name of the `autonomousMode` boolean's two states. */\nexport function autonomyLevelLabel(autonomous: boolean): 'Full' | 'Guarded' {\n return autonomous ? 'Full' : 'Guarded';\n}\n\n/** `full`/`guarded` name the levels; `on`/`off` and `auto` are older words for them. Null for anything else. */\nexport function parseAutonomyLevel(arg: string | undefined): boolean | null {\n switch (arg?.trim().toLowerCase()) {\n case 'full': case 'on': return true;\n case 'guarded': case 'auto': case 'off': return false;\n default: return null;\n }\n}\n\nexport function buildModeGuide(\n runnerModes: Record<RunnerId, RunnerModeInfo[]>,\n autonomousDefault = true,\n): string {\n const lines: string[] = [];\n for (const [runnerId, modes] of Object.entries(runnerModes)) {\n if (!modes || modes.length === 0) continue;\n const filtered = filteredBuildModes(modes, autonomousDefault);\n if (filtered.length === 0) continue;\n const modeStr = filtered\n .map((m) => {\n const tag = isDefaultMode(m, autonomousDefault) ? ' (DEFAULT)' : '';\n return `${m.id}${tag} (${m.description})`;\n })\n .join(', ');\n lines.push(`- ${runnerId}: ${modeStr}`);\n }\n if (lines.length === 0) return '';\n\n return [\n `Autonomy level: ${autonomyLevelLabel(autonomousDefault)}.`,\n 'AVAILABLE MODES PER RUNNER:',\n ...lines,\n '',\n 'For each AI task, use the mode marked (DEFAULT) unless the task needs a different compatible mode listed above. Avoid the \"plan\" mode (read-only) unless the user explicitly requested analysis-only.',\n ].join('\\n');\n}\n\nexport function resolveTaskMode(\n emittedMode: string | undefined,\n runnerId: RunnerId,\n runnerModes: Record<RunnerId, RunnerModeInfo[]> | undefined,\n autonomousDefault = true,\n): string {\n const rawMode = (emittedMode as string) || 'build';\n\n if (!runnerModes) return rawMode === 'plan' ? 'plan' : 'build';\n\n const modes = runnerModes[runnerId];\n\n if (!modes || modes.length === 0) return rawMode;\n\n // A missing mode is an invalid emission, not a request for legacy `build` —\n // which on Codex aliases the workspace-write sandbox, not full access.\n if (!emittedMode) return resolveDefaultMode(modes, autonomousDefault) ?? 'build';\n\n const validIds = new Set(modes.map((m) => m.id));\n\n if (rawMode === 'build' || validIds.has(rawMode)) {\n if (rawMode === 'plan' || rawMode === 'build') return rawMode;\n const modeObj = modes.find((m) => m.id === rawMode);\n if (modeObj && modeConflictsWithToggle(modeObj, autonomousDefault)) {\n const fallback = resolveDefaultMode(modes, autonomousDefault);\n return fallback ?? 'build';\n }\n return rawMode;\n }\n\n const fallback = resolveDefaultMode(modes, autonomousDefault);\n return fallback ?? 'build';\n}\n","import { Task, createTask, TaskModelAssignment, RunnerId, type ValidationContext, type ValidationResult } from '../models/Task';\nimport { extractObjectsWithKey, stripTrailingCommas, escapeControlCharsInStrings, PlanParseError, PLAN_ENVELOPE_KEY } from './JsonExtractor';\nimport { resolveTaskMode, type RunnerModeInfo } from './ModeResolver';\n\nexport function parsePlanJson(\n raw: string,\n runners: RunnerId[],\n runnerModes?: Record<RunnerId, RunnerModeInfo[]>,\n autonomousDefault = true,\n): Task[] {\n const { matches, fallback, sawUnbalanced } = extractObjectsWithKey(raw, PLAN_ENVELOPE_KEY);\n\n // A reply can carry several tasks-keyed objects — a schema echo from the\n // prompt, an inline draft, then the real plan. The model's LAST emission is\n // its final answer, so candidates are tried back to front and the first one\n // that fully parses and validates wins.\n const candidates = matches.length > 0 ? [...matches].reverse() : [fallback.json];\n\n let lastError: PlanParseError | null = null;\n for (const json of candidates) {\n try {\n return parsePlanObject(json, raw, runners, runnerModes, autonomousDefault);\n } catch (err) {\n if (!(err instanceof PlanParseError)) throw err;\n // Prefer surfacing the error from the most plan-like candidate: the\n // last one carrying a tasks key (tried first).\n if (!lastError) lastError = err;\n }\n }\n\n // No usable tasks object anywhere, but an object ran off the end of the\n // text: the plan was almost certainly cut off mid-stream.\n if (matches.length === 0 && sawUnbalanced) {\n throw new PlanParseError(\n 'Plan response appears truncated — the model likely hit its output length limit before finishing the JSON.',\n raw,\n { truncated: true },\n );\n }\n throw lastError ?? new PlanParseError('Invalid plan: missing tasks array', raw);\n}\n\nfunction parsePlanObject(\n json: string,\n raw: string,\n runners: RunnerId[],\n runnerModes?: Record<RunnerId, RunnerModeInfo[]>,\n autonomousDefault = true,\n): Task[] {\n const cleaned = stripTrailingCommas(escapeControlCharsInStrings(json));\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(cleaned);\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n throw new PlanParseError(`Plan response was not valid JSON: ${detail}`, raw);\n }\n\n const result = validatePlanTasks(parsed, runners, runnerModes, autonomousDefault);\n if (result.ok) return result.tasks;\n const [first] = result.errors;\n // An envelope problem (no tasks array, an empty one) keeps the generic\n // re-emit; only a rule broken by a task is worth naming in the corrective.\n throw new PlanParseError(first.message, raw, { semantic: first.taskId !== undefined });\n}\n\n/** One reason a plan was refused, pinned to the task and field it is about. */\nexport interface PlanTaskError {\n /** Absent when the envelope itself is wrong rather than one of its tasks. */\n taskId?: string;\n field: string;\n message: string;\n}\n\nexport type PlanTasksResult = { ok: true; tasks: Task[] } | { ok: false; errors: PlanTaskError[] };\n\n/**\n * Every check a plan's tasks must pass, on an already-parsed `{ tasks }`\n * object — what a plan is held to whichever channel it arrived on. All\n * problems are reported, in the order the text path has always met them, so\n * the first is the one its corrective names.\n */\nexport function validatePlanTasks(\n obj: unknown,\n runners: RunnerId[],\n runnerModes?: Record<RunnerId, RunnerModeInfo[]>,\n autonomousDefault = true,\n): PlanTasksResult {\n const rawTasks = isRecord(obj) ? obj.tasks : undefined;\n if (!Array.isArray(rawTasks)) {\n return { ok: false, errors: [{ field: 'tasks', message: 'Invalid plan: missing tasks array' }] };\n }\n if (rawTasks.length === 0) {\n return { ok: false, errors: [{ field: 'tasks', message: 'Plan contained no tasks' }] };\n }\n\n const tasks = rawTasks.map((t) => parseTask(asRecord(t), runners, runnerModes, autonomousDefault));\n\n const errors = verticalSliceErrors(tasks);\n for (const t of tasks) {\n if (!runners.includes(t.assignedRunner)) {\n errors.push({\n taskId: t.id,\n field: 'assignedRunner',\n message: `Task \"${t.title}\" has invalid assignedRunner \"${t.assignedRunner}\". Expected one of: ${runners.join(', ')}`,\n });\n }\n }\n\n return errors.length > 0 ? { ok: false, errors } : { ok: true, tasks };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n// A non-object entry reads as an empty task, so the shape checks name it\n// instead of the parser throwing a TypeError out of the validator.\nfunction asRecord(value: unknown): Record<string, unknown> {\n return isRecord(value) ? value : {};\n}\n\n/**\n * Whether a reply that failed {@link parsePlanJson} actually LOOKED like a\n * plan attempt — a balanced tasks-keyed object, or JSON that got cut off.\n * Distinguishes \"the model tried to emit a plan and botched it\" (worth a\n * corrective retry) from prose that merely mentions `\"tasks\"` (leave alone).\n */\nexport function looksLikePlanAttempt(raw: string): boolean {\n const { matches, sawUnbalanced } = extractObjectsWithKey(raw, PLAN_ENVELOPE_KEY);\n if (matches.length > 0) return true;\n return sawUnbalanced && raw.includes(`\"${PLAN_ENVELOPE_KEY}\"`);\n}\n\n/**\n * The parent's slice classification, handed to `ai` subtasks that omit their\n * own. Budget models emit sub-steps as bare `{id, order, title, description,\n * type}` — neither prompt has ever shown a populated `subtasks` entry — and the\n * recursive slice contract then rejected the whole plan. Inheriting invents no\n * information: an `ai` sub-step of an AFK slice is AFK. Deliberately NOT a\n * blanket `'AFK'` default, which would silently strip a human gate the planner\n * intended (`sliceType` is what puts ORDEWELL_CHECKPOINT in the runner prompt,\n * and subtasks are schedulable — PlanStore.rebuild flattens them into\n * _allTasks). `type: 'user'` subtasks inherit nothing and must still declare\n * HITL themselves.\n */\ntype InheritedSlice = { sliceType?: Task['sliceType']; autonomy?: Task['autonomy'] };\n\nfunction parseTask(\n raw: Record<string, unknown>,\n runners: RunnerId[],\n runnerModes?: Record<RunnerId, RunnerModeInfo[]>,\n autonomousDefault = true,\n inherited?: InheritedSlice,\n): Task {\n const assignedRunner = typeof raw.assignedRunner === 'string' ? raw.assignedRunner : (runners[0] ?? 'claude-code');\n const taskType = (raw.type === 'user' ? 'user' : 'ai') as Task['type'];\n const title = String(raw.title ?? '');\n const description = String(raw.description ?? '');\n // Explicit child values always win; inheritance only fills a gap, and only\n // for `ai` tasks.\n const autonomy = taskType === 'ai' && typeof raw.autonomy === 'string' && (raw.autonomy === 'AFK' || raw.autonomy === 'HITL')\n ? raw.autonomy\n : (taskType === 'ai' ? inherited?.autonomy : undefined);\n const sliceType = typeof raw.sliceType === 'string' && (raw.sliceType === 'HITL' || raw.sliceType === 'AFK')\n ? raw.sliceType\n : (taskType === 'ai' ? inherited?.sliceType : undefined);\n return createTask({\n id: String(raw.id ?? ''),\n order: Number(raw.order ?? 0),\n title,\n description,\n type: taskType,\n dependencies: Array.isArray(raw.dependencies)\n ? raw.dependencies.map(String)\n : [],\n // The planner sometimes omits `prompt` on an AI task while still filling in\n // description/title — same fallback TaskOps.applyTaskOps uses for `add`, so\n // a task never silently ends up unschedulable (getReadyTasks requires prompt).\n prompt: raw.prompt ? String(raw.prompt) : (description || title || undefined),\n userSteps: Array.isArray(raw.userSteps)\n ? raw.userSteps.map(asRecord).map((s) => ({\n order: Number(s.order ?? 0),\n instruction: String(s.instruction ?? ''),\n completed: false,\n }))\n : undefined,\n subtasks: Array.isArray(raw.subtasks)\n ? raw.subtasks.map((s: unknown) =>\n parseTask(asRecord(s), runners, runnerModes, autonomousDefault, { sliceType, autonomy }))\n : [],\n assignedModel: raw.assignedModel\n ? {\n modelId: String((raw.assignedModel as Record<string, unknown>).modelId ?? ''),\n modelLabel: String((raw.assignedModel as Record<string, unknown>).modelLabel ?? ''),\n thinkingEffort: (raw.assignedModel as Record<string, unknown>).thinkingEffort as TaskModelAssignment['thinkingEffort'],\n }\n : undefined,\n assignedRunner,\n thinkingEffort: raw.thinkingEffort ? String(raw.thinkingEffort) : undefined,\n taskMode: resolveTaskMode(\n raw.taskMode !== undefined ? String(raw.taskMode) : undefined,\n assignedRunner,\n runnerModes,\n autonomousDefault,\n ),\n autonomy,\n sliceType,\n userStoriesCovered: Array.isArray(raw.userStoriesCovered)\n ? raw.userStoriesCovered.map(String)\n : undefined,\n // A subtask runs with its parent, so only a top-level AI task carries it (ADR-0020).\n ops: !inherited && taskType === 'ai' && raw.ops === true,\n });\n}\n\nfunction verticalSliceErrors(tasks: Task[], parentTitle?: string): PlanTaskError[] {\n // Without this the message names a title that appears nowhere in the plan's\n // top-level `tasks` array, and neither the corrective nor a human can find\n // the offending object.\n const where = (t: Task) => (parentTitle ? `subtask \"${t.title}\" of \"${parentTitle}\"` : `Task \"${t.title}\"`);\n const errors: PlanTaskError[] = [];\n\n for (const t of tasks) {\n const fail = (field: string, message: string) => errors.push({ taskId: t.id, field, message });\n\n if (!t.sliceType) {\n fail('sliceType', `${where(t)} is missing sliceType. Every task must specify sliceType (\"AFK\" or \"HITL\").`);\n }\n\n if (t.type === 'ai' && !t.autonomy) {\n fail('autonomy', `AI ${where(t)} is missing autonomy. Every AI task must specify autonomy (\"AFK\" or \"HITL\").`);\n }\n\n if (t.autonomy === 'AFK' && t.userSteps && t.userSteps.length > 0) {\n fail('userSteps', `${where(t)} has autonomy \"AFK\" but contains userSteps. AFK tasks must not have user touchpoints.`);\n }\n\n if (t.type === 'user' && t.sliceType && t.sliceType !== 'HITL') {\n fail('sliceType', `User ${where(t)} has sliceType \"${t.sliceType}\". User tasks must have sliceType \"HITL\".`);\n }\n\n if (t.subtasks.length > 0) {\n errors.push(...verticalSliceErrors(t.subtasks, t.title));\n }\n }\n return errors;\n}\n\nexport function checkUniqueIds(ctx: ValidationContext): ValidationResult {\n const seen = new Set<string>();\n const errors: string[] = [];\n for (const t of ctx.newPending) {\n if (seen.has(t.id)) {\n errors.push(`Duplicate task ID in modified plan: ${t.id}`);\n }\n seen.add(t.id);\n }\n return { valid: errors.length === 0, errors };\n}\n\nexport function checkNoCycles(ctx: ValidationContext): ValidationResult {\n const ids = new Set(ctx.newPending.map((t) => t.id));\n const adj = new Map<string, string[]>();\n for (const t of ctx.newPending) {\n adj.set(t.id, t.dependencies.filter((d) => ids.has(d)));\n }\n\n const visited = new Set<string>();\n const inStack = new Set<string>();\n const errors: string[] = [];\n\n function dfs(node: string): boolean {\n if (inStack.has(node)) {\n errors.push(`Cycle detected in task dependencies involving task: ${node}`);\n return true;\n }\n if (visited.has(node)) return false;\n visited.add(node);\n inStack.add(node);\n for (const dep of adj.get(node) ?? []) {\n if (dfs(dep)) return true;\n }\n inStack.delete(node);\n return false;\n }\n\n for (const id of ids) {\n if (dfs(id)) break;\n }\n\n return { valid: errors.length === 0, errors };\n}\n\nexport function checkDepsResolve(ctx: ValidationContext): ValidationResult {\n const existingIds = new Set<string>();\n for (const t of ctx.executionLog) existingIds.add(t.id);\n for (const t of ctx.newPending) existingIds.add(t.id);\n\n const errors: string[] = [];\n for (const t of ctx.newPending) {\n for (const dep of t.dependencies) {\n if (!existingIds.has(dep)) {\n errors.push(`Task \"${t.title}\" depends on \"${dep}\" which is not in the execution log or pending tasks`);\n }\n }\n }\n return { valid: errors.length === 0, errors };\n}\n\nexport function checkImmutableLog(ctx: ValidationContext): ValidationResult {\n const logIds = new Map(ctx.executionLog.map((t) => [t.id, t]));\n\n const errors: string[] = [];\n\n for (const t of ctx.newPending) {\n const logEntry = logIds.get(t.id);\n if (logEntry) {\n if (logEntry.status === 'completed' && logEntry.finalized) {\n errors.push(`Task \"${t.id}\" was already completed in the execution log and cannot be re-added`);\n }\n }\n }\n\n return { valid: errors.length === 0, errors };\n}\n\nexport function checkInProgress(ctx: ValidationContext): ValidationResult {\n const oldInProgress = new Map(\n ctx.oldPending.filter((t) => t.status === 'in_progress').map((t) => [t.id, t])\n );\n const newIds = new Set(ctx.newPending.map((t) => t.id));\n const errors: string[] = [];\n\n for (const [id, oldTask] of oldInProgress) {\n if (!newIds.has(id)) {\n errors.push(`In-progress task \"${oldTask.title}\" was removed from the modified plan`);\n continue;\n }\n const newTask = ctx.newPending.find((t) => t.id === id)!;\n if (newTask.prompt !== oldTask.prompt || newTask.assignedModel?.modelId !== oldTask.assignedModel?.modelId) {\n errors.push(`In-progress task \"${oldTask.title}\" was modified in the new plan`);\n }\n const oldDeps = new Set(oldTask.dependencies);\n const newDeps = new Set(newTask.dependencies);\n if (oldDeps.size !== newDeps.size || [...oldDeps].some((d) => !newDeps.has(d))) {\n errors.push(`In-progress task \"${oldTask.title}\" had dependencies modified`);\n }\n }\n\n return { valid: errors.length === 0, errors };\n}\n\nexport function validatePlanModification(ctx: ValidationContext): ValidationResult {\n const checks = [\n checkUniqueIds,\n checkNoCycles,\n checkDepsResolve,\n checkImmutableLog,\n checkInProgress,\n ];\n const allErrors: string[] = [];\n for (const check of checks) {\n const result = check(ctx);\n allErrors.push(...result.errors);\n }\n return { valid: allErrors.length === 0, errors: allErrors };\n}\n","import { stripModelNoise } from './JsonExtractor';\n\n/** A task as seen in a still-streaming plan: its title (possibly partial) and whether its object has closed. */\nexport interface PartialPlanTask {\n title: string;\n status: 'streaming' | 'complete';\n /** Assigned model label, once it has streamed in — for the live row's chip. */\n model?: string;\n /** Task mode (\"build\"|\"plan\"), once it has streamed in — for the live row's chip. */\n mode?: string;\n}\n\n/**\n * Parse a partial (still-streaming) plan-JSON string into an ordered list of task\n * rows for the live progress view. Pure and lenient: it walks the characters of the\n * `tasks` array, emitting one row per task object once it has opened, with the title\n * read incrementally and the status flipping to `complete` when the object's brace\n * closes. The currently-streaming object stays `streaming` even with a partial title.\n * The React view is a thin renderer over this — it never parses JSON itself.\n */\nexport function parsePartialPlan(partial: string): PartialPlanTask[] {\n const text = stripModelNoise(partial);\n const arrayStart = findTasksArrayStart(text);\n if (arrayStart === -1) return [];\n\n const tasks: PartialPlanTask[] = [];\n let depth = 0; // brace depth relative to a task object (0 = between objects)\n let objText = ''; // accumulated text of the in-progress task object\n let inString = false;\n let escaped = false;\n\n for (let i = arrayStart; i < text.length; i++) {\n const ch = text[i];\n if (depth > 0) objText += ch;\n\n if (inString) {\n if (escaped) escaped = false;\n else if (ch === '\\\\') escaped = true;\n else if (ch === '\"') inString = false;\n continue;\n }\n if (ch === '\"') { inString = true; continue; }\n if (ch === ']' && depth === 0) break; // end of the tasks array\n if (ch === '{') {\n if (depth === 0) objText = '{';\n depth++;\n } else if (ch === '}') {\n depth--;\n if (depth === 0) {\n tasks.push(rowFromObject(objText, 'complete'));\n objText = '';\n }\n }\n }\n\n // A task object that opened but never closed is the row currently streaming in.\n if (depth > 0) tasks.push(rowFromObject(objText, 'streaming'));\n return tasks;\n}\n\n/** Index just after the `[` that opens the top-level `tasks` array, or -1 if not present yet. */\nfunction findTasksArrayStart(text: string): number {\n const key = /\"tasks\"\\s*:\\s*\\[/.exec(text);\n return key ? key.index + key[0].length : -1;\n}\n\n/** Build a live row from a (possibly unterminated) task-object fragment. */\nfunction rowFromObject(objText: string, status: PartialPlanTask['status']): PartialPlanTask {\n const model = stringField(objText, 'modelLabel');\n const mode = stringField(objText, 'taskMode');\n return {\n title: titleFromObject(objText),\n status,\n ...(model ? { model } : {}),\n ...(mode ? { mode } : {}),\n };\n}\n\n/** Read the `title` value out of a (possibly unterminated) task-object fragment. */\nfunction titleFromObject(objText: string): string {\n const m = /\"title\"\\s*:\\s*\"((?:[^\"\\\\]|\\\\.)*)/.exec(objText);\n if (!m) return '';\n // The captured group may include a trailing closing quote's content only up to an\n // unescaped quote; for a completed value that's the whole title, for a streaming\n // one it's whatever has arrived so far.\n return m[1].replace(/\\\\\"/g, '\"');\n}\n\n/** Read a fully-streamed (closing-quote present) string field's value, or undefined. */\nfunction stringField(objText: string, key: string): string | undefined {\n const m = new RegExp(`\"${key}\"\\\\s*:\\\\s*\"((?:[^\"\\\\\\\\]|\\\\\\\\.)*)\"`).exec(objText);\n return m ? m[1].replace(/\\\\\"/g, '\"') : undefined;\n}\n"],"mappings":"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","names":["fallback"]}
|