Skip to content

service-automation: flow index and activation consult on (package, name) (ADR-0150 child E1) #31672

Closed

Description

@objectstack-fleet

epic:#31527#1 · os-project-manager · session_01FEkQ5mLd7pR2PHjsPwiGkz

Filing gate: ④ coordination node: child E1 of the epic #31527 (parent and per-layer children), as ADR-0150 (docs/adr/0150-behavioural-metadata-addressed-by-package-objects-keep-the-literal-prefix.md, merged in #31586 at 5d1382a)'s execution plan lists it. Hand-over card: filed undispatched as the epic seat signs off (maintainer 2026-11-08T16:34Z 「专题卡当前任务处理完,合并后就下班」). ⛔ Not a claim.
Ruling-ref: per-type table A (6723462584); epic A 「立专题」 (6723499113); division of labour A 「留核心,其余交车道」 (6723571682); ADR-0150 accepted by merge (#31586, 2026-11-08T21:16Z).
Business reason: inherited from the parent #31527. Behavioural metadata is addressed by (package, name), so two installed packages can each ship an item of the same name and every reader answers the right one, or refuses with the candidates, instead of silently taking the first match.
Reader: the next domain:server seat picks it from the queue (pm-dispatch selection) and accepts its PR against the red lines below.
Dedupe (open AND closed): flow index package name (1202; top hits #31527(open) #30806(open) #31155(open), none on point: they are this epic, its parent #30806, or unrelated cards).
class: d · type: Feature
Grade: p1, inherited from the parent (self-graded under 「定级你可以自己决定」).
Blocked-by: #31575

维护者速读

流程的索引和激活按(软件包, 名称)查找,不再只看名字。

What to build

The flow index and activation consult on (package, name), through R's resolver (D3, D4). A bare name with one holder still resolves.

Surface

  • Expected file surface: service-automation (engine.ts, flow-definitions.ts).
  • Clause-②: no.
  • Narrowing: yes, for a package item's bare reference that only an environment-authored item holds (D3 (a); not measurable first-party; the D10 upgrade report lists each case).

Acceptance — the epic's three red lines (every child shares them)

  • Resolution never loosens. No first-registered fallback, no environment-wide guess for a caller with a package, no silent pick.
  • Ambiguity is reported, never guessed. Every refusal and every migration report names every candidate.
  • Independently releasable (red line 3). The PR proves it with ADR-0150's four readings: (a) the phase-1 one-holder tests stay green; (b) bare-name behaviour (URLs, MCP, SDK) is unchanged for every name with one holder, except this card's declared narrowing; (c) any migration is re-runnable and never guesses; (d) its Clause-②: declaration and, where it changes the protocol, its ADR-0087 migration entry.
  • The epic seat is off duty after hand-over: the accepting lane seat checks these lines itself, and a narrowing beyond the declared one goes to the maintainer before landing.

Parent: #31527.

Activity

  1. added
    enhancementNew feature or request
    priority:p1High: required for production / M2
    pm:blockedBlocked by another issue/PR — body carries Blocked-by: #N
    area:devpathThe road — create, dev, verify, publish/install, connect an agent, iterate
    domain:serverDomain lane — seat card indexed by label:pm:seat
    on Nov 8, 2026
  2. objectstack-fleet commented on Nov 8, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: confirmed · domain:server · p1 · pm:blocked · 2026-11-08T21:55Z

    ⛔ Not a claim.


    Generated by Claude Code

  3. added
    pm:blockingDerived cache from the Blocked-by reverse index: open card with open dependents — never hand-set
    on Nov 8, 2026
  4. objectstack-fleet commented on Nov 8, 2026

    @objectstack-fleet
    ContributorAuthor

    epic:#31527#1 · os-steve · session_01ADHkmP7o3uDTti21wLTfPf

    Unblocked 2026-11-08T22:58Z: Blocked-by: #31575 is closed. R merged in #31637 as 0ebb080 (resolvePackageScopedName, packageResolutionClosure and the three read-only SchemaRegistry package-scoped methods in objectql; packageDependencyClosure in metadata-protocol). pm:blocked → pm:queue in this stroke. Read the resolver through those exports only, and never re-implement the rule. The epic seat reviews this card's PR against the three red lines before it lands.

  5. added
    pm:queueReady for the PM dispatch loop
    and removed
    pm:blockedBlocked by another issue/PR — body carries Blocked-by: #N
    on Nov 8, 2026
  6. objectstack-fleet commented on Nov 8, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#3 · os-steve · session_01ADHkmQXLfvyB5R53VDm3Ka

    Claim: PM loop round 1 · #31672 (E1, epic #31527) · 2026-11-08T23:05Z
    Session: session_01ADHkmQXLfvyB5R53VDm3Ka (seat); dev = card thread session_01ADHkmQjmHnuYAuaRd9k252
    Account: os-steve
    Branch: claude/project-thread-ack2ot
    Worktree: the card thread's checkout of objectstack-ai/objectstack
    Domain: domain:server
    Seat: domain:server#3
    File surface: packages/services/service-automation/src/** (engine.ts, flow-definitions.ts: the flow index and activation), their tests, .changeset/31672-*.md (stop on breach; ⛔ no packages/spec edit, no second resolver: R's exports only)
    Container & model: L, mode:thread, model: default tier; CONTRACT_REVIEW_TIER for the review owed before the queue (dispatch-gates --tier: a card that only NARROWS owes one contract-review-tier review, judged from the card content), effort: high
    Clause-②: no
    Metadata-protocol: none
    Responsibility: n/a — not a defect card
    Thread-read: 6728342084
    Premise: holds (R #31637 merged as 0ebb080; the card's Blocked-by: #31575 closed, moved to pm:queue by the epic seat in 6728342084; the dev confirms the resolver exports on main in step 0)
    Narrowing: as the card declares (D3 (a)), a package item's bare reference that only an environment-authored item holds; the dev measures it on base and head
    Serial constraints cleared: E5 #31677 (this seat, branch claude/project-thread-bwr6nn) also touches service-automation (connectors): the two threads read each other's branch, run in parallel while the files are disjoint, and E1 lands first if they meet. S3 #31684 follows E1, E5 and E7 on this seat. Seat 1 holds N/K/G1 (registry.ts, objectql), outside this surface.

  7. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Nov 8, 2026
  8. objectstack-fleet commented on Nov 8, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#3 · os-steve · session_01ADHkmQXLfvyB5R53VDm3Ka

    Claim amendment · #31672 · 2026-11-08T23:10Z · amends Claim 6728428231
    File surface: adds packages/services/service-automation/package.json (@objectstack/objectql moves from devDependencies to dependencies) and the matching pnpm-lock.yaml importer line. Reason: R's resolver is exported from objectql, and a copy of the rule inside the engine would be the second resolver the epic forbids. No cycle: nothing in objectql's dependency closure depends on service-automation (the dev's reading; the seat re-reads it at review).
    Narrowing: unchanged in this claim. The dev reports one more case the resolver's step 3 refuses for a package caller (a bare name held only by a package outside the caller's declared dependency closure; first-party count 0 on main, measured by the dev). It is declared in the PR body with that count; whether it is inside ADR-0150's declared narrowings is settled before landing, not by this amendment.

  9. objectstack-fleet commented on Nov 9, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#3 · os-steve · session_01ADHkmQjmHnuYAuaRd9k252
    os-dev-report

    {
     "issue": 31672,
     "status": "done",
     "branch": "claude/project-thread-ack2ot",
     "pr": "https://github.com/objectstack-ai/objectstack/pull/31738",
     "session": "session_01ADHkmQjmHnuYAuaRd9k252",
     "premise_still_valid": true,
     "summary": "The flow engine now asks R's one resolver (resolvePackageScopedName, objectql) whether a bare flow name is refused for the caller's package: execute() reads the caller package from context.flowName (the calling flow's packagedFlowOwner), so a subflow/map child of a package flow resolves own -> unique holder in declared closure (+sys), and an environment-only holder (D3 (a)) or an outside-closure package holder (D3 step 3) is refused with every candidate named. The activation projection is keyed by (package, name) (FlowActivationProjection). The sealed two-holder clash arm (ambiguous-* refusals + registerFlow gate) is held back per seat 3: it reddened exactly 2 phase-1 dogfood pins on bcc5ba62; it is a ready patch inline in the PR body pending #31677.",
     "tests": "New src/flow-package-scoped-resolution.test.ts, 14 cases (real SchemaRegistry + plugin flowNameResolver): 14/14. Package: vitest run 267 files / 3470 tests passed; tsc --noEmit 0; eslint package 0. Ablations via scripts/ablation-replace.mjs: FLOW_NAME_REFUSALS_ACTED_ON emptied (e94f303d) -> 2 failed | 12 passed (14), D3 (a) + D3 step 3 red (= base reading); projection has() -> true (bcc5ba62) -> 2 failed | 14 passed (16); held-back registerFlow gate off (bcc5ba62) -> 1 failed | 15 passed (16). Each restored, blob == HEAD. Arm patch: git apply --check on e94f303d ok, 16/16 green, reverted.",
     "gates": "87 derived gates run on e94f303d, every exit 0; dispatch-gates.mjs --ran: 87 derived, 87 run, 0 NOT-MEASURED, 0 UNRUN. First pass on bcc5ba62 found check-tenant-audit-census exit 1 (untyped receiver packages.delete() in flow-activation-projection.ts) -> fixed by annotating Set<string> | undefined, no UNTYPED_RECEIVERS row. Prerequisite exits 3 on the first pass (teardown self-test needed fixture commit fetch; dual-build-cjs-loads needed dist; type-check-debt lost the lock queue) all re-run green. CI check-runs: not awaited per order.",
     "dogfood_battery": "e94f303d · os-verify-lock: VERDICT command-exit 0 · held the lock 1812s · Test Files 440 passed | 3 skipped (443) · Tests 3652 passed | 41 skipped (3693) · no failures. (bcc5ba62 with the arm: VERDICT command-exit 1, 2 failed | 3650 passed, both bare-name-one-holder-flow-family.dogfood.test.ts armedFlowLabel('qa_shared_flow') pins -> arm held back.)",
     "mcp_calls": "5 — mcp__github__issue_read x4 (reads), mcp__claude-code-remote__subscribe_pr_activity x1 (not a GitHub write); no GitHub write tool",
     "api_writes": "0 REST proxy writes by this session; GitHub writes went through the fleet relay: pr_create #31738 (with-fleet dispatch run 42543481191) and this comment via post-stamped.mjs",
     "files_changed": [
      ".changeset/31672-flow-package-scoped-resolution.md",
      "packages/services/service-automation/package.json",
      "packages/services/service-automation/src/engine.ts",
      "packages/services/service-automation/src/flow-activation-projection.ts",
      "packages/services/service-automation/src/flow-definitions.ts",
      "packages/services/service-automation/src/flow-package-scoped-resolution.test.ts",
      "packages/services/service-automation/src/index.ts",
      "packages/services/service-automation/src/plugin.ts",
      "pnpm-lock.yaml"
     ],
     "line_budget": "+531 / -12 across 9 files (merge-base..e94f303d)",
     "deviations": [
      "File surface amended by seat 3: service-automation package.json (objectql devDependencies -> dependencies) and its pnpm-lock importer line; no-cycle reading: objectql runtime closure (11 packages) excludes service-automation, check:workspace-manifest-cycles green.",
      "Sealed-clash arm held back from E1 on seat 3's instruction (2 phase-1 dogfood pins red only on it); ready as a patch in the PR body.",
      "First closure build ran with OS_SKIP_DTS=0, which still skips declarations (any set value does); rebuilt without the variable."
     ],
     "open_questions": [
      {
       "question": "Sealed two-package flow clash: refuse at arming and in execute (the held-back arm), or keep today's precedence pick?",
       "options": [
        "A refuse: apply the inline patch + update the 2 phase-1 dogfood pins",
        "B keep the pick until S3 arms both"
       ],
       "recommendation": "Per #31677's ruling; the patch is ready either way and adds no first-pick of its own."
      },
      {
       "question": "D4 'all same-named flows arm' needs package on run/credential/dispatch rows; E1 keeps one armed slot. Leave to S3 #31684?",
       "options": [
        "A leave to S3",
        "B add a per-package slot now"
       ],
       "recommendation": "A, because without S3's columns two same-named flows' runs would cross."
      },
      {
       "question": "A stale ledger row of package Q no longer disables package P's same-named flow (declared in changeset). Keep, or keep any foreign row disabling until S1?",
       "options": [
        "A keep (D4 reading)",
        "B one-line change: foreign rows disable until S1"
       ],
       "recommendation": "A, because the row names a flow this deployment no longer ships under Q; reachable only when a name moves packages."
      },
      {
       "question": "E2 (actions) and E6 (api endpoints) callers still execute with no caller package until their cards land; refused child results carry no new code (G1 maps 409).",
       "options": [
        "A as is"
       ],
       "recommendation": "A."
      }
     ],
     "security_findings": "withheld",
     "out_of_scope_findings": []
    }

    Stamped 2026-11-09T01:04Z.


    Generated by Claude Code

  10. objectstack-fleet commented on Nov 9, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#3 · os-steve · session_01ADHkmQjmHnuYAuaRd9k252
    os-dev-report

    {
     "issue": 31672,
     "status": "done",
     "branch": "claude/project-thread-ack2ot",
     "pr": "https://github.com/objectstack-ai/objectstack/pull/31738",
     "session": "session_01ADHkmQjmHnuYAuaRd9k252",
     "premise_still_valid": true,
     "summary": "Round 2 on #31738 (head d7a38bb7). (1) #31677 Q1 ruled A: registerFlow refuses a flow name two packages hold (no-package resolver ask) and execute refuses every resolver refusal, sealed clash included; the interim held-back warning is gone. The 2 phase-1 dogfood pins (qa_shared_flow) now read neither flow armed plus the refusal in the boot log. (2) Q3 ruled B: the projection keeps each package row's state; the holder's own row decides; a row of a package that still holds the name keys only itself; a stale row keeps the holder off and is warned once naming both packages and the remedy (toggle again). (3) Merged main (E5): objectql dependency move now on main; the flow reader reuses E5's packageScopedRegistryOf (the merge had produced a duplicate import, caught by the closure build and fixed).",
     "tests": "flow-package-scoped-resolution.test.ts 20/20. Package vitest 267 files / 3478 tests; tsc 0; eslint 0. Ablations (committed heads, restored blob == HEAD): registerFlow gate deleted -> 1 failed | 19 passed (20); execute gate deleted -> 4 failed (D3 (a), step 3, sealed-clash door run, ambiguous-in-closure caller); stillHolds -> continue -> 2 failed | 15 passed (17); reportStale deleted -> 2 failed | 15 passed (17); holder-row-decides deleted -> 3 failed | 14 passed (17).",
     "gates": "76 derived gates on d7a38bb7, every exit 0; dispatch-gates.mjs --ran: 76 derived, 76 run, 0 NOT-MEASURED, 0 UNRUN. CI check-runs: not awaited per order.",
     "dogfood_battery": "d7a38bb7 · os-verify-lock: VERDICT command-exit 0 · held the lock 2037s · Test Files 440 passed | 3 skipped (443) · Tests 3652 passed | 41 skipped (3693) · no failures (includes the 2 moved phase-1 pins)",
     "mcp_calls": "5 — mcp__github__issue_read x4 (reads), mcp__claude-code-remote__subscribe_pr_activity x1; no GitHub write tool",
     "api_writes": "0 REST proxy writes by this session; relay writes: pr_create #31738, issue_patch #31738 body (r2, run 42551442687), 2 card comments via post-stamped.mjs",
     "files_changed": [
      ".changeset/31672-flow-package-scoped-resolution.md",
      "packages/qa/dogfood/test/bare-name-one-holder-flow-family.dogfood.test.ts",
      "packages/services/service-automation/src/engine.ts",
      "packages/services/service-automation/src/flow-activation-projection.ts",
      "packages/services/service-automation/src/flow-definitions.ts",
      "packages/services/service-automation/src/flow-package-scoped-resolution.test.ts",
      "packages/services/service-automation/src/index.ts",
      "packages/services/service-automation/src/plugin.ts"
     ],
     "line_budget": "+676 / -16 across 8 files (merge-base with main..d7a38bb7)",
     "deviations": [
      "Dogfood test file bare-name-one-holder-flow-family.dogfood.test.ts edited outside the claimed surface, on seat 3's direction after #31677 Q1 ruled A (forced test change, declared in the PR body).",
      "PR body edit carries the relay's required trailer <!-- signed: ... --> as its last line (issue_patch signature), besides the attribution comment.",
      "First closure build ran with OS_SKIP_DTS=0, which still skips declarations; rebuilt without the variable."
     ],
     "open_questions": [
      {
       "question": "resolveFlowPrecedence still logs 'Flow name collision ... arming <first> by package id' for two package holders, followed by the refusal line; its wording is pinned in packages/cli/src/utils/format.boot-warning-classes.test.ts (outside this surface).",
       "options": [
        "A small follow-up card rewording the two-package case to say neither is armed",
        "B leave it"
       ],
       "recommendation": "A, because the log now contradicts the engine for that case."
      }
     ],
     "answered_questions": "Q1 (sealed clash): ruled A on #31677, applied. Q2 (D4 arm-both): prerequisite of B #31696, not S3 (epic seat). Q3 (stale row): ruled B, applied. Q4 (E2/E6 callers without package): A, as is.",
     "security_findings": "withheld",
     "out_of_scope_findings": []
    }

    Stamped 2026-11-09T02:32Z.


    Generated by Claude Code

  11. objectstack-fleet commented on Nov 9, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#3 · os-steve · session_01ADHkmQXLfvyB5R53VDm3Ka

    Landed · #31672 (ADR-0150 E1) · 2026-11-09T03:42Z

    Reading Value
    PR #31738, merged 2026-11-09T03:42:26Z, merge commit 55c4e95b, from head 1081c777 (seat ACCEPT 6731228679, epic final PASS 6730866938). It went through the queue once, with no ejection.
    Card closed completed by Fixes #31672

    pm:dispatched is removed in this stroke. Follow-ups: #31741 (skills automation SKILL.md) and #31754 (collision log wording, claimed by seat 3, starts now). S3 #31684 now waits only on the email half of E5 #31677, which waits on R2 #31716.

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

Metadata

Metadata

Assignees

Labels

area:devpathThe road — create, dev, verify, publish/install, connect an agent, iteratedomain:serverDomain lane — seat card indexed by label:pm:seatenhancementNew feature or requestpm:blockingDerived cache from the Blocked-by reverse index: open card with open dependents — never hand-setpriority:p1High: required for production / M2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions