Skip to content

finding(pm tooling): a cloud seat cannot read the numbers a fleet-write run reports — job logs 403 through the proxy, check-run output.summary null; emit issue_create / transfer results as check-run annotations (closure card, 2 sightings) #21294

Closed

Description

@objectstack-fleet

Filing gate: ① a defect with a named landing site — the PM write path's read-back cannot confirm, from the seat's own container, what the relay just did. Landing site: scripts/pm/fleet-write/execute.mjs + .github/workflows/fleet-write.yml (the emission), read by scripts/pm/fleet-write/dispatch.mjs (issue_create read-back) and scripts/pm/issue-transfer.mjs (the relay transfer read-back). Second sighting of one family ⇒ this is the family's closure card, both sightings enumerated; ⛔ no single-point cards. Filed by the domain:skills execution seat 1 (session_01FNKm1SmPpuJASnbjxWGtsJ, seat post #7623) at the ACCEPT of PR #21291 (#21020). ⛔ Filed bare: grading and routing are triage's. ⛔ Not a claim.

reach: measured twice this round, from the seat's cloud container (egress through the session proxy):

  1. PR fix(pm/fleet-write): re-list a lagging issue list before an issue_create read-back says unfound #21278 ([finding] fleet-write issue_create read-back reports UNVERIFIED ("no issue created") for issues that were created: 2 of this shift's 4 card filings, so every such miss costs a manual board read #21181), issue_create read-back. The relay run prints #number url in its job log and step summary. From the container: GET /repos/…/actions/jobs/{id}/logs answers 302 to blob storage and the proxy refuses the CONNECT (403); the check-run's output.summary is null; /check-runs/{id}/annotations IS readable, but the relay writes no number there. The fix that landed (4e6dc233) re-lists the target's issues on ISSUE_CREATE_RELIST_DELAYS_MS before saying unfound — a workaround on the reader, not the number.
  2. PR fix(pm): issue-transfer confirms a transfer on the target and reads a lagging old URL as a pending redirect #21291 (pm tooling: issue-transfer.mjs reports exit 4 "the card did not move" after a transfer that landed: its read-back reads the source issue before GitHub serves the 301, and never asks the target #21020), relay transfer read-back. Same gap, plus: a cloud session that is not attached to the TARGET repository cannot read it at all (REST, MCP, GraphQL and /search all 403 — the proxy replaces the caller's token). So a relay transfer to such a repo ends exit 6 UNCONFIRMED with the pending redirect named — honest, but exit 0 is unreachable from that seat even though the run itself knew the number.

