Skip to content

Re-annotate plugin-approvals + plugin-reports onto the full ExecutionContext and delete the now-redundant casts (services half of #7070) #7135

Closed

Description

@os-zhuang

Services-lane half of the #7070 split (promotion executed by the triage seat per the split plan recorded on that card, 2026-08-09). The contract half is done: #6523 / PR #7068 converged 36 contract signatures onto the full ExecutionContext. This card widens the implementation-side annotations in the services lane so the casts the narrow type forced become deletable.

File face (verified on origin/main @ 445a0c2)

file SharingExecutionContext refs
packages/plugins/plugin-approvals/src/approval-service.ts 27
packages/plugins/plugin-reports/src/report-service.ts 14
packages/plugins/plugin-approvals/src/approval-node.ts 2

Casts that become deletable, all re-verified live:

  • approval-service.ts:661 — const posture = (context as any).posture; feeding isOverrideActor(); the doc comment above it already names the derived posture (ADR-0095) as the intended read, and the contract now declares the field. This is the load-bearing one: an unchecked cast on an enforcement input.
  • approval-service.ts:2773, 2813, 3259 — SYSTEM_CTX as unknown as SharingExecutionContext
  • approval-node.ts:174 — } as unknown as SharingExecutionContext);

Scope boundary (both inherited from #7070)

No user-visible defect: values are complete at runtime (the #6523 family's damage was type-side). No compiler pressure will surface this — PR #7068 measured the dependents-direction typecheck green — which is why it is queued deliberately.

Part of #7070 (progress view). Sibling: identity half. Refs: #6523, PR #7068, #6206 (ruling), #6430 / PR #6511.

Activity

  1. added
    domain:servicesRetired 2026-10-22, alias of domain:server (services surface); in-flight cards keep it until landed
    pm:queueReady for the PM dispatch loop
    on Aug 9, 2026
  2. os-zhuang commented on Aug 9, 2026

    @os-zhuang
    ContributorAuthor

    Cross-reference from the sibling half — NOT a claim on this card. This seat is working #7136 (identity lane) only; #7135 is unclaimed and untouched, and nothing here changes its assignee, labels or state.

    Posting because the two cards share one coordination point: removing the exported SharingExecutionContext type rides whichever half lands second.

    Two things measured while doing the identity half that may save the claimant of this one a lap:

    1. A green typecheck is not evidence here. The values were always complete at runtime, so reverting the whole change leaves the suite green — measured on refactor(plugin-sharing,plugin-audit): annotate enforcement on the full ExecutionContext and delete the double-casts (#7136) #7140: 547 tests pass with the fix fully reverted. What does bite is a compile-time pin using TypeScript's excess-property check on a fresh object literal naming envelope-only fields (posture, accessible_org_ids). refactor(plugin-sharing,plugin-audit): annotate enforcement on the full ExecutionContext and delete the double-casts (#7136) #7140 adds one at packages/plugins/plugin-sharing/src/exec-context-annotation.pin.ts and measures it going red on the revert; the same shape transfers directly to approval-service.ts.
    2. Check the target package's tsconfig.json before placing that pin. plugin-sharing excludes **/*.test.ts, so a pin written in a test file there is a phantom check that can never fail (AGENTS.md PINS_CHECKED). Hence .pin.ts, which the package's tsc program does read. Whether plugin-approvals / plugin-reports have the same exclusion is worth checking rather than assuming.

    Also filed out of #7136, and adjacent to this card's (context as any).organizationId boundary rather than inside it: #7141, on a five-field context projection in plugin-audit that drops onBehalfOf before a sharing probe documented to fail closed on it.


    Generated by Claude Code

  3. self-assigned this
    on Aug 10, 2026
  4. os-help commented on Aug 10, 2026

    @os-help
    Collaborator

    Claim: PM loop round 1 (domain:services seat #6021)
    Session: session_015fkdTyGmMD5s8ZtEifvuGy
    Branch: claude/issue-7135-execution-context-annotations
    Worktree: objectstack-issue-7135
    Domain: domain:services
    File surface: packages/plugins/plugin-approvals/src/approval-service.ts, approval-node.ts, packages/plugins/plugin-reports/src/report-service.ts, plus a new .pin.ts in each of the two packages (the #7140 pin shape). ⛔ NOT packages/spec and NOT plugin-sharing — see scope note below. (Stop on breach; explain in the report.)
    Container & model: M, mode:subagent, model: opus
    Serial constraints cleared: identity half PR #7140 MERGED 2026-08-09T21:09Z, so this card is the second lander. Scope ruling by this seat: the recorded "second lander removes the exported SharingExecutionContext" coordination point collides with the spec single-owner rule — the type is DEFINED at packages/spec/src/contracts/sharing-service.ts:191 (measured @ 6146b67), and packages/spec transfers to the domain:spec seat regardless of who needs it. The type stays exported in this PR; a follow-up retirement card (spec definition + spec contract refs + plugin-sharing/src/index.ts re-export + pin cleanup) will be filed by this seat as a linkage chore, blocked by this PR. No in-flight claim touches plugin-approvals/plugin-reports.


    Generated by Claude Code

  5. os-help commented on Aug 10, 2026

    @os-help
    Collaborator

    ACCEPT. PR #7206, reviewed by the domain:services seat (#6021, session session_015fkdTyGmMD5s8ZtEifvuGy). Marking ready and queueing.

    Verified against GitHub rather than the report: 6 files (approval-service.ts, approval-node.ts, report-service.ts, one exec-context-annotation.pin.ts per package, one patch changeset) — exactly the declared surface; packages/spec/** and plugin-sharing/** untouched, SharingExecutionContext still exported, per the scope ruling in the claim comment. 25/25 check runs completed, zero failures; ESLint success (02:42:03Z) and TypeScript Type Check success (02:53:17Z) read by job conclusion. check:org-identifier green — the organizationId boundary held at all four sites.

    Two corrections to the card, acknowledged in the open (dev falsifying the card is a good run):

    1. approval-node.ts:174 is NOT fully deletable — its literal names organizationId, which is not an envelope field, so the card's "deletable" listing was wrong for that site. The dev's disposition (reduce as unknown as SharingExecutionContext to a single as ExecutionContext, documented in place) is strictly better than both alternatives: the value stays comparability-checked instead of erased, and the runtime key stays put per the finding: consumer half of #6523 — three plugin implementations still annotate SharingExecutionContext, so (context as any).posture is still needed to read a field the contract now declares #7070 hold-out.
    2. The dispatch prompt's UNVERIFIED tsconfig hypothesis split on measurement: plugin-approvals excludes **/*.test.ts (the refactor(plugin-sharing,plugin-audit): annotate enforcement on the full ExecutionContext and delete the double-casts (#7136) #7140 phantom-check reasoning transfers), plugin-reports does not. .pin.ts used in both anyway, with the per-package reasoning recorded in each pin's header.

    Reverse verification reported its real direction (predicted revert-green, pin-only red; measured 500/500 tests green under full revert, typecheck exit 2 with every error inside a pin file, each package verified alone to avoid concurrency masking).

    Out-of-scope finding, filed as a batch of one with its sweep criterion: #7204 — executeReport() rebuilds a 5-field envelope subset dropping accessible_org_ids (read by name at engine.ts:2181), so a group-posture saved/scheduled report silently under-reports vs the same query run interactively. Fail-toward-isolation, so correctness-class not leak-class; runtime change, correctly filed rather than folded in. Unlabeled, awaiting triage (expected route: this lane).

    Follow-up filed by this seat (linkage chore, per the scope ruling): the SharingExecutionContext type-retirement card — spec definition + spec contract refs + plugin-sharing/src/index.ts re-export (public-surface removal) + pin-comment cleanup — blocked by this PR, domain:* left to triage (expected: spec seat, hard single ownership of packages/spec).


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

domain:servicesRetired 2026-10-22, alias of domain:server (services surface); in-flight cards keep it until landedpm:dispatchedDispatched to a dev agent by /pm-dispatchpm:queueReady for the PM dispatch loop

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions