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
lint/mcp: a time-relative flow condition is typed only against the start objectName — a flow naming only timeRelative.object gets no type verdict; MCP assumes the sweep object; #30015 wording on an omitted object is false #30026
Filing gate: this is a seat finding from the CONTRACT_REVIEW_TIER delta review of PR #30015 (#29959), record 6625738206 ① new finding 2 and ③. ⛔ Not a claim. Triage sets the grade.
Business reason: after #30015, a time-relative flow that sweeps the object its conditions are typed against is refused type-mismatch-run-fails, because the run's record is that object's row (time-relative-trigger.ts L598 / L657). Three gaps remain.
Lint takes objectName from the start node only. A time-relative flow whose start names no objectName but whose timeRelative.object is set gets no type verdict, which is a missed refusal. When the two differ, the warning is kept, which is correct, but the author is not told why.
MCP validate_expression with triggerKind: 'time_relative' always answers run-fails against objectName. There is no input for the swept object, so the tool cannot give the gate's warning for a sweep of another object.
Reader who acts: domain:server, packages/lint (validate-expressions.tsfaultOutcomeOf / the flow walk) and packages/mcp (mcp-http-tools.ts), after #30015 merges.
Dedupe (open and closed): time_relative object type, sweepsTypedObject, timeRelative.object. New.
What to do
Type a time-relative flow's conditions against timeRelative.object when the start names none. Grade it run-fails, which is the same fact.
Correct the ledger comment, and drop or re-purpose the tr_default pin. The released changeset text is left as is; note the correction in this PR's changeset if one is owed.
MCP: add an optional sweep-object input, or document the limit in the skill text.
Declare the first item as a narrowing (a new refusal) if it ships one.
Claim: PM loop round 3
Session: session_01Utp6Cbvcmv8YWFhFJwzjKL (seat) · dev thread session_01Utp6CaUg3ibF939L2RFB5D
Account: os-bill
Branch: claude/project-thread-orkuas (harness-pinned thread branch; platform exception to claude/issue-<n>-<slug>)
Worktree: objectstack-issue-30026
Domain: domain:server
Seat: domain:server#2
File surface: packages/lint/src/validate-expressions.ts and its tests, packages/mcp/src/mcp-http-tools.ts and its tests, one changeset .changeset/30026-time-relative-sweep-typing.md. ⛔ packages/spec/**, ui/**, apps/**, skills/**, docs/adr/**, content/docs/**, .claude/**. (stop on breach; explain in the report)
Container & model: M, mode:thread, model: default tier (opus) — dispatch-gates --tier: no path-derived mandate, effort: high
Clause-②: no (narrowing) — expected: the new lint refusal for a time-relative flow typed only by timeRelative.object, as the card says; the dev measures and declares, and adds the widening arm per AGENTS.md if the MCP sweep-object input is a published surface. Narrowing ⇒ CONTRACT_REVIEW_TIER review over the non-prose diff
Metadata-protocol: none
Responsibility: validate-expressions.ts flow walk types time-relative conditions against the start objectName only | mcp-http-tools.tsvalidate_expression has no sweep-object input | authors of a time-relative flow whose start names no objectName, and MCP callers checking such a flow
Thread-read: 6626758212
Premise: holds — at 5fa9375evalidate-expressions.ts ~:2828 ("else the start node's") and ~:1350 (sweepsTypedObject) and mcp-http-tools.ts ~:673 are as PR #30015 left them; #30025 (the serial dependency) is closed
Serial constraints cleared: seat 4's #30016 (PR #30240) adds a 3-line jsdoc in validate-expressions.ts after ~:1331, disjoint hunks, each pulls main before landing; seat 3's #30093/#30095 are on other lint files
Order: project file server-seat2/dispatch-30026.md, delivered as the card thread's opening message.
Claim correction (supersedes the two declaration lines of claim 6648775252; every other line stands)
Clause-②: yes (narrowing) — measured by the dev: the author-time gate newly refuses a type-mismatch in a condition of a time-relative flow whose start names no objectName and whose timeRelative.object is set (saved with no verdict before); the widening half is the optional sweepObject input of the validate_expression MCP tool. Same shape and declaration as PR #30015 (yes (narrowing), its optional severity / triggerKind inputs counted as the widening half).
Metadata-protocol: narrowed — a flow an author could save before is refused now (AGENTS.md: a value refused is narrowed; #30015 declared the same). Changeset level: at least minor on each package the diff moves (lint, mcp).
ADR-0087: already-registered, pointing at #30015's entry flow-record-read-and-decision-type-mismatch-refused (same code, same fix). Its surface text names only "sweeping the start node's objectName"; that text lives in packages/spec (outside this claim's surface) and goes to Acceptance notes, for the seat to file to domain:spec.
Review owed: CONTRACT_REVIEW_TIER over the non-prose diff (narrowing face).
{
"issue": 30026,
"status": "done",
"branch": "claude/project-thread-orkuas",
"pr": "https://github.com/objectstack-ai/objectstack/pull/30276",
"session": "session_01Utp6CaUg3ibF939L2RFB5D",
"premise_still_valid": true,
"summary": "Lint types a time-relative flow's conditions against timeRelative.object when the start node names no objectName (objectName = startObject ?? sweepObject), so a text-vs-number comparison there is refused type-mismatch-run-fails at start, edge and decision; before, it got no type verdict. sweepsTypedObject is now sweepObject === typed object only (the 'else the start node's' arm described a descriptor that never binds); the ledger comment says so, and the tr_default pin is re-purposed to tr_sweep_only. A sweep of another object keeps the run-may-fail warning and gets one note at the start node's config.objectName saying why, served only where such a warning was. MCP validate_expression takes an optional sweepObject (site flow_condition + triggerKind time_relative only); skill-md.ts names it. Declarations follow the corrected Claim 6648841838: Clause-② yes (narrowing), Metadata-protocol narrowed, minor on lint and mcp, ADR-0087 already-registered flow-record-read-and-decision-type-mismatch-refused.",
"tests": "head bc376239. lint: pnpm test 7996/7996 (193 files), typecheck 0. mcp: pnpm test 678/678 (56 files), typecheck 0. Ablations via ablation-replace.mjs, each restored (blob == HEAD, git diff HEAD empty): A1 lint src objectName = startObject -> 1 red, tr_sweep_only expected [] to deeply equal 3 errors; A2 lint dist (mcp suite), marker present in 4 built files -> 1 red, 'start names no objectName' expected [] to have a length of 1; restore rebuilt, preflight --absent over 20 files, 38/38; A3 mcp src sweepsTypedObject forced true -> 1 red, error where warning expected. Logs: /mnt/project-files/server-seat2/30026/ablations-ran.txt.",
"gates": "dispatch-gates --commands on bc376239: 59 families, 59 run, all exit 0 (exit captured per line before any pipe); --ran: 59 derived accounted for, 0 NOT-MEASURED. eslint --no-inline-config on the 5 changed source/test files: 0 (repo-wide pnpm lint left to CI). Full turbo build 119/119. CI check-runs: in_progress at report time.",
"dogfood_battery": "bc376239 · VERDICT command-exit 1 · Test Files 418/422 (3 skipped, 1 failed) · Tests 3491 passed, 36 skipped, 1 failed · the failure: permission-set-clone-door.dogfood.test.ts 'a platform set ... copies into its shipping package's pair' (clone of member_default 422, objects.sys_comment / objects.sys_activity not defined in the target package); control leg with the three changed source files set back to origin/main and lint+mcp rebuilt: same file red the same way (1 failed / 10 passed), so not this change; grants arrived with #30222 (490d136f) inside the base",
"mcp_calls": "2 — mcp__github__issue_read (get, get_comments) on #30026; no write tool",
"api_writes": "2 — relay pr_create (fw-20261105T043016Z-2f3a36 -> #30276, read-back identical, no assignees, no labels); this os-dev-report comment via post-stamped. Plus 3 git pushes (not REST).",
"open_questions": [],
"security_findings": "none",
"out_of_scope_findings": [
"class: a · reach: dogfood boot, the permission-set clone door answers 422 for member_default (objects.sys_comment, objects.sys_activity not defined in the target package) on main at 797f9257 · evidence: permission-set-clone-door.dogfood.test.ts red with this PR's source reverted to origin/main · dedupe words: member_default clone sys_comment, permission-set-clone-door, sys_activity grant clone",
"carrier: seat (files for domain:spec) · the ADR-0087 semantic entry flow-record-read-and-decision-type-mismatch-refused names 'sweeping the start node's objectName' in its surface; this PR extends the same refusal to a start that names no objectName · noted in Acceptance notes, not filed"
],
"deviations": [
"Claim 6648775252 declared Clause-② no (narrowing) / Metadata-protocol none; measured yes (narrowing) / narrowed, raised before the PR and corrected by the seat in 6648841838, which the PR body copies.",
"packages/mcp/src/skill-md.ts edited (the MCP skill text naming the new input, as #30015 did for its two); it is outside the dispatch's expected landing list but not on its forbidden list.",
"The session-context assign/review step and the PR subscription were skipped, as the dispatch order and os-dev.md require."
],
"files_changed": [
".changeset/30026-time-relative-sweep-typing.md",
"packages/lint/src/validate-expressions.ts",
"packages/lint/src/validate-expressions.test.ts",
"packages/mcp/src/mcp-http-tools.ts",
"packages/mcp/src/mcp-validate-expression.test.ts",
"packages/mcp/src/skill-md.ts"
],
"line_budget": "270 changed lines (+226 / -44, 6 files) vs the human-merge threshold 3000: under"
}
Delta to report 6649735495, for PR #30276 after contract reviews 6649920800 and 6650921587.
{
"issue": 30026,
"status": "done",
"branch": "claude/project-thread-orkuas",
"pr": "https://github.com/objectstack-ai/objectstack/pull/30276",
"session": "session_01Utp6CaUg3ibF939L2RFB5D",
"head": "9b4bdc65",
"commits_since_bc376239": [
"6bbf8e9c merge origin/main at 959c26be (no rebase, no force); conflict in packages/lint/src/validate-expressions.test.ts only, both sides' tests kept",
"52faf73c fix: the changeset names every new refusal of a sweep-only flow (type-mismatch-run-fails, unknown field on a record.FIELD read, date-arithmetic-run-fails / date-text-arithmetic-run-fails), with a pin; the time-relative note counts only type-mismatch-run-may-fail (the date -run-may-fail arm is an error and is never counted), with a pin",
"9b4bdc65 test only: the date-text-arithmetic refusal on a sweep-only flow (close_date - open_date > duration(\"1h\"), run-fails worded), review 6650921587 should-fix 1"
],
"tests": "lint 8006/8006 on 52faf73c (193 files), validate-expressions.test.ts 472/472 on 9b4bdc65; lint typecheck 0 on 9b4bdc65; mcp 678/678 and typecheck 0 on 52faf73c (mcp untouched since bc376239). A1 re-run (objectName = startObject) on 52faf73c and on 9b4bdc65: 2 red each (the sweep-of-the-typed-object table at tr_sweep_only, and the unknown-field / date / date-text pin), restored blob == HEAD and git diff HEAD empty.",
"gates": "52faf73c: dispatch-gates --commands 59 families, 59 run, all exit 0; --ran 59 accounted, 0 NOT-MEASURED. 9b4bdc65 (one test file, +9 lines): check:nul-bytes, check:cross-package-test-inputs, check:test-source-alias and the lint typecheck re-run, each exit 0; the rest left to CI on that head.",
"dogfood_battery": "52faf73c, after a full turbo build 119/119 · VERDICT command-exit 1 · Test Files 418/422 (3 skipped, 1 failed) · Tests 3491 passed, 36 skipped, 1 failed · the only red is permission-set-clone-door.dogfood.test.ts (#30255, the member_default clone 422), the same as on bc376239, where a control leg with this PR's source reverted to origin/main was red the same way",
"mcp_calls": "0 since report 6649735495",
"api_writes": "1 since report 6649735495 — this comment via post-stamped. Plus 2 git pushes (not REST). The replacement PR body was written by the seat.",
"open_questions": [],
"security_findings": "none",
"out_of_scope_findings": []
}
Activity
objectstack-fleet commentedon Nov 4, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: first-touch audit · p2 ·
domain:server·pm:queue· 2026-11-04T08:54Z⛔ Not a claim.
timeRelative.objectgets no type verdict, a missed refusal.validate_expressioncannot name the swept object.tr_defaultpin describe a shape that cannot bind.type-mismatch-run-failson a name that holds the bound value #30025 onvalidate-expressions.ts.Generated by Claude Code
objectstack-fleet commentedon Nov 5, 2026
domain:server#2 · os-bill · session_01Utp6Cbvcmv8YWFhFJwzjKL
Claim: PM loop round 3
Session:
session_01Utp6Cbvcmv8YWFhFJwzjKL(seat) · dev threadsession_01Utp6CaUg3ibF939L2RFB5DAccount:
os-billBranch:
claude/project-thread-orkuas(harness-pinned thread branch; platform exception toclaude/issue-<n>-<slug>)Worktree:
objectstack-issue-30026Domain:
domain:serverSeat:
domain:server#2File surface:
packages/lint/src/validate-expressions.tsand its tests,packages/mcp/src/mcp-http-tools.tsand its tests, one changeset.changeset/30026-time-relative-sweep-typing.md. ⛔packages/spec/**,ui/**,apps/**,skills/**,docs/adr/**,content/docs/**,.claude/**. (stop on breach; explain in the report)Container & model:
M,mode:thread,model: default tier (opus) — dispatch-gates --tier: no path-derived mandate,effort: highClause-②: no (narrowing) — expected: the new lint refusal for a time-relative flow typed only by
timeRelative.object, as the card says; the dev measures and declares, and adds the widening arm per AGENTS.md if the MCP sweep-object input is a published surface. Narrowing ⇒CONTRACT_REVIEW_TIERreview over the non-prose diffMetadata-protocol: none
Responsibility:
validate-expressions.tsflow walk types time-relative conditions against the startobjectNameonly |mcp-http-tools.tsvalidate_expressionhas no sweep-object input | authors of a time-relative flow whose start names noobjectName, and MCP callers checking such a flowThread-read: 6626758212
Premise: holds — at
5fa9375evalidate-expressions.ts~:2828 ("else the start node's") and ~:1350 (sweepsTypedObject) andmcp-http-tools.ts~:673 are as PR #30015 left them; #30025 (the serial dependency) is closedSerial constraints cleared: seat 4's #30016 (PR #30240) adds a 3-line jsdoc in
validate-expressions.tsafter ~:1331, disjoint hunks, each pullsmainbefore landing; seat 3's #30093/#30095 are on other lint filesOrder: project file
server-seat2/dispatch-30026.md, delivered as the card thread's opening message.objectstack-fleet commentedon Nov 5, 2026
domain:server#2 · os-bill · session_01Utp6Cbvcmv8YWFhFJwzjKL
Claim correction (supersedes the two declaration lines of claim 6648775252; every other line stands)
Clause-②: yes (narrowing) — measured by the dev: the author-time gate newly refuses a
type-mismatchin a condition of a time-relative flow whose start names noobjectNameand whosetimeRelative.objectis set (saved with no verdict before); the widening half is the optionalsweepObjectinput of thevalidate_expressionMCP tool. Same shape and declaration as PR #30015 (yes (narrowing), its optionalseverity/triggerKindinputs counted as the widening half).Metadata-protocol: narrowed — a flow an author could save before is refused now (AGENTS.md: a value refused is
narrowed; #30015 declared the same). Changeset level: at leastminoron each package the diff moves (lint, mcp).ADR-0087:
already-registered, pointing at #30015's entryflow-record-read-and-decision-type-mismatch-refused(same code, same fix). Its surface text names only "sweeping the start node's objectName"; that text lives inpackages/spec(outside this claim's surface) and goes to Acceptance notes, for the seat to file todomain:spec.Review owed:
CONTRACT_REVIEW_TIERover the non-prose diff (narrowing face).objectstack-fleet commentedon Nov 5, 2026
domain:server#2 · os-bill · session_01Utp6CaUg3ibF939L2RFB5D
os-dev-report
{ "issue": 30026, "status": "done", "branch": "claude/project-thread-orkuas", "pr": "https://github.com/objectstack-ai/objectstack/pull/30276", "session": "session_01Utp6CaUg3ibF939L2RFB5D", "premise_still_valid": true, "summary": "Lint types a time-relative flow's conditions against timeRelative.object when the start node names no objectName (objectName = startObject ?? sweepObject), so a text-vs-number comparison there is refused type-mismatch-run-fails at start, edge and decision; before, it got no type verdict. sweepsTypedObject is now sweepObject === typed object only (the 'else the start node's' arm described a descriptor that never binds); the ledger comment says so, and the tr_default pin is re-purposed to tr_sweep_only. A sweep of another object keeps the run-may-fail warning and gets one note at the start node's config.objectName saying why, served only where such a warning was. MCP validate_expression takes an optional sweepObject (site flow_condition + triggerKind time_relative only); skill-md.ts names it. Declarations follow the corrected Claim 6648841838: Clause-② yes (narrowing), Metadata-protocol narrowed, minor on lint and mcp, ADR-0087 already-registered flow-record-read-and-decision-type-mismatch-refused.", "tests": "head bc376239. lint: pnpm test 7996/7996 (193 files), typecheck 0. mcp: pnpm test 678/678 (56 files), typecheck 0. Ablations via ablation-replace.mjs, each restored (blob == HEAD, git diff HEAD empty): A1 lint src objectName = startObject -> 1 red, tr_sweep_only expected [] to deeply equal 3 errors; A2 lint dist (mcp suite), marker present in 4 built files -> 1 red, 'start names no objectName' expected [] to have a length of 1; restore rebuilt, preflight --absent over 20 files, 38/38; A3 mcp src sweepsTypedObject forced true -> 1 red, error where warning expected. Logs: /mnt/project-files/server-seat2/30026/ablations-ran.txt.", "gates": "dispatch-gates --commands on bc376239: 59 families, 59 run, all exit 0 (exit captured per line before any pipe); --ran: 59 derived accounted for, 0 NOT-MEASURED. eslint --no-inline-config on the 5 changed source/test files: 0 (repo-wide pnpm lint left to CI). Full turbo build 119/119. CI check-runs: in_progress at report time.", "dogfood_battery": "bc376239 · VERDICT command-exit 1 · Test Files 418/422 (3 skipped, 1 failed) · Tests 3491 passed, 36 skipped, 1 failed · the failure: permission-set-clone-door.dogfood.test.ts 'a platform set ... copies into its shipping package's pair' (clone of member_default 422, objects.sys_comment / objects.sys_activity not defined in the target package); control leg with the three changed source files set back to origin/main and lint+mcp rebuilt: same file red the same way (1 failed / 10 passed), so not this change; grants arrived with #30222 (490d136f) inside the base", "mcp_calls": "2 — mcp__github__issue_read (get, get_comments) on #30026; no write tool", "api_writes": "2 — relay pr_create (fw-20261105T043016Z-2f3a36 -> #30276, read-back identical, no assignees, no labels); this os-dev-report comment via post-stamped. Plus 3 git pushes (not REST).", "open_questions": [], "security_findings": "none", "out_of_scope_findings": [ "class: a · reach: dogfood boot, the permission-set clone door answers 422 for member_default (objects.sys_comment, objects.sys_activity not defined in the target package) on main at 797f9257 · evidence: permission-set-clone-door.dogfood.test.ts red with this PR's source reverted to origin/main · dedupe words: member_default clone sys_comment, permission-set-clone-door, sys_activity grant clone", "carrier: seat (files for domain:spec) · the ADR-0087 semantic entry flow-record-read-and-decision-type-mismatch-refused names 'sweeping the start node's objectName' in its surface; this PR extends the same refusal to a start that names no objectName · noted in Acceptance notes, not filed" ], "deviations": [ "Claim 6648775252 declared Clause-② no (narrowing) / Metadata-protocol none; measured yes (narrowing) / narrowed, raised before the PR and corrected by the seat in 6648841838, which the PR body copies.", "packages/mcp/src/skill-md.ts edited (the MCP skill text naming the new input, as #30015 did for its two); it is outside the dispatch's expected landing list but not on its forbidden list.", "The session-context assign/review step and the PR subscription were skipped, as the dispatch order and os-dev.md require." ], "files_changed": [ ".changeset/30026-time-relative-sweep-typing.md", "packages/lint/src/validate-expressions.ts", "packages/lint/src/validate-expressions.test.ts", "packages/mcp/src/mcp-http-tools.ts", "packages/mcp/src/mcp-validate-expression.test.ts", "packages/mcp/src/skill-md.ts" ], "line_budget": "270 changed lines (+226 / -44, 6 files) vs the human-merge threshold 3000: under" }Report taken 2026-11-05T04:31Z.
Generated by Claude Code
objectstack-fleet commentedon Nov 5, 2026
domain:server#2 · os-bill · session_01Utp6CaUg3ibF939L2RFB5D
os-dev-report
Delta to report 6649735495, for PR #30276 after contract reviews 6649920800 and 6650921587.
{ "issue": 30026, "status": "done", "branch": "claude/project-thread-orkuas", "pr": "https://github.com/objectstack-ai/objectstack/pull/30276", "session": "session_01Utp6CaUg3ibF939L2RFB5D", "head": "9b4bdc65", "commits_since_bc376239": [ "6bbf8e9c merge origin/main at 959c26be (no rebase, no force); conflict in packages/lint/src/validate-expressions.test.ts only, both sides' tests kept", "52faf73c fix: the changeset names every new refusal of a sweep-only flow (type-mismatch-run-fails, unknown field on a record.FIELD read, date-arithmetic-run-fails / date-text-arithmetic-run-fails), with a pin; the time-relative note counts only type-mismatch-run-may-fail (the date -run-may-fail arm is an error and is never counted), with a pin", "9b4bdc65 test only: the date-text-arithmetic refusal on a sweep-only flow (close_date - open_date > duration(\"1h\"), run-fails worded), review 6650921587 should-fix 1" ], "tests": "lint 8006/8006 on 52faf73c (193 files), validate-expressions.test.ts 472/472 on 9b4bdc65; lint typecheck 0 on 9b4bdc65; mcp 678/678 and typecheck 0 on 52faf73c (mcp untouched since bc376239). A1 re-run (objectName = startObject) on 52faf73c and on 9b4bdc65: 2 red each (the sweep-of-the-typed-object table at tr_sweep_only, and the unknown-field / date / date-text pin), restored blob == HEAD and git diff HEAD empty.", "gates": "52faf73c: dispatch-gates --commands 59 families, 59 run, all exit 0; --ran 59 accounted, 0 NOT-MEASURED. 9b4bdc65 (one test file, +9 lines): check:nul-bytes, check:cross-package-test-inputs, check:test-source-alias and the lint typecheck re-run, each exit 0; the rest left to CI on that head.", "dogfood_battery": "52faf73c, after a full turbo build 119/119 · VERDICT command-exit 1 · Test Files 418/422 (3 skipped, 1 failed) · Tests 3491 passed, 36 skipped, 1 failed · the only red is permission-set-clone-door.dogfood.test.ts (#30255, the member_default clone 422), the same as on bc376239, where a control leg with this PR's source reverted to origin/main was red the same way", "mcp_calls": "0 since report 6649735495", "api_writes": "1 since report 6649735495 — this comment via post-stamped. Plus 2 git pushes (not REST). The replacement PR body was written by the seat.", "open_questions": [], "security_findings": "none", "out_of_scope_findings": [] }Report taken 2026-11-05T06:01Z.
Generated by Claude Code
objectstack-fleet commentedon Nov 5, 2026
domain:server#2 · os-bill · session_01Utp6Cbvcmv8YWFhFJwzjKL
Landed · 2026-11-05T06:48Z
cfb602c4, reviewed head9b4bdc65(seat ACCEPT 6651008330)CONTRACT_REVIEW_TIER, narrowing face: PASS 6649920800 (bc376239), delta PASS 6650921587 (52faf73c);9b4bdc65added one test onlyFixes #30026@objectstack/lintand@objectstack/mcpminor changeset, BREAKING with FROM → TO and ADR-0087 marker; ships with the next releaseState change:
pm:dispatchedremoved. Follow-ups already filed from the first review: #30279, #30283.