You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
automation: GET /automation/_status reports bound:true for a time_relative flow whose trigger refused to bind it, with no unboundCause #27415
QA-source: #27409 · automation.trigger-type-matrix · observed beside the clauses
Found by an off-clause probe in the 18.3.0 release-candidate QA run #27409, at framework c4c515ad, on a showcase boot with scheduled work enabled.
Reach is low: the save door's lint refuses this descriptor, so reproducing it needs the unlinted-writes escape hatch or a stored row from before that lint existed. It is still a status door that contradicts the server's own log.
Reproduction
Boot the showcase with OS_AUTOMATION_SCHEDULED_WORK_ENABLED=1 and OS_ALLOW_UNLINTED_METADATA_WRITES=1.
PUT /api/v1/meta/flow/qa_tr_both with a copy of showcase_task_due_reminder whose start node's config.timeRelative carries both offsetDays and withinDays. An unknown key, or schedule nested inside it, does the same. It answers 200.
The server log reads: WARN [time-relative] flow qa_tr_both has no valid timeRelative descriptor - not bound.
GET /api/v1/automation/_status reports {name: "qa_tr_both", bound: true, triggerType: "time_relative"} with no unboundCause, and no sweep run ever appears.
Expected vs actual
Expected: bound: false with an unboundCause naming the binding failure. The Packaged Automation page's status badge reads this row.
Actual: bound: true.
Mechanism
The engine appears to set bound when it hands the flow to the trigger, while the time-relative trigger declines the flow afterwards on its descriptor safeParse. The decline is not reported back to the engine's status.
Not located to a file and line in this run.
Suggested acceptance
A flow the time-relative trigger declines reads bound: false with an unboundCause on _status.
A valid time_relative flow still reads bound: true.
Read fresh. GET /automation/_status reports bound: true for a time_relative flow its trigger refused to bind, with no unboundCause. Reach is low: the save lint refuses the descriptor, so reproducing it needs the unlinted-writes escape hatch. p3.
⛔ The status reads the trigger's own bind result. It does not rebuild it.
Triage: lands in packages/triggers/trigger-schedule/src/time-relative-trigger.ts (domain:server); rationale: this concurs with the first touch at 06:03Z (comment 6489293901) on class, domain, area and p3 (low reach, because it needs the unlinted-writes escape hatch). The landing file and the platform's existing remedy are now located. Labels stay as they are (bug, priority:p3, pm:queue, area:automation, domain:server). Read at origin/main ded67bfb, 2026-10-29T09:55Z.
Class (a): a reproducible defect on the public _status door.
Mechanism located (the card says it was not located): FlowTrigger.start returns void. TimeRelativeTrigger.start (lines 334 to 342) logs "not bound" and returns. The engine's activateFlowTrigger (packages/services/service-automation/src/engine.ts line 3825) then marks the flow bound in boundFlowTriggers.
The platform's existing remedy: schedule-trigger.ts already solved this same shape. Its docblock (around lines 454 to 476, "Why it throws, and does not merely log and return") throws from start, so the engine's catch never marks the flow bound, and getTriggerBindingAudit() reports it. The fix is to give the time-relative descriptor refusal the same treatment, a one-file change with no engine or interface change. This is a lead, not an answer.
Responsibility: (1) the platform's time-relative trigger produces the risk. (2) The throw-on-refusal path in the engine already covers it, and this trigger does not use it. (3) It is reached only through OS_ALLOW_UNLINTED_METADATA_WRITES or a stored row from before the lint existed, so it stays p3.
Prior rulings read: check-prior-rulings.mjs --card 27415 named no decision that governs the bind signal. The hits were term noise (ADR-0044 D2, ADR-0028 D6, ADR-0041 §4, ADR-0088 §1).
Claim: PM loop round 1
Session: session_017xRBcScm27Q3R5mkYLPWdB
Account: sunhaolin
Branch: claude/issue-27415-time-relative-bind-verdict
Worktree: objectstack-issue-27415
Domain: domain:server
Seat: domain:devx#1
File surface: packages/triggers/trigger-schedule/src/time-relative-trigger.ts (start only) and its tests under packages/triggers/trigger-schedule, one @objectstack/trigger-schedule changeset; packages/services/service-automation/** is out of surface (in-flight #27237) (stop on breach; explain in the report)
Container & model: S, mode:subagent, model: default (dispatch-gates --tier at c4c515a: "no path-derived mandate"), effort: medium
Clause-②: no
Metadata-protocol: none
Responsibility: trigger-schedule's TimeRelativeTrigger.start logs and returns on an invalid descriptor, so the engine marks the flow bound | schedule-trigger.ts already throws from start for the same shape, and the engine reads a throw as unbound | reached only through the unlinted-writes escape hatch or a pre-lint stored row; low reach
Thread-read: 6494096554
Premise: holds (triage completion located the mechanism on origin/main ded67bfb; the dev re-measures before editing)
Serial constraints cleared: none — the 10 open domain:server + pm:dispatched claims were read; none names packages/triggers/trigger-schedule; #27237 owns packages/services/service-automation/**, which this card does not touch
Maintainer direct dispatch (cross-lane claim authority): the maintainer, in session session_017xRBcScm27Q3R5mkYLPWdB on 2026-10-29, verbatim: 「你应该使用 pm-dispatch 技能处理 issue 和 pr」. This devx-seat session claims this domain:server card on that instruction; the card stays domain:server.
domain:devx#1 · sunhaolin · session_017xRBcScm27Q3R5mkYLPWdB
os-dev-report
{
"issue": 27415,
"status": "done",
"branch": "claude/issue-27415-time-relative-bind-verdict",
"pr": "#27556",
"session": "session_017xRBcScm27Q3R5mkYLPWdB",
"premise_still_valid": true,
"summary": "Premise measured at origin/main 57c51aa: TimeRelativeTrigger.start logged 'has no valid timeRelative descriptor - not bound' and returned, and the engine's activateFlowTrigger then set boundFlowTriggers (the set sits inside the try, after start). That return is why the status row read bound:true. The fix: on a failed safeParse, start now calls this.stop(flowName), logs the same warn line (byte-identical), and throws the same sentence. This matches refuseMissingOrganization / refuseScheduledWorkDisabled, so the engine's existing catch leaves the flow unbound and the status row reads bound:false with unboundCause 'binding_failure'. One file in src, start only. No change to service-automation or the FlowTrigger interface. PM assumption partly disproved: schedule-trigger.ts throws only for its organization and policy refusals. Its own descriptor refusal ('no recognizable schedule descriptor - not bound') still logs and returns, which is the same shape as this bug (see out_of_scope_findings).",
"tests": "At head da85763, under the lock: pnpm --filter @objectstack/trigger-schedule test && typecheck. Result: Test Files 11 passed (11), Tests 196 passed (196), tsc --noEmit exit 0, VERDICT command-exit 0. tsc --listFiles shows 11 .test.ts files in the program, the new e2e file among them. New pins: (1) time-relative-trigger.test.ts. Three invalid shapes (both modes, an unknown key, schedule nested inside the descriptor): start throws a message naming the flow, arms no job, and warns once. A re-bind with a broken descriptor drops the sweep armed earlier. Control: a valid descriptor does not throw and arms its sweep. The existing invalid-descriptor case now asserts the throw. (2) time-relative-bind-status-e2e.test.ts (new). Real TimeRelativeTrigger on the real AutomationEngine: the invalid flow's row is bound:false, triggerType time_relative, unboundCause binding_failure, with no sweep armed. The valid control row is bound:true with no unboundCause key, and its sweep is armed. The engine-only twin pin is engine.test.ts 'ON: a genuine bind failure reads as one on the status row too' in service-automation, which is outside the surface. Ablation: scripts/ablation-replace.mjs swapped 'throw new Error(sentence);' for 'return;'. The anchor went 1 to 0 and the blob 520bd258c30a to cf719226888f. Result: Test Files 2 failed (2), Tests 6 failed | 60 passed (66), the expected red direction. Restore leg: blob == HEAD 520bd258c30a and git diff HEAD empty. No rebuild was needed: the trigger is imported by relative path, and the engine (via dist) is unchanged in this diff.",
"gates": "dispatch-gates --commands --repo objectstack-ai/objectstack derived 57 families. Merge base 57c51aa, 4 paths, +199/-17. All 57 ran locally, each exit captured before any pipe; --ran reconciles 57 derived, 57 run, 0 UNRUN. 54 exited 0. check:nul-bytes, check:cross-package-test-inputs, check:test-source-alias and check:engine-double-contract were re-run at da85763: exit 0 x4. NOT MEASURED locally, left to CI: check:dual-build-cjs-loads (exit 3, PREREQUISITE NOT MET, needs every package's dist); check:query-options-erasure (exit 124, hit the 300s local timeout, repo-wide ESLint); check:type-check-debt (exit 124, hit the 300s timeout). Closure build pnpm --filter '@objectstack/trigger-schedule^...' build: VERDICT command-exit 0. PR check-runs at da85763 when the report was written: every required context in_progress (Lint * lanes, Type Check * lanes, Check Changeset, Governed Surface Queue Guard, PR-body guards, Check PR Size); skipped: Schedule gate, Packed-tarball smoke (opt-in), 18.x upgrade harness (opt-in). check-platform-checklist not owed: no exported symbol was renamed or removed.",
"dogfood_battery": "n/a: no ! in the PR title and no (narrowing) arm (Clause-②: no)",
"mcp_calls": "0",
"api_writes": "2 relay strokes, 3 REST requests: (1) pr_create, relay run 40874512050: POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos//issues/27556/assignees [sunhaolin]; (2) os-dev-report comment: POST /repos//issues/27415/comments. git push x4 to own branch, not REST.",
"files_changed": [
"packages/triggers/trigger-schedule/src/time-relative-trigger.ts",
"packages/triggers/trigger-schedule/src/time-relative-trigger.test.ts",
"packages/triggers/trigger-schedule/src/time-relative-bind-status-e2e.test.ts",
".changeset/27415-time-relative-descriptor-refusal-unbound.md"
],
"line_budget": "n/a: no skills/* file touched. PR size +199/-17 = 216 changed lines, under the 3000 threshold.",
"deviations": [
"First push was refused by check:commit-card-trailers (model name in the Co-Authored-By trailer, which the harness reminder had prescribed). The unpublished commit was amended to the model-free pair; nothing published was rewritten.",
"dispatch-gates warned STALE TREE: the branch was 7 commits behind origin/main, and the 2 changed files are scripts/gen-sdui-reference.mjs and scripts/pm/dispatch-gates.self-test.mjs. origin/main was not merged into the branch; neither file reads this diff's paths.",
"The 57-family local gate loop ran at the changeset commit, before the final test-fixture commit (da85763 changed only the e2e test file). The 4 families that read test files were re-run at head.",
"Whole-repo pnpm test (AGENTS.md section 10) was not run. Local scope follows os-dev: package test/typecheck plus derived gates, with test:repo and the full farm left to CI.",
"Live showcase boot repro via _status was not run. The engine-level e2e pin covers the same getFlowRuntimeStates row that the route serves."
],
"open_questions": [
{
"question": "The PR assignee instructions conflict. os-dev.md says pr_create carries assignees: [card's LOGIN]. The scripts/pm/fleet-write/ops.mjs pr_create header says a dev's create carries no assignees and the seat's own account is never assigned to a pull. Which one governs?",
"options": [
"A: os-dev.md governs. This run followed it and assigned sunhaolin, the card's assignee.",
"B: the ops.mjs header governs. The seat removes the PR assignee and os-dev.md is corrected."
],
"recommendation": "A for this PR, because os-dev.md says the agent file wins on conflict. The seat should reconcile the two texts in one place."
}
],
"out_of_scope_findings": [
"class: a (same family as this card) · reach: NOT measured at a public door. Read-only inference from ScheduleTrigger.start: its 'no recognizable schedule descriptor - not bound' branch logs, releases and returns, so the engine marks the flow bound and _status would read bound:true. This needs the same throw. The file is outside this card's claimed surface, so it was not fixed in place · dedupe words: schedule trigger, no recognizable schedule descriptor, bound true, unboundCause, _status",
"carrier: none · noted, not filed. In both triggers the 'job service unavailable - not scheduled' branch returns instead of throwing, so the flow reads bound:true while no job exists. This is a composition gap, a different remedy from a bad descriptor. It is a read-only inference and was not reproduced. It is recorded in the PR Acceptance notes."
]
}
Handover: PR #27556 → PM session session_017xRBcVy4VXmkQjn2MGeaWk (review and landing)
Head da85763f at handover; CI was in progress, none red. The dev report is 6496874565 (it has one open question on PR assignee, and one class (a) out-of-scope finding: ScheduleTrigger.start has the same log-and-return shape for an unrecognised descriptor, unmeasured at a public door).
Activity
objectstack-fleet commentedon Oct 29, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: 审批与自动化 | none | P⑤
Triage: p3 ·
domain:server·area:automation· 2026-10-29T06:03Z⛔ Not a claim.
GET /automation/_statusreportsbound: truefor atime_relativeflow its trigger refused to bind, with nounboundCause. Reach is low: the save lint refuses the descriptor, so reproducing it needs the unlinted-writes escape hatch. p3.bug,pm:queue.Generated by Claude Code
objectstack-fleet commentedon Oct 29, 2026
domain:devx#1 · sunhaolin · session_017xRBcScm27Q3R5mkYLPWdB
Path: 审批与自动化 | none | P⑤
Triage: lands in
packages/triggers/trigger-schedule/src/time-relative-trigger.ts(domain:server); rationale: this concurs with the first touch at 06:03Z (comment 6489293901) on class, domain, area and p3 (low reach, because it needs the unlinted-writes escape hatch). The landing file and the platform's existing remedy are now located. Labels stay as they are (bug,priority:p3,pm:queue,area:automation,domain:server). Read at origin/mainded67bfb, 2026-10-29T09:55Z._statusdoor.FlowTrigger.startreturnsvoid.TimeRelativeTrigger.start(lines 334 to 342) logs "not bound" and returns. The engine'sactivateFlowTrigger(packages/services/service-automation/src/engine.tsline 3825) then marks the flow bound inboundFlowTriggers.schedule-trigger.tsalready solved this same shape. Its docblock (around lines 454 to 476, "Why it throws, and does not merely log and return") throws fromstart, so the engine's catch never marks the flow bound, andgetTriggerBindingAudit()reports it. The fix is to give the time-relative descriptor refusal the same treatment, a one-file change with no engine or interface change. This is a lead, not an answer.OS_ALLOW_UNLINTED_METADATA_WRITESor a stored row from before the lint existed, so it stays p3.automation.getRuntimeStatus()hand-types its rows as{ name, enabled, bound }, so an SDK caller cannot readreason(or the newunboundCause) thatGET /automation/_statusalready returns #23859, automation: an approval node's escalation values are checked only at execution — timeoutHours 0.5 registers and activates, then every run fails and the record is created with no approval gate #21848, automation: a host's per-kernel scheduled-work refusal is reported with the deployment sentence —SCHEDULED_WORK_DISABLED_REASONtells a free-plan tenant to setOS_AUTOMATION_SCHEDULED_WORK_ENABLED=true(the #19834 seam has no reason slot) #21110, service-automation: a restart re-arms the trigger of a ledger-disabled packaged flow — registerTrigger ignores the activation ledger, and every matching event then logs an ERROR claiming a run-history record that is never written #20677, [finding]requires: ['triggers']withoutautomationvalidates, but at boot the record-change trigger is not installed and every flow "will never run" #20332 and 标量config.timeRelative(如timeRelative: 'daily')= 引擎解析不出任何 trigger,flow 永不触发且全层零输出 #5647 (closed, other mechanisms). No duplicate.check-prior-rulings.mjs --card 27415named no decision that governs the bind signal. The hits were term noise (ADR-0044 D2, ADR-0028 D6, ADR-0041 §4, ADR-0088 §1).Size/model suggestion: S.
Generated by Claude Code
objectstack-fleet commentedon Oct 29, 2026
domain:devx#1 · sunhaolin · session_017xRBcScm27Q3R5mkYLPWdB
Claim: PM loop round 1
Session:
session_017xRBcScm27Q3R5mkYLPWdBAccount:
sunhaolinBranch:
claude/issue-27415-time-relative-bind-verdictWorktree:
objectstack-issue-27415Domain:
domain:serverSeat:
domain:devx#1File surface:
packages/triggers/trigger-schedule/src/time-relative-trigger.ts(startonly) and its tests underpackages/triggers/trigger-schedule, one@objectstack/trigger-schedulechangeset;packages/services/service-automation/**is out of surface (in-flight #27237) (stop on breach; explain in the report)Container & model:
S,mode:subagent,model: default(dispatch-gates --tierat c4c515a: "no path-derived mandate"),effort: mediumClause-②: no
Metadata-protocol: none
Responsibility: trigger-schedule's
TimeRelativeTrigger.startlogs and returns on an invalid descriptor, so the engine marks the flow bound |schedule-trigger.tsalready throws fromstartfor the same shape, and the engine reads a throw as unbound | reached only through the unlinted-writes escape hatch or a pre-lint stored row; low reachThread-read: 6494096554
Premise: holds (triage completion located the mechanism on origin/main
ded67bfb; the dev re-measures before editing)Serial constraints cleared: none — the 10 open
domain:server+pm:dispatchedclaims were read; none namespackages/triggers/trigger-schedule; #27237 ownspackages/services/service-automation/**, which this card does not touchMaintainer direct dispatch (cross-lane claim authority): the maintainer, in session
session_017xRBcScm27Q3R5mkYLPWdBon 2026-10-29, verbatim: 「你应该使用 pm-dispatch 技能处理 issue 和 pr」. This devx-seat session claims this domain:server card on that instruction; the card staysdomain:server.Generated by Claude Code
objectstack-fleet commentedon Oct 29, 2026
domain:devx#1 · sunhaolin · session_017xRBcScm27Q3R5mkYLPWdB
os-dev-report
{
"issue": 27415,
"status": "done",
"branch": "claude/issue-27415-time-relative-bind-verdict",
"pr": "#27556",
"session": "session_017xRBcScm27Q3R5mkYLPWdB",
"premise_still_valid": true,
"summary": "Premise measured at origin/main 57c51aa: TimeRelativeTrigger.start logged 'has no valid timeRelative descriptor - not bound' and returned, and the engine's activateFlowTrigger then set boundFlowTriggers (the set sits inside the try, after start). That return is why the status row read bound:true. The fix: on a failed safeParse, start now calls this.stop(flowName), logs the same warn line (byte-identical), and throws the same sentence. This matches refuseMissingOrganization / refuseScheduledWorkDisabled, so the engine's existing catch leaves the flow unbound and the status row reads bound:false with unboundCause 'binding_failure'. One file in src, start only. No change to service-automation or the FlowTrigger interface. PM assumption partly disproved: schedule-trigger.ts throws only for its organization and policy refusals. Its own descriptor refusal ('no recognizable schedule descriptor - not bound') still logs and returns, which is the same shape as this bug (see out_of_scope_findings).",
"tests": "At head da85763, under the lock: pnpm --filter @objectstack/trigger-schedule test && typecheck. Result: Test Files 11 passed (11), Tests 196 passed (196), tsc --noEmit exit 0, VERDICT command-exit 0. tsc --listFiles shows 11 .test.ts files in the program, the new e2e file among them. New pins: (1) time-relative-trigger.test.ts. Three invalid shapes (both modes, an unknown key, schedule nested inside the descriptor): start throws a message naming the flow, arms no job, and warns once. A re-bind with a broken descriptor drops the sweep armed earlier. Control: a valid descriptor does not throw and arms its sweep. The existing invalid-descriptor case now asserts the throw. (2) time-relative-bind-status-e2e.test.ts (new). Real TimeRelativeTrigger on the real AutomationEngine: the invalid flow's row is bound:false, triggerType time_relative, unboundCause binding_failure, with no sweep armed. The valid control row is bound:true with no unboundCause key, and its sweep is armed. The engine-only twin pin is engine.test.ts 'ON: a genuine bind failure reads as one on the status row too' in service-automation, which is outside the surface. Ablation: scripts/ablation-replace.mjs swapped 'throw new Error(sentence);' for 'return;'. The anchor went 1 to 0 and the blob 520bd258c30a to cf719226888f. Result: Test Files 2 failed (2), Tests 6 failed | 60 passed (66), the expected red direction. Restore leg: blob == HEAD 520bd258c30a and git diff HEAD empty. No rebuild was needed: the trigger is imported by relative path, and the engine (via dist) is unchanged in this diff.",
"gates": "dispatch-gates --commands --repo objectstack-ai/objectstack derived 57 families. Merge base 57c51aa, 4 paths, +199/-17. All 57 ran locally, each exit captured before any pipe; --ran reconciles 57 derived, 57 run, 0 UNRUN. 54 exited 0. check:nul-bytes, check:cross-package-test-inputs, check:test-source-alias and check:engine-double-contract were re-run at da85763: exit 0 x4. NOT MEASURED locally, left to CI: check:dual-build-cjs-loads (exit 3, PREREQUISITE NOT MET, needs every package's dist); check:query-options-erasure (exit 124, hit the 300s local timeout, repo-wide ESLint); check:type-check-debt (exit 124, hit the 300s timeout). Closure build pnpm --filter '@objectstack/trigger-schedule^...' build: VERDICT command-exit 0. PR check-runs at da85763 when the report was written: every required context in_progress (Lint * lanes, Type Check * lanes, Check Changeset, Governed Surface Queue Guard, PR-body guards, Check PR Size); skipped: Schedule gate, Packed-tarball smoke (opt-in), 18.x upgrade harness (opt-in). check-platform-checklist not owed: no exported symbol was renamed or removed.",
"dogfood_battery": "n/a: no
!in the PR title and no (narrowing) arm (Clause-②: no)","mcp_calls": "0",
"api_writes": "2 relay strokes, 3 REST requests: (1) pr_create, relay run 40874512050: POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos//issues/27556/assignees [sunhaolin]; (2) os-dev-report comment: POST /repos//issues/27415/comments. git push x4 to own branch, not REST.",
"files_changed": [
"packages/triggers/trigger-schedule/src/time-relative-trigger.ts",
"packages/triggers/trigger-schedule/src/time-relative-trigger.test.ts",
"packages/triggers/trigger-schedule/src/time-relative-bind-status-e2e.test.ts",
".changeset/27415-time-relative-descriptor-refusal-unbound.md"
],
"line_budget": "n/a: no skills/* file touched. PR size +199/-17 = 216 changed lines, under the 3000 threshold.",
"deviations": [
"First push was refused by check:commit-card-trailers (model name in the Co-Authored-By trailer, which the harness reminder had prescribed). The unpublished commit was amended to the model-free pair; nothing published was rewritten.",
"dispatch-gates warned STALE TREE: the branch was 7 commits behind origin/main, and the 2 changed files are scripts/gen-sdui-reference.mjs and scripts/pm/dispatch-gates.self-test.mjs. origin/main was not merged into the branch; neither file reads this diff's paths.",
"The 57-family local gate loop ran at the changeset commit, before the final test-fixture commit (da85763 changed only the e2e test file). The 4 families that read test files were re-run at head.",
"Whole-repo pnpm test (AGENTS.md section 10) was not run. Local scope follows os-dev: package test/typecheck plus derived gates, with test:repo and the full farm left to CI.",
"Live showcase boot repro via _status was not run. The engine-level e2e pin covers the same getFlowRuntimeStates row that the route serves."
],
"open_questions": [
{
"question": "The PR assignee instructions conflict. os-dev.md says pr_create carries assignees: [card's LOGIN]. The scripts/pm/fleet-write/ops.mjs pr_create header says a dev's create carries no assignees and the seat's own account is never assigned to a pull. Which one governs?",
"options": [
"A: os-dev.md governs. This run followed it and assigned sunhaolin, the card's assignee.",
"B: the ops.mjs header governs. The seat removes the PR assignee and os-dev.md is corrected."
],
"recommendation": "A for this PR, because os-dev.md says the agent file wins on conflict. The seat should reconcile the two texts in one place."
}
],
"out_of_scope_findings": [
"class: a (same family as this card) · reach: NOT measured at a public door. Read-only inference from ScheduleTrigger.start: its 'no recognizable schedule descriptor - not bound' branch logs, releases and returns, so the engine marks the flow bound and _status would read bound:true. This needs the same throw. The file is outside this card's claimed surface, so it was not fixed in place · dedupe words: schedule trigger, no recognizable schedule descriptor, bound true, unboundCause, _status",
"carrier: none · noted, not filed. In both triggers the 'job service unavailable - not scheduled' branch returns instead of throwing, so the flow reads bound:true while no job exists. This is a composition gap, a different remedy from a bad descriptor. It is a read-only inference and was not reproduced. It is recorded in the PR Acceptance notes."
]
}
objectstack-fleet commentedon Oct 29, 2026
domain:devx#1 · sunhaolin · session_017xRBcScm27Q3R5mkYLPWdB
Handover: PR #27556 → PM session session_017xRBcVy4VXmkQjn2MGeaWk (review and landing)
Head
da85763fat handover; CI was in progress, none red. The dev report is 6496874565 (it has one open question on PR assignee, and one class (a) out-of-scope finding:ScheduleTrigger.starthas the same log-and-return shape for an unrecognised descriptor, unmeasured at a public door).Generated by Claude Code