1
0
Эх сурвалжийг харах

test(subagent): drop the vacuous fork-dedup case; align wording with the header baseline

The dedup guard pinned 'no duplicate stamp' — under the header baseline no
stamping exists, so its event-count assertion became a tautology and its
fence assertions a subset of the stale-seed case. The spec docblock claimed
the session invariants pin the stamping design (superseded); it now names
the three review-found timing threats the suite pins as distinct shapes.
Service overrideOf JSDoc shrinks to a pointer at the owning pure export.
kingwl 2 сар өмнө
parent
commit
b02d3e4c03

+ 6 - 20
docs/cordis-catalog/services.md

@@ -244,19 +244,12 @@ Approval service that applies session policy before answerers and logs every ask
 async request(req: ApprovalRequest): Promise<ApprovalOutcome>
 
 /**
- * A session's approval-policy OVERRIDE — the override chain alone, never
- * the configured default: the fold of the session's OWN switches (events
- * past the seed boundary — a fork seed's stale parent switch is subsumed by
- * the baseline captured after it), else the header's inherited delegation
- * baseline. The subagent driver stamps `overrideOf(parent.session)` into
- * each child's creation meta, so a `'never'` (headless/CI) parent cannot
- * mint children that fall back to a prompting default, at any depth
- * ([rationale](../../../.agents/notes/implemented/feature/2026-07-25-subagent-policy-inheritance.md)).
+ * {@link approvalOverrideOf} surfaced on the service, for consumers that
+ * reach the seam through `ctx.get('approval')` (the subagent driver's
+ * delegation capture) rather than a value import.
  * @param session - the session whose override chain to resolve.
  * @returns the effective override, or `undefined` for a session following
  *   the configured default.
- * @throws when the durable header baseline is outside the closed policy
- *   vocabulary (a corrupt or foreign log; durable-boundary validation).
  */
 overrideOf(session: Session): ApprovalPolicy | undefined
 ```
@@ -973,19 +966,12 @@ The sandbox-policy service (`ctx.sandboxPolicy`). Owns the deployment default mo
 resolve(request: SandboxPolicyRequest = {}): SandboxExecutionPolicy
 
 /**
- * A session's sandbox-mode OVERRIDE — the override chain alone, never the
- * deployment default: the fold of the session's OWN switches (events past
- * the seed boundary — a fork seed's stale parent switch is subsumed by the
- * baseline captured after it), else the header's inherited delegation
- * baseline. The subagent driver stamps `overrideOf(parent.session)` into
- * each child's creation meta, so the chain collapses one level per
- * delegation and a tightened parent binds children at any depth
- * ([rationale](../../../.agents/notes/implemented/feature/2026-07-25-subagent-policy-inheritance.md)).
+ * {@link sandboxOverrideOf} surfaced on the service, for consumers that
+ * reach policy through `ctx.get('sandboxPolicy')` (the subagent driver's
+ * delegation capture, pty-local) rather than a value import.
  * @param session - the session whose override chain to resolve.
  * @returns the effective override, or `undefined` for a session following
  *   the deployment default.
- * @throws when the durable header baseline is outside the closed mode
- *   vocabulary (a corrupt or foreign log; durable-boundary validation).
  */
 overrideOf(session: Session): SandboxMode | undefined
 ```

+ 2 - 2
packages/cordis/tool-cordis/src/api-catalog.ts

@@ -152,7 +152,7 @@ export const SERVICE_API: readonly ServiceApiEntry[] = [
       },
       {
         signature: 'overrideOf(session: Session): ApprovalPolicy | undefined',
-        jsDoc: '/**\n * A session\'s approval-policy OVERRIDE — the override chain alone, never\n * the configured default: the fold of the session\'s OWN switches (events\n * past the seed boundary — a fork seed\'s stale parent switch is subsumed by\n * the baseline captured after it), else the header\'s inherited delegation\n * baseline. The subagent driver stamps `overrideOf(parent.session)` into\n * each child\'s creation meta, so a `\'never\'` (headless/CI) parent cannot\n * mint children that fall back to a prompting default, at any depth\n * ([rationale](../../../.agents/notes/implemented/feature/2026-07-25-subagent-policy-inheritance.md)).\n * @param session - the session whose override chain to resolve.\n * @returns the effective override, or `undefined` for a session following\n *   the configured default.\n * @throws when the durable header baseline is outside the closed policy\n *   vocabulary (a corrupt or foreign log; durable-boundary validation).\n */',
+        jsDoc: '/**\n * {@link approvalOverrideOf} surfaced on the service, for consumers that\n * reach the seam through `ctx.get(\'approval\')` (the subagent driver\'s\n * delegation capture) rather than a value import.\n * @param session - the session whose override chain to resolve.\n * @returns the effective override, or `undefined` for a session following\n *   the configured default.\n */',
       },
     ],
   },
@@ -492,7 +492,7 @@ export const SERVICE_API: readonly ServiceApiEntry[] = [
       },
       {
         signature: 'overrideOf(session: Session): SandboxMode | undefined',
-        jsDoc: '/**\n * A session\'s sandbox-mode OVERRIDE — the override chain alone, never the\n * deployment default: the fold of the session\'s OWN switches (events past\n * the seed boundary — a fork seed\'s stale parent switch is subsumed by the\n * baseline captured after it), else the header\'s inherited delegation\n * baseline. The subagent driver stamps `overrideOf(parent.session)` into\n * each child\'s creation meta, so the chain collapses one level per\n * delegation and a tightened parent binds children at any depth\n * ([rationale](../../../.agents/notes/implemented/feature/2026-07-25-subagent-policy-inheritance.md)).\n * @param session - the session whose override chain to resolve.\n * @returns the effective override, or `undefined` for a session following\n *   the deployment default.\n * @throws when the durable header baseline is outside the closed mode\n *   vocabulary (a corrupt or foreign log; durable-boundary validation).\n */',
+        jsDoc: '/**\n * {@link sandboxOverrideOf} surfaced on the service, for consumers that\n * reach policy through `ctx.get(\'sandboxPolicy\')` (the subagent driver\'s\n * delegation capture, pty-local) rather than a value import.\n * @param session - the session whose override chain to resolve.\n * @returns the effective override, or `undefined` for a session following\n *   the deployment default.\n */',
       },
     ],
   },

+ 3 - 10
packages/sandbox/sandbox-policy/src/index.ts

