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: a flow node config-value finding (validateStackExpressions) carries only where prose and no key path, so Studio's Problems row lists it but cannot point at the node #27828
Filing gate: ① product defect with reach measured, found while landing #27799 (PR #27826, report 6512261435, out_of_scope_findings).
Reach: Studio → Automations, any flow whose node config value the publish verdict refuses (measured on a blank expression in an Update Records value, main86aaff32). After PR #27826, the Problems list shows the finding, but its row cannot select or reveal the node; it can only print the server's locator text.
Business reason: Problems is how an author finds what blocks Publish. A row that names a node in prose but does not take them there makes a large flow slow to fix, and the canvas badge never appears on that node.
Reader who acts: the lane that owns packages/lint (spec lane per the #27482 precedent). The ui side needs no change: flow-problems.tsserverTarget already maps a flows[0].nodes[N].config… / nodes.N… path onto the node.
Duplicate search: search_issues "lint ExprIssue path flow node config value slot key path where prose Problems" → 1 hit, #17305 (closed, template-path rule scope), which is not this. The same producer shape blocked #27482's Validations arm (validation-rule findings carry where only), and flow edges got a key path in #26858; this is the node-config sibling.
What happens
validateStackExpressions (packages/lint/src/validate-expressions.ts) reports a flow node's config-value finding (e.g. expression-invalid on config.fields.id) with where = flow 'x' · node 'y' (update_record) … at config.fields.id and no path. authoring-rules.ts sets path: i.path ?? i.where, so the draft read's _diagnostics path is prose. Studio cannot place it on an element.
Expected
The finding carries a key path to the node's config value (e.g. nodes.<index>.config.fields.id, the same shape the edge findings use since #26858). The prose where stays for the CLI. With that path, Studio's existing mapping badges the node and selects it from Problems, with no ui change.
Acceptance
A lint pin: a flow node config-value finding carries the key path.
protocol.runtime-authoring-gate (or its successor) pins the draft read's _diagnostics path for that finding.
Optional ui pin (separate lane): the Problems row for that finding selects the node.
Claim: PM loop round 3 · 2026-10-30T15:12Z
Session: session_01L9qibwb6hBqszPTYJobitm
Account: os-tesla
Branch: claude/project-thread-2rqpic (card thread; the platform assigns the thread's branch and it can push only that one, written as measured instead of claude/issue-27828-<slug>)
Worktree: objectstack-issue-27828
Domain: domain:spec
Seat: domain:spec#1
Card thread: session session_01L9qibxhpYpVUxgK5jbQMXT; the dispatch order is in the seat's project, frame + card file.
File surface: packages/lint/src/validate-expressions.ts (flow node config-value findings carry a key path, the #26858 edge shape), tests, the runtime-authoring-gate _diagnostics pin, changeset. ⛔ No ui change (flow-problems.ts already maps the path) (stop on breach; explain in the report)
Container & model: S, mode:thread, model: TIER_DEFAULT (dispatch-gates --tier: no path-derived mandate), effort: high
Clause-②: no
Metadata-protocol: none
Responsibility: packages/lint reports a flow node config-value finding with prose where only | the key path at the producer, as edges got in #26858 | Studio authors fixing a flow from Problems
Thread-read: none
Premise: holds — authoring-rules.ts sets path: i.path ?? i.where, so the draft read's path is prose for these findings
Serial constraints cleared: ⛔ one held — PR #28150 edits validate-expressions.ts and is in the merge queue; the thread edits only after it merges
{
"issue": 27828,
"status": "done",
"branch": "claude/project-thread-2rqpic",
"pr": "https://github.com/objectstack-ai/objectstack/pull/28192",
"session": "session_01L9qibxhpYpVUxgK5jbQMXT",
"premise_still_valid": true,
"summary": "validateStackExpressions' flow node walk records, per node, the key each finding site judged (config.condition, config.KEY for a node-config refusal, BLOCK.SLOT_PATH for a ledger slot and a value-template refusal including connectorConfig.input from #28150, config.TEXT_SLOT, config.function for the script callable check) and stamps each top-level node's findings with path flows[F].nodes[N].KEY, the #26858 edge shape. Nested-region nodes and map-form flows keep where alone. The draft read's _diagnostics for a blank Update Records value now reads nodes.1.config.fields.name, which ui flow-problems.ts serverTarget maps to the node; no ui or consumer change. Changeset: @objectstack/lint patch, Clause-② no, Metadata-protocol none.",
"tests": "Pre-fix on 9f13ee81 (tests committed first): new lint file 5 failed | 2 passed; metadata-protocol [#27828] case failed with the prose path. Head 6360f96e: lint full vitest 180 files, 7655 passed / 1 failed (#5017 receiver meta-test, fixed by excusing nodeSlotKeys) then validate-expressions.test.ts 440/440; node-config-path + edge-condition-path + connector-input 18/18; metadata-protocol protocol.draft-publish-verdict.test.ts 18/18; lint typecheck (incl. check:test-typecheck) exit 0; metadata-protocol typecheck exit 0. Ablation on committed e8b5683d via ablation-replace (stamp line -> 'void key;', anchor 0 / replacement 1 on disk), lint rebuilt OS_SKIP_DTS=1, ablation-dist-preflight 'nodes[${nodeIndex}]' --absent exit 0: lint 6 failed | 7 passed, metadata-protocol (lint dist) 1 failed | 17 passed; restored by EXIT trap, git diff HEAD empty, blob hash = HEAD, rebuilt, preflight 'void key;' --absent exit 0, metadata-protocol 18/18.",
"gates": "dispatch-gates --commands derived 59 on 6360f96e; all 59 run with </dev/null, codes captured before pipes: 56 exit 0, 3 first exit 3 PREREQUISITE NOT MET (check-plugin-teardown-shape --self-test: shallow clone, fetched 621a4876; check:dual-build-cjs-loads, check:lean-entry-closure: unbuilt packages) -> all 3 exit 0 after the build/fetch. --ran reconcile: 59 derived, 59 run, 0 NOT-MEASURED, 0 UNRUN. Ran list: spec-seat-1/r2026-10-30/out/27828-gates-ran-6360f96e.list. CI check-runs: not read (just opened; seat reads).",
"line_budget": "235 changed lines (+229/-6) on 6360f96e, 7 files, under the 3000 threshold",
"dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
"files_changed": [
".changeset/27828-flow-node-config-finding-path.md",
"packages/lint/src/authoring-rules.ts",
"packages/lint/src/validate-expressions.edge-condition-path.test.ts",
"packages/lint/src/validate-expressions.node-config-path.test.ts",
"packages/lint/src/validate-expressions.test.ts",
"packages/lint/src/validate-expressions.ts",
"packages/metadata-protocol/src/protocol.draft-publish-verdict.test.ts"
],
"deviations": [
"The _diagnostics pin lives in protocol.draft-publish-verdict.test.ts (the draft-read harness that pins _diagnostics paths), not protocol.runtime-authoring-gate.test.ts; the card names that file 'or its successor'.",
"validate-expressions.edge-condition-path.test.ts case 'a finding off the edge condition gains no path' asserted a node condition finding has no path — the behaviour this card changes; it now asserts the node's own path, still no edge path.",
"Script callable findings (no function / retired dispatch keys) are given config.function / config.FIRST_RETIRED_KEY: they locate the node but name a key the author must write or remove, not an authored value.",
"test:repo not run locally (CI's Test Core); metadata-protocol run limited to the edited test file (no other metadata-protocol test pins a prose path for a node finding: git grep measured)."
],
"mcp_calls": "6 — reads only: issue_read get x1, issue_read get_comments x2, pull_request_read get x3; 0 writes",
"api_writes": "2 — fleet-write relay pr_create (objectstack-ai/objectstack#28192), post-stamped comment on #27828 (this report)",
"open_questions": [],
"out_of_scope_findings": []
}
Activity
objectstack-fleet commentedon Oct 30, 2026
domain:spec#1 · os-tesla · session_01L9qibwb6hBqszPTYJobitm
Claim: PM loop round 3 · 2026-10-30T15:12Z
Session:
session_01L9qibwb6hBqszPTYJobitmAccount:
os-teslaBranch:
claude/project-thread-2rqpic(card thread; the platform assigns the thread's branch and it can push only that one, written as measured instead ofclaude/issue-27828-<slug>)Worktree:
objectstack-issue-27828Domain:
domain:specSeat:
domain:spec#1Card thread: session
session_01L9qibxhpYpVUxgK5jbQMXT; the dispatch order is in the seat's project, frame + card file.File surface:
packages/lint/src/validate-expressions.ts(flow node config-value findings carry a keypath, the #26858 edge shape), tests, the runtime-authoring-gate_diagnosticspin, changeset. ⛔ No ui change (flow-problems.tsalready maps the path) (stop on breach; explain in the report)Container & model:
S,mode:thread,model: TIER_DEFAULT(dispatch-gates --tier: no path-derived mandate),effort: highClause-②: no
Metadata-protocol: none
Responsibility:
packages/lintreports a flow node config-value finding with prosewhereonly | the key path at the producer, as edges got in #26858 | Studio authors fixing a flow from ProblemsThread-read: none
Premise: holds —
authoring-rules.tssetspath: i.path ?? i.where, so the draft read's path is prose for these findingsSerial constraints cleared: ⛔ one held — PR #28150 edits
validate-expressions.tsand is in the merge queue; the thread edits only after it mergesobjectstack-fleet commentedon Oct 30, 2026
domain:spec#1 · os-tesla · session_01L9qibxhpYpVUxgK5jbQMXT
os-dev-report
{ "issue": 27828, "status": "done", "branch": "claude/project-thread-2rqpic", "pr": "https://github.com/objectstack-ai/objectstack/pull/28192", "session": "session_01L9qibxhpYpVUxgK5jbQMXT", "premise_still_valid": true, "summary": "validateStackExpressions' flow node walk records, per node, the key each finding site judged (config.condition, config.KEY for a node-config refusal, BLOCK.SLOT_PATH for a ledger slot and a value-template refusal including connectorConfig.input from #28150, config.TEXT_SLOT, config.function for the script callable check) and stamps each top-level node's findings with path flows[F].nodes[N].KEY, the #26858 edge shape. Nested-region nodes and map-form flows keep where alone. The draft read's _diagnostics for a blank Update Records value now reads nodes.1.config.fields.name, which ui flow-problems.ts serverTarget maps to the node; no ui or consumer change. Changeset: @objectstack/lint patch, Clause-② no, Metadata-protocol none.", "tests": "Pre-fix on 9f13ee81 (tests committed first): new lint file 5 failed | 2 passed; metadata-protocol [#27828] case failed with the prose path. Head 6360f96e: lint full vitest 180 files, 7655 passed / 1 failed (#5017 receiver meta-test, fixed by excusing nodeSlotKeys) then validate-expressions.test.ts 440/440; node-config-path + edge-condition-path + connector-input 18/18; metadata-protocol protocol.draft-publish-verdict.test.ts 18/18; lint typecheck (incl. check:test-typecheck) exit 0; metadata-protocol typecheck exit 0. Ablation on committed e8b5683d via ablation-replace (stamp line -> 'void key;', anchor 0 / replacement 1 on disk), lint rebuilt OS_SKIP_DTS=1, ablation-dist-preflight 'nodes[${nodeIndex}]' --absent exit 0: lint 6 failed | 7 passed, metadata-protocol (lint dist) 1 failed | 17 passed; restored by EXIT trap, git diff HEAD empty, blob hash = HEAD, rebuilt, preflight 'void key;' --absent exit 0, metadata-protocol 18/18.", "gates": "dispatch-gates --commands derived 59 on 6360f96e; all 59 run with </dev/null, codes captured before pipes: 56 exit 0, 3 first exit 3 PREREQUISITE NOT MET (check-plugin-teardown-shape --self-test: shallow clone, fetched 621a4876; check:dual-build-cjs-loads, check:lean-entry-closure: unbuilt packages) -> all 3 exit 0 after the build/fetch. --ran reconcile: 59 derived, 59 run, 0 NOT-MEASURED, 0 UNRUN. Ran list: spec-seat-1/r2026-10-30/out/27828-gates-ran-6360f96e.list. CI check-runs: not read (just opened; seat reads).", "line_budget": "235 changed lines (+229/-6) on 6360f96e, 7 files, under the 3000 threshold", "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm", "files_changed": [ ".changeset/27828-flow-node-config-finding-path.md", "packages/lint/src/authoring-rules.ts", "packages/lint/src/validate-expressions.edge-condition-path.test.ts", "packages/lint/src/validate-expressions.node-config-path.test.ts", "packages/lint/src/validate-expressions.test.ts", "packages/lint/src/validate-expressions.ts", "packages/metadata-protocol/src/protocol.draft-publish-verdict.test.ts" ], "deviations": [ "The _diagnostics pin lives in protocol.draft-publish-verdict.test.ts (the draft-read harness that pins _diagnostics paths), not protocol.runtime-authoring-gate.test.ts; the card names that file 'or its successor'.", "validate-expressions.edge-condition-path.test.ts case 'a finding off the edge condition gains no path' asserted a node condition finding has no path — the behaviour this card changes; it now asserts the node's own path, still no edge path.", "Script callable findings (no function / retired dispatch keys) are given config.function / config.FIRST_RETIRED_KEY: they locate the node but name a key the author must write or remove, not an authored value.", "test:repo not run locally (CI's Test Core); metadata-protocol run limited to the edited test file (no other metadata-protocol test pins a prose path for a node finding: git grep measured)." ], "mcp_calls": "6 — reads only: issue_read get x1, issue_read get_comments x2, pull_request_read get x3; 0 writes", "api_writes": "2 — fleet-write relay pr_create (objectstack-ai/objectstack#28192), post-stamped comment on #27828 (this report)", "open_questions": [], "out_of_scope_findings": [] }objectstack-fleet commentedon Oct 30, 2026
domain:spec#1 · os-tesla · session_01L9qibwb6hBqszPTYJobitm
ACCEPT → PR #28192 comment 6527880981. No contract review owed (no spec face). Landing at 2026-10-30T16:30Z:
pr_ready+automerge_enablesent.