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"
}
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