@@ -106,19 +106,12 @@ export class SandboxPolicyService extends Service {
   }
 
   /**
-   * A session's sandbox-mode OVERRIDE — the override chain alone, never the
-   * deployment default: the fold of the session's OWN switches (events past
-   * the seed boundary — a fork seed's stale parent switch is subsumed by the
-   * baseline captured after it), else the header's inherited delegation
-   * baseline. The subagent driver stamps `overrideOf(parent.session)` into
-   * each child's creation meta, so the chain collapses one level per
-   * delegation and a tightened parent binds children at any depth
-   * ([rationale](../../../.agents/notes/implemented/feature/2026-07-25-subagent-policy-inheritance.md)).
+   * {@link sandboxOverrideOf} surfaced on the service, for consumers that
+   * reach policy through `ctx.get('sandboxPolicy')` (the subagent driver's
+   * delegation capture, pty-local) rather than a value import.
    * @param session - the session whose override chain to resolve.
    * @returns the effective override, or `undefined` for a session following
    *   the deployment default.
-   * @throws when the durable header baseline is outside the closed mode
-   *   vocabulary (a corrupt or foreign log; durable-boundary validation).
    */
   overrideOf(session: Session): SandboxMode | undefined {
     return sandboxOverrideOf(session)

+ 7 - 34
packages/subagent/subagent-inprocess/tests/inheritance.spec.ts

@@ -8,9 +8,11 @@
  *
  * Red/green anchor for the delegation-bypass gap: a parent switched to
  * `read-only` must not mint children that run under the (wider) deployment
- * default. The stamping design is itself pinned by the mounted session
- * invariants: an implementation that appends the inherited override OUTSIDE
- * the child's first turn fails these suites through the turn-enclosure check.
+ * default. The captured overrides ride the child's creation-time header, so
+ * three review-found timing threats are pinned as distinct shapes: a parent
+ * switch racing the asynchronous creation, a veto-capable prompt-submit
+ * listener closing a promptless first turn, and an injection-persisted turn
+ * before any prompt turn opens (header asserted before the child runs).
  */
 
 import { describe, expect, it, beforeEach, afterEach } from 'vitest'
@@ -276,35 +278,6 @@ describe('sandbox-mode inheritance against the real fs fence', () => {
     expect(ctx.sandboxPolicy.resolve({ session: child.session }).mode).toBe('read-only')
   })
 
-  it('a FORK child whose seed already folds to the parent mode gets NO duplicate stamp (guard)', async () => {
-    const script: Script = []
-    const captured: Agent[] = []
-    const { ctx, parent } = await setupWalled(script)
-    registerDelegate(ctx, captured)
-    const blocked = join(workspace, 'fork-dedup-blocked.txt')
-    script.push(
-      () => {
-        setSandboxMode(parent.session, 'read-only')
-        return textResponse('turn one')
-      },
-      toolCallResponse('d-fork', 'delegate', { fork: true }),
-      toolCallResponse('c-write', 'write', { file_path: blocked, content: 'escaped' }),
-      textResponse('fork child done'),
-      textResponse('turn two done'),
-    )
-    parent.followup([{ type: 'text', text: 'turn one' }])
-    await parent.whenIdle()
-    parent.followup([{ type: 'text', text: 'turn two: delegate' }])
-    await parent.whenIdle()
-
-    const child = captured[0] as Agent
-    // The seed-carried override keeps enforcing…
-    await expect(readFile(blocked, 'utf8')).rejects.toMatchObject({ code: 'ENOENT' })
-    expect(ctx.sandboxPolicy.resolve({ session: child.session }).mode).toBe('read-only')
-    // …and inheritance did not append a redundant copy on top of it.
-    expect(overrideEvents(child).sandbox).toBe(1)
-  })
-
   it('inherits the mode AT delegation, not a parent switch racing child creation', async () => {
     const script: Script = []
     const captured: Agent[] = []
@@ -371,7 +344,7 @@ describe('sandbox-mode inheritance against the real fs fence', () => {
 })
 
 describe('inheritance survives prompt vetoes', () => {
-  it('stamps the child even when an earlier-registered prompt-submit listener vetoes without next()', async () => {
+  it('keeps the baseline when an earlier-registered prompt-submit listener vetoes without next()', async () => {
     const script: Script = []
     const { ctx, parent } = await setupWalled(script)
     // A veto-capable listener registered BEFORE the child exists — the
@@ -409,7 +382,7 @@ describe('inheritance survives prompt vetoes', () => {
 })
 
 describe('inheritance guards (must hold before AND after the fix)', () => {
-  it('a child of an unswitched parent runs under the live deployment default, with ZERO stamped events', async () => {
+  it('a child of an unswitched parent runs under the live deployment default, with NO baseline or events', async () => {
     const script: Script = []
     const { parent } = await setupWalled(script)
     const allowed = join(workspace, 'default-allowed.txt')

+ 3 - 10
packages/ui/user-approval/src/index.ts

@@ -350,19 +350,12 @@ export class ApprovalService extends Service {
   }
 
   /**
-   * A session's approval-policy OVERRIDE — the override chain alone, never
-   * the configured default: the fold of the session's OWN switches (events
-   * past the seed boundary — a fork seed's stale parent switch is subsumed by
-   * the baseline captured after it), else the header's inherited delegation
-   * baseline. The subagent driver stamps `overrideOf(parent.session)` into
-   * each child's creation meta, so a `'never'` (headless/CI) parent cannot
-   * mint children that fall back to a prompting default, at any depth
-   * ([rationale](../../../.agents/notes/implemented/feature/2026-07-25-subagent-policy-inheritance.md)).
+   * {@link approvalOverrideOf} surfaced on the service, for consumers that
+   * reach the seam through `ctx.get('approval')` (the subagent driver's
+   * delegation capture) rather than a value import.
    * @param session - the session whose override chain to resolve.
    * @returns the effective override, or `undefined` for a session following
    *   the configured default.
-   * @throws when the durable header baseline is outside the closed policy
-   *   vocabulary (a corrupt or foreign log; durable-boundary validation).
    */
   overrideOf(session: Session): ApprovalPolicy | undefined {
     return approvalOverrideOf(session)