immune-brain 5.3.0 → 5.5.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/README.md +4 -4
- package/README.zh-CN.md +4 -4
- package/package.json +2 -1
- package/plugins/immune-brain/.claude-plugin/plugin.json +1 -1
- package/plugins/immune-brain/.pi-extension/imm-canary-enroll.ts +54 -70
- package/plugins/immune-brain/.pi-extension/imm-canary-work.ts +163 -28
- package/plugins/immune-brain/.pi-extension/imm-unattended-batch.ts +71 -10
- package/plugins/immune-brain/.pi-extension/pi-canary-tool-failure.ts +1 -1
- package/plugins/immune-brain/.pi-extension/pi-run-continuation.ts +161 -0
- package/plugins/immune-brain/agents/immune-brain-reviewer.md +26 -2
- package/plugins/immune-brain/dist/BASELINE.md +13 -1
- package/plugins/immune-brain/dist/claude/mcp-server.mjs +16130 -12734
- package/plugins/immune-brain/dist/docs/reference/code-quality-guard.md +3 -1
- package/plugins/immune-brain/dist/docs/reference/immune-brain-config.md +41 -1
- package/plugins/immune-brain/dist/docs/reference/planning-quality-gate.md +1 -1
- package/plugins/immune-brain/dist/imm-planner.md +57 -16
- package/plugins/immune-brain/dist/imm-run-batch.md +398 -0
- package/plugins/immune-brain/dist/imm-run.md +89 -344
- package/plugins/immune-brain/dist/role-prompts/code-review.md +26 -2
- package/plugins/immune-brain/dist/role-prompts/executor.md +35 -10
- package/plugins/immune-brain/hooks/hooks.json +21 -1
- package/plugins/immune-brain/runtime/assurance/coordinator.ts +203 -13
- package/plugins/immune-brain/runtime/assurance/delivery_workspace.ts +2 -1
- package/plugins/immune-brain/runtime/assurance/enrollment_git_base.ts +99 -14
- package/plugins/immune-brain/runtime/assurance/phase_entry.ts +1 -7
- package/plugins/immune-brain/runtime/assurance/qa.ts +126 -43
- package/plugins/immune-brain/runtime/assurance/qa_findings.ts +8 -0
- package/plugins/immune-brain/runtime/assurance/review_evidence.ts +48 -0
- package/plugins/immune-brain/runtime/assurance/run_continuation.ts +284 -0
- package/plugins/immune-brain/runtime/assurance/verdict_authority.ts +46 -4
- package/plugins/immune-brain/runtime/assurance/verification.ts +83 -35
- package/plugins/immune-brain/runtime/assurance/workflow_autocommit.ts +222 -0
- package/plugins/immune-brain/runtime/claude/interaction.ts +11 -2
- package/plugins/immune-brain/runtime/claude/kernel_ports.ts +199 -48
- package/plugins/immune-brain/runtime/claude/lane_guard.ts +8 -15
- package/plugins/immune-brain/runtime/claude/mcp_server.ts +105 -9
- package/plugins/immune-brain/runtime/claude/run_continuation.ts +274 -0
- package/plugins/immune-brain/runtime/commands/kernel.ts +41 -103
- package/plugins/immune-brain/runtime/github_issue_tracker.ts +60 -2
- package/plugins/immune-brain/runtime/kernel/application.ts +4 -1
- package/plugins/immune-brain/runtime/kernel/assurance_projection.ts +103 -20
- package/plugins/immune-brain/runtime/kernel/canary_application.ts +57 -7
- package/plugins/immune-brain/runtime/kernel/completion.ts +28 -4
- package/plugins/immune-brain/runtime/kernel/enrollment.ts +48 -8
- package/plugins/immune-brain/runtime/kernel/intent.ts +169 -104
- package/plugins/immune-brain/runtime/kernel/reducer.ts +136 -6
- package/plugins/immune-brain/runtime/kernel/risk_floor.ts +286 -0
- package/plugins/immune-brain/runtime/kernel/storage_layout_migration.ts +83 -1
- package/plugins/immune-brain/runtime/kernel/storage_paths.ts +1 -1
- package/plugins/immune-brain/runtime/kernel/types.ts +49 -3
- package/plugins/immune-brain/runtime/kernel/validation.ts +147 -7
- package/plugins/immune-brain/runtime/loop_contract.ts +5 -0
- package/plugins/immune-brain/runtime/plan_core.ts +15 -8
- package/plugins/immune-brain/runtime/plugin_source_skew.ts +58 -0
- package/plugins/immune-brain/runtime/plugin_version.ts +1 -1
- package/plugins/immune-brain/runtime/prompts/code-review.md +26 -2
- package/plugins/immune-brain/runtime/prompts/executor.md +35 -10
- package/plugins/immune-brain/runtime/unattended/batch_delegation.ts +5 -3
- package/plugins/immune-brain/runtime/unattended/batch_disposition.ts +40 -10
- package/plugins/immune-brain/runtime/unattended/batch_final_verification.ts +57 -3
- package/plugins/immune-brain/runtime/unattended/batch_git.ts +424 -66
- package/plugins/immune-brain/runtime/unattended/batch_integration.ts +2 -1
- package/plugins/immune-brain/runtime/unattended/batch_kernel_port.ts +13 -0
- package/plugins/immune-brain/runtime/unattended/batch_lanes.ts +43 -24
- package/plugins/immune-brain/runtime/unattended/batch_plan.ts +6 -2
- package/plugins/immune-brain/runtime/unattended/batch_preflight.ts +102 -41
- package/plugins/immune-brain/runtime/unattended/batch_reasons.ts +9 -3
- package/plugins/immune-brain/runtime/unattended/batch_reconfirmation.ts +9 -9
- package/plugins/immune-brain/runtime/unattended/batch_runner.ts +90 -32
- package/plugins/immune-brain/runtime/unattended/batch_state.ts +102 -4
- package/plugins/immune-brain/runtime/unattended/parent_delivery_consolidation.ts +248 -0
- package/plugins/immune-brain/runtime/workspace_scope.ts +126 -18
- package/plugins/immune-brain/skills/BASELINE.md +13 -1
- package/plugins/immune-brain/skills/imm-planner/SKILL.md +5 -0
- package/plugins/immune-brain/skills/imm-run/SKILL.md +12 -8
package/README.md
CHANGED
|
@@ -556,9 +556,9 @@ Key invariants:
|
|
|
556
556
|
|
|
557
557
|
## Unattended Batch Runs
|
|
558
558
|
|
|
559
|
-
|
|
559
|
+
Enter `imm-run <Parent Issue>` to execute its complete approved plan through the Host's `start_unattended_batch` tool and native authorization. Enter `imm-run <Slice/Child Issue>` to execute only that Slice after prerequisite delivery checks; it starts no siblings or predecessors.
|
|
560
560
|
|
|
561
|
-
|
|
561
|
+
The Parent chooses **Managed Serial Mode** or **Parallel Batch Lanes** before confirmation, using dependency readiness, scope conflicts, Lane capacity and supervised Host capability. Without Lane supervision it runs serially in the same Host. Status questions preserve the binding; explicit cancellation releases continuation.
|
|
562
562
|
|
|
563
563
|
### 1. Batch Execution Modes Overview
|
|
564
564
|
|
|
@@ -573,9 +573,9 @@ Immune-Brain supports two batch execution modes: **Default Serial Mode** and **P
|
|
|
573
573
|
|
|
574
574
|
### 2. Batch Authority & Invariants
|
|
575
575
|
|
|
576
|
-
- **Explicit Entry & Single Authorization:**
|
|
576
|
+
- **Explicit Entry & Single Authorization:** Parent selection invokes `start_unattended_batch` directly; a standalone Task or Child uses single-task Enrollment. Critical-only and delivered-only Parents use native task gates and final observations without an empty batch grant. The native gate (Pi TUI dialog or Claude MCP elicitation) displays the ordered child list and global `plan_digest`; this single user confirmation constitutes complete Batch Authorization.
|
|
577
577
|
- **Child Authority Invariance:** A batch merely bundles authorization scope without weakening engineering rigor. Every child is still individually enrolled, scope-frozen, QA-verified via authentic child processes, reviewed in isolation, and settled with its own `TaskRecord`. A batch is a scope of authorization, not a new authority layer.
|
|
578
|
-
- **Deterministic Boundaries:**
|
|
578
|
+
- **Deterministic Boundaries:** Ordinary children use batch authorization; ready `critical` children use separate native Enrollment. Ordinary failures receive bounded repair. A blocker parks its dependent branch while independent work continues. Parent success and closure require every necessary delivery integrated and final verification passing on the final HEAD; later code defects receive a validated repair candidate and fresh native Enrollment. Runners never push, open PRs, or make arbitrary decisions.
|
|
579
579
|
|
|
580
580
|
### 3. Parallel Batch Lanes Lifecycle & Architecture
|
|
581
581
|
|
package/README.zh-CN.md
CHANGED
|
@@ -559,9 +559,9 @@ flowchart TD
|
|
|
559
559
|
|
|
560
560
|
## 无人值守批次运行
|
|
561
561
|
|
|
562
|
-
|
|
562
|
+
输入 `imm-run <Parent Issue>`,会自动选择完整已批准计划,通过 Host 的 `start_unattended_batch` 和 native 授权执行。输入 `imm-run <Slice/Child Issue>` 则先检查前置交付,只执行该 Slice,不启动前置或兄弟任务。
|
|
563
563
|
|
|
564
|
-
|
|
564
|
+
Parent 在确认前根据依赖、scope 冲突、Lane 容量及受监督 Host 能力,选择 **Managed 串行模式** 或 **多 Lane 并行模式**;缺少 Lane supervision 时在同一 Host 串行执行。状态询问保留运行绑定,显式取消解除续接。
|
|
565
565
|
|
|
566
566
|
### 1. 批次运行模式概览
|
|
567
567
|
|
|
@@ -576,9 +576,9 @@ flowchart TD
|
|
|
576
576
|
|
|
577
577
|
### 2. 批次授权与运行红线
|
|
578
578
|
|
|
579
|
-
- **入口显式且单一授权:**
|
|
579
|
+
- **入口显式且单一授权:** Parent 入口直接调用 `start_unattended_batch`;独立 Task 和 Child 走单任务 Enrollment。critical-only 和 delivered-only Parent 使用单任务 native gate 和最终验证观察,不制造空批次授权。调用时由原生 gate(Pi TUI 弹窗或 Claude MCP elicitation)一次性展示有序任务清单与全局 `plan_digest`,用户的单次确认即为整批执行提供完备授权。
|
|
580
580
|
- **Child Authority 守恒:** 批次仅代表授权范围的聚合,绝非降低工程标准。每个 child 依然由 Kernel 单独执行 Enrollment、物理 Scope 冻结、真实子进程 QA、隔离 Review 与独立的 `TaskRecord` 结算。批次只是一次授权的覆盖范围,不是新的授权层级。
|
|
581
|
-
- **确定性执行边界:**
|
|
581
|
+
- **确定性执行边界:** 普通 child 使用批次授权,已就绪的 `critical` child 单独 native Enrollment。普通失败自动进行有界修复;阻塞只停放其依赖分支,独立任务继续。所有必需交付集成、最终 HEAD 验证通过后才报告 Parent 成功并关闭 Issue;结算后发现的代码缺陷先生成、验证修复候选,再打开新的 native Enrollment。批次运行器不擅自 push、不开 PR、不代替用户结算决策。
|
|
582
582
|
|
|
583
583
|
### 3. 多 Lane 并行流水线与架构(Parallel Batch Lanes)
|
|
584
584
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "immune-brain",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.5.1",
|
|
4
4
|
"description": "Immune-Brain agent skill system",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public",
|
|
@@ -83,6 +83,7 @@
|
|
|
83
83
|
"plugins/immune-brain/runtime/role_prompt_bridge.ts",
|
|
84
84
|
"plugins/immune-brain/runtime/loop_contract.ts",
|
|
85
85
|
"plugins/immune-brain/runtime/plugin_version.ts",
|
|
86
|
+
"plugins/immune-brain/runtime/plugin_source_skew.ts",
|
|
86
87
|
"plugins/immune-brain/runtime/assurance",
|
|
87
88
|
"plugins/immune-brain/runtime/unattended",
|
|
88
89
|
"plugins/immune-brain/runtime/claude",
|
|
@@ -15,16 +15,20 @@ import { resolve } from "node:path";
|
|
|
15
15
|
// from the Kernel's own prepare module.
|
|
16
16
|
import { LITERAL_USER_ACTOR_ID } from "../runtime/kernel/actor_identity";
|
|
17
17
|
import { createEnrollmentAuthorityRegistry } from "../runtime/kernel/enrollment_authority";
|
|
18
|
+
import { assertIsolatedTaskPrerequisites } from "../runtime/github_issue_tracker";
|
|
18
19
|
import { preparePiCanary, revalidatePiCanary } from "../runtime/assurance/enrollment";
|
|
19
20
|
import { evaluateCanaryEligibility } from "../runtime/kernel/canary_eligibility";
|
|
20
|
-
import { enrollTask, EnrollmentRehearsalError } from "../runtime/kernel/enrollment";
|
|
21
|
+
import { enrollmentScopeDisclosure, enrollTask, EnrollmentRehearsalError } from "../runtime/kernel/enrollment";
|
|
21
22
|
import { reconcileKernelAuthority, withKernelStoreLock } from "../runtime/kernel/storage";
|
|
22
23
|
import { inspectStorageLayout } from "../runtime/kernel/storage_paths";
|
|
23
|
-
import {
|
|
24
|
+
import { commitPendingMigrationDiff, migrateAndCommitLegacyLayout } from "../runtime/kernel/storage_layout_migration";
|
|
24
25
|
import {
|
|
26
|
+
commitEnrollmentPreconditions,
|
|
27
|
+
commitUnbornEnrollmentPreconditions,
|
|
25
28
|
inspectEnrollmentGitBase,
|
|
26
29
|
enrollmentGitBaseNotice,
|
|
27
30
|
initializeEnrollmentGitBase,
|
|
31
|
+
preconditionCommitNote,
|
|
28
32
|
} from "../runtime/assurance/enrollment_git_base";
|
|
29
33
|
import { piRunEntryRefusal, readTaskIntentForRecord } from "./imm-canary-work";
|
|
30
34
|
import {
|
|
@@ -280,6 +284,8 @@ async function classifyCommitFailure(
|
|
|
280
284
|
);
|
|
281
285
|
}
|
|
282
286
|
|
|
287
|
+
const terminalWithoutCommitNote = terminal;
|
|
288
|
+
|
|
283
289
|
async function executeForegroundEnrollment(
|
|
284
290
|
root: string,
|
|
285
291
|
action: EnrollmentAction,
|
|
@@ -293,6 +299,14 @@ async function executeForegroundEnrollment(
|
|
|
293
299
|
): Promise<EnrollmentTerminal> {
|
|
294
300
|
let stage = "preparing";
|
|
295
301
|
let gitBaseNote = "";
|
|
302
|
+
// Every unsuccessful exit reports the Git effects that preceded authority.
|
|
303
|
+
const terminal: typeof terminalWithoutCommitNote = (action, taskId, state, stage, summary, nextAction) => {
|
|
304
|
+
if (state !== "completed" && gitBaseNote) {
|
|
305
|
+
if (summary.endsWith(gitBaseNote)) summary = summary.slice(0, -gitBaseNote.length);
|
|
306
|
+
summary = `${summary.slice(0, 4_096 - gitBaseNote.length)}${gitBaseNote}`;
|
|
307
|
+
}
|
|
308
|
+
return terminalWithoutCommitNote(action, taskId, state, stage, summary, nextAction);
|
|
309
|
+
};
|
|
296
310
|
const progress = (nextStage: string, summary: string) => {
|
|
297
311
|
stage = nextStage;
|
|
298
312
|
const update = updateResult(action, taskId, nextStage, summary);
|
|
@@ -314,75 +328,32 @@ async function executeForegroundEnrollment(
|
|
|
314
328
|
const now = new Date().toISOString();
|
|
315
329
|
let taskIntent: Awaited<ReturnType<typeof readTaskIntentForRecord>>;
|
|
316
330
|
|
|
317
|
-
//
|
|
318
|
-
// mutation boundary. Kernel transaction markers recover under the
|
|
319
|
-
// store lock; the one-release migrator relocates an owner-free legacy
|
|
320
|
-
// layout and stops, and the literal user retries after committing the
|
|
321
|
-
// affected migration diff. Repreparation never proceeds on a dirty
|
|
322
|
-
// or blocked layout.
|
|
331
|
+
// Recover markers first; only a pending diff or supported legacy import may advance.
|
|
323
332
|
{
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
if (inspection.layout === "ready") return undefined;
|
|
341
|
-
if (
|
|
342
|
-
inspection.layout === "migration_required" ||
|
|
343
|
-
inspection.layout === "recovery_required"
|
|
344
|
-
) {
|
|
345
|
-
const migration = await migrateLegacyLayout(root);
|
|
346
|
-
if (migration.outcome === "migrated")
|
|
347
|
-
return terminal(
|
|
348
|
-
action,
|
|
349
|
-
taskId,
|
|
350
|
-
"blocked",
|
|
351
|
-
stage,
|
|
352
|
-
`Legacy storage migrated (${migration.affected_paths.length} paths); commit the affected migration diff and retry enrollment`,
|
|
353
|
-
"commit .imm/audit/** and .imm/legacy paths, then retry",
|
|
354
|
-
);
|
|
355
|
-
if (migration.outcome === "migration_uncommitted")
|
|
356
|
-
return terminal(
|
|
357
|
-
action,
|
|
358
|
-
taskId,
|
|
359
|
-
"blocked",
|
|
360
|
-
stage,
|
|
361
|
-
`Migration completed but affected paths are uncommitted: ${migration.affected_paths.join(", ")}`,
|
|
362
|
-
"commit the affected migration diff, then retry",
|
|
363
|
-
);
|
|
364
|
-
return terminal(
|
|
365
|
-
action,
|
|
366
|
-
taskId,
|
|
367
|
-
"blocked",
|
|
368
|
-
stage,
|
|
369
|
-
`Enrollment blocked by storage layout (${migration.outcome}): ${migration.reason ?? inspection.reason ?? ""}`,
|
|
370
|
-
"resolve the reported layout condition and retry",
|
|
371
|
-
);
|
|
372
|
-
}
|
|
373
|
-
return terminal(
|
|
374
|
-
action,
|
|
375
|
-
taskId,
|
|
376
|
-
"blocked",
|
|
377
|
-
stage,
|
|
378
|
-
`Enrollment blocked by storage layout (${inspection.layout}): ${inspection.reason ?? ""}`,
|
|
379
|
-
"resolve the reported layout condition and retry",
|
|
380
|
-
);
|
|
381
|
-
};
|
|
382
|
-
const blocked = await recoverLayout();
|
|
383
|
-
if (blocked) return blocked;
|
|
333
|
+
let inspection = inspectStorageLayout(root);
|
|
334
|
+
if (inspection.layout === "migration_uncommitted") {
|
|
335
|
+
gitBaseNote += preconditionCommitNote(commitPendingMigrationDiff(root, signal));
|
|
336
|
+
inspection = inspectStorageLayout(root);
|
|
337
|
+
}
|
|
338
|
+
if (inspection.layout === "migration_required") {
|
|
339
|
+
const migration = migrateAndCommitLegacyLayout(root, signal);
|
|
340
|
+
for (const commit of migration.commits)
|
|
341
|
+
gitBaseNote += preconditionCommitNote({ committed: true, commit, paths: migration.affected_paths });
|
|
342
|
+
if (migration.outcome !== "migrated" && migration.outcome !== "already_migrated")
|
|
343
|
+
return terminal(action, taskId, "blocked", stage, `Enrollment blocked by storage layout (${migration.outcome}): ${migration.reason ?? ""}`, "resolve the reported layout condition and retry");
|
|
344
|
+
inspection = inspectStorageLayout(root);
|
|
345
|
+
}
|
|
346
|
+
if (inspection.layout !== "ready")
|
|
347
|
+
return terminal(action, taskId, "blocked", stage, `Enrollment blocked by storage layout (${inspection.layout}): ${inspection.reason ?? ""}`, "resolve the reported layout condition and retry");
|
|
348
|
+
await withKernelStoreLock(root, () => undefined);
|
|
384
349
|
}
|
|
385
350
|
|
|
351
|
+
// Commit the task's own dirty preconditions first, so every read and the
|
|
352
|
+
// confirmation below bind the HEAD that results. An owned workspace
|
|
353
|
+
// commits nothing.
|
|
354
|
+
gitBaseNote += preconditionCommitNote(await commitEnrollmentPreconditions(root, taskId, signal));
|
|
355
|
+
signal.throwIfAborted();
|
|
356
|
+
|
|
386
357
|
try {
|
|
387
358
|
taskIntent = await readTaskIntentForRecord(root, taskId);
|
|
388
359
|
} catch (error) {
|
|
@@ -438,6 +409,7 @@ async function executeForegroundEnrollment(
|
|
|
438
409
|
`task ${taskId} is terminal in this worktree`,
|
|
439
410
|
"inspect authority state; do not retry enrollment",
|
|
440
411
|
);
|
|
412
|
+
await assertIsolatedTaskPrerequisites(root, taskId);
|
|
441
413
|
let preparation = await preparePiCanary(root, { task_id: taskId, now });
|
|
442
414
|
signal.throwIfAborted();
|
|
443
415
|
if (!preparation.intent)
|
|
@@ -479,6 +451,9 @@ async function executeForegroundEnrollment(
|
|
|
479
451
|
// Enrollment binds authority to the validated intent. Acceptance descriptors
|
|
480
452
|
// execute only during post-implementation deterministic QA.
|
|
481
453
|
const confirmedContentHash = preparation.intent.content_hash;
|
|
454
|
+
// In-scope changes that already exist are shown in the gate and only the
|
|
455
|
+
// ones shown are claimed as task work on confirmation.
|
|
456
|
+
const disclosure = enrollmentScopeDisclosure(root, taskId);
|
|
482
457
|
{
|
|
483
458
|
const confirmationSummary = [
|
|
484
459
|
`Task: ${taskId}`,
|
|
@@ -487,6 +462,7 @@ async function executeForegroundEnrollment(
|
|
|
487
462
|
`Scope: ${taskIntent.intent.scope_hint.length > 0 ? taskIntent.intent.scope_hint.join(", ") : "(none)"}`,
|
|
488
463
|
`Acceptance: ${taskIntent.intent.acceptance.length} descriptor(s)`,
|
|
489
464
|
...(gitNotice ? [gitNotice] : []),
|
|
465
|
+
...(disclosure.notice ? [disclosure.notice] : []),
|
|
490
466
|
].join("\n");
|
|
491
467
|
const confirmationDetails = [
|
|
492
468
|
`Acceptance descriptors:`,
|
|
@@ -510,7 +486,7 @@ async function executeForegroundEnrollment(
|
|
|
510
486
|
);
|
|
511
487
|
if (signal.aborted) return cancelled();
|
|
512
488
|
if (!confirmed)
|
|
513
|
-
return terminal(action, taskId, "rejected", stage,
|
|
489
|
+
return terminal(action, taskId, "rejected", stage, `Enrollment confirmation was rejected; zero authority writes were requested${gitBaseNote}`, "invoke the launcher again only if enrollment is still intended");
|
|
514
490
|
}
|
|
515
491
|
{
|
|
516
492
|
let liveEarly: string | null = null;
|
|
@@ -541,7 +517,14 @@ async function executeForegroundEnrollment(
|
|
|
541
517
|
signal.throwIfAborted();
|
|
542
518
|
|
|
543
519
|
preparation = await initializeEnrollmentGitBase(root, { task_id: taskId, now }, preparation, gitBase, signal);
|
|
544
|
-
if (gitBase.state === "unborn")
|
|
520
|
+
if (gitBase.state === "unborn") {
|
|
521
|
+
gitBaseNote += `; empty initial commit ${preparation.git_base_head} remains`;
|
|
522
|
+
// The scope could not be compared with an unborn HEAD; commit it now
|
|
523
|
+
// that a base exists and bind the HEAD that results.
|
|
524
|
+
const late = await commitUnbornEnrollmentPreconditions(root, { task_id: taskId, now }, preparation, signal);
|
|
525
|
+
gitBaseNote += preconditionCommitNote(late.result);
|
|
526
|
+
preparation = late.preparation;
|
|
527
|
+
}
|
|
545
528
|
if (!preparation.intent) throw new Error("Enrollment requires a readable TaskIntent");
|
|
546
529
|
signal.throwIfAborted();
|
|
547
530
|
|
|
@@ -565,6 +548,7 @@ async function executeForegroundEnrollment(
|
|
|
565
548
|
// zero writes, and once it accepts, commit is no longer cancellable.
|
|
566
549
|
const outcome = await enrollTask(root, registry, {
|
|
567
550
|
binding,
|
|
551
|
+
disclosed_scope_paths: disclosure.paths,
|
|
568
552
|
now,
|
|
569
553
|
checkpoint: () => {
|
|
570
554
|
if (signal.aborted) return false;
|