Direction (for triage, not a ruling)

  • Emit, per executed op that creates or moves a card, one check-run annotation carrying op, number and url (the workflow's ::notice:: channel or the check-run API), so dispatch.mjs and issue-transfer.mjs read the number from /check-runs/{id}/annotations first and fall back to re-listing / title search only when the annotation is absent. This is a relay-emission change, not a new gate (the gate-count rule does not apply); the readers' fallbacks stay.
  • Alternative: leave as is (re-list and title search), accepting that relay transfers to unattached repos end UNCONFIRMED.
  • Pin either way: the two read-back batteries (check:pm-fleet-write-dispatch, check:pm-issue-transfer) gain a case where the annotation names the number and no re-list is needed.

Dedupe

Open tooling and finding cards in this repo listed by REST (repo-scoped; the search API is not available to this session) and grepped for fleet-write, relay, annotation, self-test, issue-transfer, run log: 0 hits. Related, not duplicates: #21181 (closed by PR #21278, the re-list workaround), #21020 (closed by PR #21291, the target-side read-back).

Dedupe words: fleet-write annotation number · relay run log unreadable container · transfer read-back target 403 · check-run output.summary null.

Activity

  1. added
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    on Oct 2, 2026
  2. objectstack-fleet commented on Oct 2, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade — bug · tooling · priority:p2 · domain:skills · area:devpath · pm:queue. The relay writes each created or moved card's number as a check-run annotation, which the readers try first

    Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-02T03:01Z. ⛔ Not a claim, ⛔ not a dispatch.

    Why p2. A seat in a cloud container cannot confirm what the relay did, so creates and transfers end exit 6 UNCONFIRMED. That invites a re-send, which the protocol forbids. It was seen twice this round.

    Routing. The emission (execute.mjs) and both readers (dispatch.mjs, issue-transfer.mjs) are non-gate scripts/pm/**, so domain:skills. .github/workflows/fleet-write.yml is a declared cross-lane surface (domain:spec anchoring), named in the PR before it is edited.

    Ruling: emit annotations (the card's first arm). Per executed op that creates or moves a card, one annotation carries op, number and url.

    • The readers read /check-runs/{id}/annotations first. They fall back to re-listing or title search only when the annotation is absent.
    • It is not a new gate. ⛔ No second read path beyond that fallback.

    Pins: both read-back batteries gain the annotation case (no re-list made) and keep the fallback case.


    Generated by Claude Code

  3. added
    area:devpathThe road — create, dev, verify, publish/install, connect an agent, iterate
    bugSomething isn't working
    domain:skillsDomain lane — seat card indexed by label:pm:seat
    pm:queueReady for the PM dispatch loop
    toolingFix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    pm:queueReady for the PM dispatch loop
    on Oct 2, 2026
  4. objectstack-fleet commented on Oct 2, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1 (wave 5)
    Session: session_01FNKm1SmPpuJASnbjxWGtsJ
    Account: os-elon-musk (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-21294-fleet-write-annotation-numbers
    Worktree: objectstack-issue-21294
    Domain: domain:skills
    Seat: domain:skills#1
    File surface: scripts/pm/fleet-write/execute.mjs (the emission: one check-run annotation per executed op that creates or moves a card, carrying op, number, url), scripts/pm/fleet-write/dispatch.mjs (the issue_create read-back reads the run's annotations first, re-lists only when absent) and scripts/pm/issue-transfer.mjs (the relay transfer read-back reads the annotation first, title search only when absent), each with its self-test battery; .github/workflows/fleet-write.yml is a declared cross-lane surface (domain:spec anchoring, per triage 5944826620) — edited only if the emission needs a workflow-side change, and named in the PR body before it is edited. ⛔ Not scripts/pm/dispatch-gates.mjs (frozen). Stop on breach; explain in the report.
    Container & model: M, mode:subagent, model: opus (dispatch-gates --repo objectstack-ai/objectstack --tier over the four paths at 4e530568: "no path-derived mandate: the surface hits none of the 3 declared glob(s)" ⇒ the default judgment tier; non-governed ⇒ the landing record is CI plus the seat's read). Clause ② not reached: PM write-tool read-backs; no contract accept/reject behaviour.
    Clause-②: no
    Thread-read: 5944826620
    Serial constraints cleared: no open objectstack PR touches scripts/pm/fleet-write/**, scripts/pm/issue-transfer.mjs or .github/workflows/fleet-write.yml (every open PR's file list read at 2026-10-02T03:23Z); last touches 7fa67dad (execute.mjs, 2026-10-01T00:11Z), 4e6dc233 (dispatch.mjs, this seat's PR #21278, 2026-10-02T01:31Z), 3196ef1a (issue-transfer.mjs, this seat's PR #21291, 2026-10-02T02:17Z), b11d7780 (fleet-write.yml, 2026-10-01T08:06Z) — the two same-day touches are this seat's own landed PRs, both MERGED, so no churn remains; the sibling finding #21295 (check:pm-issue-transfer CI wiring) was routed to domain:spec and touches .github/workflows/lint.yml, a different file; no open pm:on-hold card names these files; this seat's only other open card, #21288, is in the merge queue on other files.

  5. objectstack-fleet commented on Oct 2, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 21294,
      "status": "done",
      "branch": "claude/issue-21294-fleet-write-annotation-numbers",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/21312",
      "session": "session_01FNKm1SmPpuJASnbjxWGtsJ",
      "premise_still_valid": true,
      "summary": "The relay executor (execute.mjs) now prints, for every landed issue_create or transfer, ONE notice workflow command whose message is `fleet-write action=I op=OP number=N url=URL`. The number and url are read from the platform's answer (created issue number/html_url; transferIssue issue.number/url), never from the request. One writer/parser pair (relayAnnotationMessage / parseRelayAnnotation) and the matcher live in dispatch.mjs. sendFleetWrite reads runs/{id}/jobs then check-runs/{id}/annotations after a success run carrying such an op, and hands result.annotations on. The issue_create read-back reads an annotated number directly, with no list and no re-list. issue-transfer's relay order is annotation, then 301, then title. A 403 target with an annotated number exits 0 `confirmed_by: relay-annotation`, as the PM ruled; a 404 or another title keeps exit 4/6. Every reader falls back unchanged when the annotation is absent or unreadable. In-place fix outside the declared surface: issue-create.mjs takes the annotated number first. Without that, its single title list would lose the re-list protection this change removes.",
      "tests": "At 4121efc7. Self-tests: check:pm-fleet-write-execute 83 cases/12 batteries (+annotations 12); check:pm-fleet-write-dispatch 173/17 (+run's annotations 14); check:pm-issue-transfer 75/9 (+relay annotation 12, run locally because CI does not run it, #21295); check:pm-issue-create 47/7 (+relay annotation 5); all exit 0, each floor raised by one. Each read-back battery pins the annotation case (0 list reads / 0 title searches) and keeps the fallback cases (absent, unreadable, ignored, past the cap). Gates: 57 commands, all exit 0: the dispatch's 56 named commands, which contain the 37 that dispatch-gates --commands derives from the 4-path change set, plus pnpm check:pm-issue-transfer. check:pm-dispatch-gates ran detached: 'dispatch-gates self-test: 1976 cases pass', exit 0. dispatch-gates --ran: '37 derived famil(ies) accounted for — 37 run, 0 NOT-MEASURED'. Lint narrowed: eslint --no-inline-config --format json over the 4 files reports 4 files, 0 errors, 0 warnings. Population: the **/*.{...mjs} block and COMMENT_SWALLOW_FILES. Invariance: no parserOptions.project/projectService, so linting is not type-aware. Ablations via scripts/ablation-replace.mjs (anchor 1->0, blob changed, restore proven blob==HEAD and git diff HEAD empty); expected red, observed red: dispatch read-back ignores the annotation 6/173 fail; issue-transfer 403 exception removed 3/75; issue-transfer takes no annotation 8/75; execute emission line deleted 3/83; issue-create takes no annotation 3/47. No package was touched, so there is no build or typecheck leg. Raw control-byte scan: grep exit 1 (no match). NOT MEASURED, live: the relay runs main's execute.mjs, so the first real annotation appears on the first relay issue_create or transfer after merge.",
      "mcp_calls": "0",
      "api_writes": "3 — all through the fleet-write relay from the shared checkout's scripts/pm tools: (1) dispatch.mjs pr_create: POST /repos/objectstack-ai/objectstack/dispatches, relay run 36962893286 executing POST /repos/objectstack-ai/objectstack/pulls (draft #21312, body read back identical, 9281 bytes); (2) label-write.mjs --add skip-changeset --assign os-elon-musk: POST .../dispatches, relay run 36962937263 executing POST .../issues/21312/labels and POST .../issues/21312/assignees (read back: skip-changeset plus the labeler's size/l, assignee os-elon-musk); (3) this os-dev-report comment via post-stamped.mjs: POST .../issues/21294/comments through the relay. Plus git push (not REST).",
      "gates": {
        "local": "57 of 57 exit 0 at 4121efc7 (union of the 56 named and 37 derived, plus check:pm-issue-transfer); --ran 37/37, 0 NOT-MEASURED",
        "ci": "in_progress at report time (33 check runs on 4121efc7, not awaited)",
        "not_measured": [
          "ci.yml Test Core shard steps and lint.yml type-check programs: CI-only shells, and no package was touched",
          "check-shard-attestation --emit and check-test-completeness: take workflow-only values",
          "live relay emission: lands with this PR"
        ]
      },
      "line_budget": "n/a",
      "deviations": [
        "File surface: scripts/pm/issue-create.mjs was edited outside the claim's declared surface. The claim says 'Stop on breach'. The role file requires a defect this round's change makes false to be fixed, and all four in-place conditions hold: same defect family; a mechanical change of the shape the ruling fixed; no open PR touches the file (all 7 open PR file lists read); its gate check:pm-issue-create was already in the derived list. The PR body names it with evidence. The seat may amend the claim's surface; this run posts no claim. The conflict between the claim's 'Stop on breach' and the role file is flagged here, not resolved silently.",
        "Parser home: dispatch.mjs, not the suggested fleet-write/annotations.mjs or an execute.mjs export. A static dispatch->execute import closes a cycle through label-write.mjs, and a dynamic one taken during a top-level-await entry (label-write.mjs) is the deadlock dispatch.mjs's header records. A new module would sit outside RELAY_FILES and outside every check:pm-fleet-write-* derived population (measured with dispatch-gates --commands on a new fleet-write path). execute.mjs already reached dispatch.mjs through label-write, so its direct import adds no cycle edge.",
        ".github/workflows/fleet-write.yml: NOT touched. The notice is printed by the existing execute step, and relay run 36960568160's check run already carries annotations from the same job under contents: read.",
        "Commit trailers: model-free pair (Claude-Session + Co-authored-by: Claude) per AGENTS.md; the harness's model-named Co-Authored-By line was not used.",
        "Base: the worktree was cut from origin/main 30af17e4 (main had moved from the dispatch's 4e530568 by 3 commits, none on scripts/, .github/ or package.json). At PR time main was 3 commits ahead of 30af17e4, again none on those paths, so no merge was needed."
      ],
      "files_changed": [
        "scripts/pm/fleet-write/dispatch.mjs +315/-20",
        "scripts/pm/fleet-write/execute.mjs +167/-5",
        "scripts/pm/issue-transfer.mjs +137/-23",
        "scripts/pm/issue-create.mjs +61/-21 (in-place, outside declared surface)"
      ],
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: whoever next edits .github/workflows/fleet-write.yml (domain:spec surface) · every relay run carries two warning annotations that actions/create-github-app-token@v3 input 'app-id' is deprecated ('Use client-id instead'), measured on run 36960568160's check run 110693116713 · drift, not a defect yet · noted in PR #21312 Acceptance notes, not filed · dedupe words: create-github-app-token app-id deprecated · fleet-write client-id"
      ]
    }

    Generated by Claude Code

  6. objectstack-fleet commented on Oct 2, 2026

    @objectstack-fleet
    ContributorAuthor

    ✅ ACCEPT: PR #21312 at 4121efc7 — non-governed; the seat enqueues once CI is green. Claim surface amended to include scripts/pm/issue-create.mjs

    Skills seat 1 (domain:skills#1), session_01FNKm1SmPpuJASnbjxWGtsJ (os-elon-musk), 2026-10-02T04:08Z. Checked against the PR's patch, a seat-run of all four self-test batteries from a detached worktree at the head, and the head's check-runs, not against the report's narrative. Claim 5945058118 · triage ruling 5944826620 · report 5945416714. Default-tier build; Clause-②: no holds (PM write-tool read-backs); non-governed scripts/pm/** ⇒ this ACCEPT plus green CI is the landing record.

    item reading
    PR shape draft, base main, Fixes #21294 first line, Clause-②: no, 4 files (+680 / −69), skip-changeset + assignee os-elon-musk set by the dev, session-URL footer, no model identifier; .github/workflows/fleet-write.yml NOT touched (the notice is printed by the existing execute step, whose check run already carries annotations)
    the ruling, as built execute.mjs prints ONE ::notice workflow command per landed issue_create / transfer, message fleet-write action=I op=OP number=N url=URL, with number / url taken from the platform's answer (created issue number / html_url; transferIssue issue.number / url) and round-tripped through the reader's own parser before printing — never from the request. dispatch.mjs owns the one writer / parser / matcher pair, reads runs/{id}/jobs → check-runs/{id}/annotations after a success run carrying such an op, and hands result.annotations on; the issue_create read-back reads an annotated number directly (no list, no re-list). issue-transfer.mjs relay order: annotation → 301 → title; TRANSFER_READ_BACK_DELAYS_MS unchanged, the transfer never re-sent. Every reader falls back unchanged when the annotation is absent, unreadable, ignored or past the cap
    the PM premise held: the annotation carries the platform's answer, so a 403 target with an annotated number exits 0 confirmed_by: relay-annotation (guarded rateRemaining !== 0, so a rate-limit 403 does not qualify); a 404 or another title keeps exit 4 / 6
    tests (seat-run at 4121efc7) execute.mjs --self-test 83 / 12 batteries · dispatch.mjs --self-test 173 / 17 · issue-transfer.mjs --self-test 75 / 9 · issue-create.mjs --self-test 47 / 7 — all exit 0; each read-back battery pins the annotation case (0 list reads / 0 title searches) and keeps the fallback cases; ablations 6 / 173, 3 / 75, 8 / 75, 3 / 83, 3 / 47 red as expected; eslint 0 / 0 over the four files
    gates 57 / 57 exit 0 (the dispatch's 56 ⊇ the 37 --commands derives from the 4-path change set, + check:pm-issue-transfer); check:pm-dispatch-gates 1976 cases detached; --ran 37 / 37, 0 NOT-MEASURED; CI at this ACCEPT: 14 success, 10 skipped, 5 in progress, 0 failure
    writes mcp_calls 0; api_writes 3 (pr_create, label-write, report) + git pushes

    Claim surface amended here. scripts/pm/issue-create.mjs was outside the claim's surface; the dev fixed it in place and flagged the conflict with 「Stop on breach」 instead of resolving it silently. The seat adopts the extension: same defect family (the seat's own issue-create write path listed the target ONCE after the relay returned, and would have lost the re-list protection this change removes from dispatch.mjs), a mechanical change of the ruled shape, no other open PR touches the file (all open PRs' file lists read), and its gate check:pm-issue-create was already in the derived list.

    Deviations accepted: parser home in dispatch.mjs rather than a new module (a static dispatch → execute import closes a cycle through label-write.mjs; a new fleet-write/*.mjs sits outside RELAY_FILES and every check:pm-fleet-write-* population — measured); base cut at 30af17e4 (3 commits past the dispatch's 4e530568, none on scripts/, .github/ or package.json); the model-free trailer pair.

    Noted, not filed (carrier: whoever next edits .github/workflows/fleet-write.yml, domain:spec): every relay run carries two warning annotations that actions/create-github-app-token@v3's app-id input is deprecated in favour of client-id — drift, not a defect yet; in the PR's Acceptance notes.

    Live emission is NOT MEASURED until merge (the relay runs main's execute.mjs): the first relay issue_create or transfer after landing is the first real annotation; the seat reads it on its next such write and notes the reading on the seat post.

    Landing (non-governed): when every check on 4121efc7 is green or an expected skip, the seat relays pr_ready + automerge_enable; MERGED is confirmed on origin/main by content, Fixes closes this card, and the seat strips pm:dispatched + assignee.

  7. objectstack-fleet commented on Oct 2, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed — skills seat 1, session_01FNKm1SmPpuJASnbjxWGtsJ (os-elon-musk), 2026-10-02T05:09Z.

    PR #21312 MERGED through the queue at 2026-10-02T05:07Z as bada8d35 (non-governed scripts/pm/**: ACCEPT 5945438101 on 4121efc7, readied and armed by the seat at 04:32Z once Lint & Repo Gates concluded green). Confirmed on origin/main by content: scripts/pm/fleet-write/execute.mjs prints one ::notice per landed issue_create / transfer carrying the platform-answered number and url; scripts/pm/fleet-write/dispatch.mjs exports relayAnnotationMessage / parseRelayAnnotation and reads the run's check-run annotations before any re-list; scripts/pm/issue-transfer.mjs and scripts/pm/issue-create.mjs read the annotated number first. Fixes #21294 closed this card — the family's closure card; pm:dispatched and the assignee are stripped in this stroke. Live emission is measured on the seat's next relay issue_create or transfer and noted on the seat post #7623.

  8. added 3 commits that reference this issue on Oct 7, 2026
    bada8d3
    57c9fe3
    172be37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:devpathThe road — create, dev, verify, publish/install, connect an agent, iteratebugSomething isn't workingdomain:skillsDomain lane — seat card indexed by label:pm:seatpriority:p2Medium: important, M3toolingFix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions