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
A connector a mixed composed input declares only at its top level beside package bodies is invisible to the lender at boot, yet the composed check accepts a borrow of it #28032
epic:#27261#1 · marchtian · session_017ihL2c5z3q4h8inrn5kwqV
Filing gate: ③ escalation in the contract review of PR #28026 (record 6519281283 ③ item 3, VERDICT PASS), confirming the dev's out-of-scope note in os-dev-report 6518764127. It is outside that PR's surface, and that card forbids it to change an accept set.
Ruling-ref: D7 ruling 6486136301 (connector-credential borrowing)
Dedupe (open AND closed): "registerUnclaimedTopLevel connector lender readDeclaredConnectorItems residual" → none this work.
Reader: the epic PM (#27261) dispatches it in the epic subtree.
type: Bug
Measured by reading (record 6519281283 ③ item 3, at origin/main3f02da1)
MetadataPlugin.registerUnclaimedTopLevel (metadata/plugin.ts :1475-1497) registers a residual top-level item through the door's sink. On the artifact door that is memLoader.save + this.manager.register (:1385-1391). On the config door it is metadata.registerInMemory (runtime/app-plugin.ts :1127-1148). Both go into the metadata service's registry.
The ObjectQL manifest service registers the bodies via ql.registerApp, and of the residual it registers OBJECTS only (unclaimedTopLevelObjects, objectql/plugin.ts :143-153, :773-848).
The lender reads readDeclaredConnectorItems (service-automation/plugin.ts :1104-1109, :1938-1972), that is protocol.getMetaItemsForExecution({ type: 'connector' }), which is engine.registry.listItems plus the sys_metadata overlay (metadata-protocol/protocol.ts :9469-9500). It never reads the metadata service's list.
A dev reload makes the entry visible (captureReloadedConnectors :1890-1905).
Accepted at build today: composeStacks([mixed(instance), looseBorrower], { manifest: 'preserve' }). The only declaration is the mixed input's top-level instance, in slot package:<mixed id>, so it is kept, can lend, and is accepted.
Task
Measure first. Boot an artifact of the accepted shape above, then borrow through the datasource. Confirm it refuses at boot and lends after a reload. If it lends at boot, close this card with the measurement.
If it reproduces, choose the fix from the measurement and say why in the PR. Option (a): the residual top-level connector (unclaimed by any body) registers where the lender reads, for example the ObjectQL registry under the composed manifest.id, the way residual objects already do. Option (b): the composed check refuses a borrow whose only lending declaration is a top-level entry beside package bodies. (b) narrows what an author can declare. Stop and report to the epic PM before taking it.
A test pins the boot-time borrow on that shape, both directions.
Clause-②: decided from the diff · Metadata-protocol: none. A spec edit (option b) owes a contract review at CONTRACT_REVIEW_TIER.
epic:#27261#1 · marchtian · session_017ihL2c5z3q4h8inrn5kwqV
Claim: PM loop round 17 2026-10-30T09:26Z
Session: session_017ihL2c5z3q4h8inrn5kwqV (epic PM); implementing card thread session_017ihL2dhraZ7BwSanQPGEAb (it carried #27917 / PR #28011)
Account: marchtian
Branch: claude/project-thread-r6cu87 (the card thread's platform-assigned branch, restarted from origin/main after #28011 merged — measured platform exception to claude/issue-<n>-<slug>)
Worktree: objectstack-issue-28032
Domain: domain:spec
Seat: epic:#27261#1 (epic PM; no domain:* seat). Filing gate ③ (record 6519281283 item 3), D7 ruling 6486136301
File surface: measurement first (a test on a booted artifact of the card's shape). Then, for option (a) only: packages/metadata/src/plugin.ts, packages/objectql/src/plugin.ts, packages/runtime/src/app-plugin.ts (registering a residual top-level connector where the lender reads), their tests, and .changeset/**. Option (b) (packages/spec/src/stack.zod.ts, which narrows) is NOT claimed: stop and report to the epic PM. #28026 is in flight on that file. Stop on any other breach.
Container & model: S, mode:thread, model: default tier (Fable unavailable; 田騏's order of 2026-10-29 19:39Z), effort: high
Clause-②: yes — provisional; restate from the diff (no if the measurement closes the card or option (a) changes no published surface)
Metadata-protocol: none
Responsibility: escalation ③ item 3 of record 6519281283 on #28006 (PR #28026)
Thread-read: none
Premise: unmeasured — by reading at origin/main3f02da1, a residual top-level connector beside package bodies registers only into the metadata service, while the lender reads engine.registry.listItems('connector') plus the overlay. Measure before any fix, and close the card if it lends at boot.
Serial constraints: #28026 (in flight) edits packages/spec/src/stack.zod.ts; this claim does not touch it.
{
"issue": 28032,
"status": "done",
"branch": "claude/project-thread-r6cu87",
"pr": "https://github.com/objectstack-ai/objectstack/pull/28046",
"head": "a5d4ed3f",
"session": "session_017ihL2dhraZ7BwSanQPGEAb",
"premise_still_valid": true,
"measurement": "Reproduces. A real kernel (ObjectKernel, ObjectQLPlugin over SQLite, AutomationServicePlugin) booted composeStacks([mixed(instance), looseBorrower], { manifest: 'preserve' }) through the manifest service, against the unfixed objectql build at origin/main 13d85bb3: registry.listItems('connector') was [] and source.borrow('sap_s4') was refused 422 'is not declared in this stack's connectors'. The composed check accepted the shape; the body-declared CONTROL lent. Reload half read off captureReloadedConnectors, not measured.",
"decision": "Option (a), as claimed. objectql plugin.ts: unclaimedTopLevelConnectors reads unclaimedTopLevel for connector items; the manifest service registers them after every body and the residual objects, under the residual rule's id, via registry.registerItem('connector', ...), version stamped on a shallow copy. The empty-packages warning no longer fires when the only residual is a connector. No spec change; option (b) not taken.",
"summary": "Files: packages/objectql/src/plugin.ts; packages/objectql/src/manifest-service-residual-objects.test.ts (3 engine pins); packages/services/service-automation/src/connector-credential-residual-connector.test.ts (new, 4 kernel pins: build accepts; residual instance lends at boot owned by the stack id; residual descriptor refused as 'declares no provider', not undeclared; CONTROL body instance lends); .changeset objectql patch. Clause-2 no (no published surface; the boot now agrees with what build already accepts), Metadata-protocol none.",
"tests": "Kernel borrow test red before the fix (2/4, both residual cases), green after (4/4). Engine pins: reverse check from the committed fix fails exactly the 2 residual-connector pins, CONTROL green. objectql full suite 493 files / 9595 passed; service-automation 224 files / 2845 passed (1 expected fail); both typechecks exit 0. After merging origin/main (cc5586da touched the lender plugin.ts) the borrow and lender tests re-run green (21 passed).",
"gates": "dispatch-gates --commands derived 63 families; all run with exit codes recorded after building ./packages/**. First pass 1 red: check:slot-lookup (getService any in the new test), fixed in 3ab79536. --ran: 63 derived, 63 run, 0 NOT-MEASURED (derived zero). Derived list unchanged after the main merge at a5d4ed3f.",
"mcp_calls": "github issue_read x2 (#28032 get, get_comments); subscribe_pr_activity x1; no MCP write tool",
"api_writes": "2: relay pr_create (run 41041880235, PR #28046, 6788 bytes read back identical, assignee marchtian); relay comment on #28032 (this report).",
"open_questions": [],
"out_of_scope_findings": [
"carrier: epic PM · by reading only: the manifest service still registers only the residual's objects and connectors. The other registry-read collections a residual can carry (flows, permissions, the rest of METADATA_ARRAY_KEYS in objectql engine.ts) reach the metadata service only, so a boot-time reader of the registry misses them the same way. Not measured, not widened here."
]
}
PR #28046 merged through the queue as 5f314700a0 at 2026-10-30T11:18:05Z, from head a5d4ed3f. It has no contract face (Clause-②: no, not governed), so CI plus the seat read in the ACCEPT is the review of record.
Measured first: a real kernel with the card's preserve shape returned an empty registry.listItems('connector'), and the borrow was refused 422 as undeclared. The fix is in the ObjectQL manifest service, which now registers a multi-package stack's residual connectors under the residual id, the same way it registers residual objects, so the lender sees them at boot. The related residual-flows finding is #28048.
Activity
objectstack-fleet commentedon Oct 30, 2026
epic:#27261#1 · marchtian · session_017ihL2c5z3q4h8inrn5kwqV
Claim: PM loop round 17 2026-10-30T09:26Z
Session:
session_017ihL2c5z3q4h8inrn5kwqV(epic PM); implementing card threadsession_017ihL2dhraZ7BwSanQPGEAb(it carried #27917 / PR #28011)Account:
marchtianBranch:
claude/project-thread-r6cu87(the card thread's platform-assigned branch, restarted fromorigin/mainafter #28011 merged — measured platform exception toclaude/issue-<n>-<slug>)Worktree:
objectstack-issue-28032Domain:
domain:specSeat:
epic:#27261#1(epic PM; nodomain:*seat). Filing gate ③ (record 6519281283 item 3), D7 ruling 6486136301File surface: measurement first (a test on a booted artifact of the card's shape). Then, for option (a) only:
packages/metadata/src/plugin.ts,packages/objectql/src/plugin.ts,packages/runtime/src/app-plugin.ts(registering a residual top-level connector where the lender reads), their tests, and.changeset/**. Option (b) (packages/spec/src/stack.zod.ts, which narrows) is NOT claimed: stop and report to the epic PM. #28026 is in flight on that file. Stop on any other breach.Container & model:
S,mode:thread,model: default tier (Fable unavailable; 田騏's order of 2026-10-29 19:39Z),effort: highClause-②: yes — provisional; restate from the diff (
noif the measurement closes the card or option (a) changes no published surface)Metadata-protocol: none
Responsibility: escalation ③ item 3 of record 6519281283 on #28006 (PR #28026)
Thread-read: none
Premise: unmeasured — by reading at
origin/main3f02da1, a residual top-level connector beside package bodies registers only into the metadata service, while the lender readsengine.registry.listItems('connector')plus the overlay. Measure before any fix, and close the card if it lends at boot.Serial constraints: #28026 (in flight) edits
packages/spec/src/stack.zod.ts; this claim does not touch it.objectstack-fleet commentedon Oct 30, 2026
epic:#27261#1 · marchtian · session_017ihL2dhraZ7BwSanQPGEAb
os-dev-report
{ "issue": 28032, "status": "done", "branch": "claude/project-thread-r6cu87", "pr": "https://github.com/objectstack-ai/objectstack/pull/28046", "head": "a5d4ed3f", "session": "session_017ihL2dhraZ7BwSanQPGEAb", "premise_still_valid": true, "measurement": "Reproduces. A real kernel (ObjectKernel, ObjectQLPlugin over SQLite, AutomationServicePlugin) booted composeStacks([mixed(instance), looseBorrower], { manifest: 'preserve' }) through the manifest service, against the unfixed objectql build at origin/main 13d85bb3: registry.listItems('connector') was [] and source.borrow('sap_s4') was refused 422 'is not declared in this stack's connectors'. The composed check accepted the shape; the body-declared CONTROL lent. Reload half read off captureReloadedConnectors, not measured.", "decision": "Option (a), as claimed. objectql plugin.ts: unclaimedTopLevelConnectors reads unclaimedTopLevel for connector items; the manifest service registers them after every body and the residual objects, under the residual rule's id, via registry.registerItem('connector', ...), version stamped on a shallow copy. The empty-packages warning no longer fires when the only residual is a connector. No spec change; option (b) not taken.", "summary": "Files: packages/objectql/src/plugin.ts; packages/objectql/src/manifest-service-residual-objects.test.ts (3 engine pins); packages/services/service-automation/src/connector-credential-residual-connector.test.ts (new, 4 kernel pins: build accepts; residual instance lends at boot owned by the stack id; residual descriptor refused as 'declares no provider', not undeclared; CONTROL body instance lends); .changeset objectql patch. Clause-2 no (no published surface; the boot now agrees with what build already accepts), Metadata-protocol none.", "tests": "Kernel borrow test red before the fix (2/4, both residual cases), green after (4/4). Engine pins: reverse check from the committed fix fails exactly the 2 residual-connector pins, CONTROL green. objectql full suite 493 files / 9595 passed; service-automation 224 files / 2845 passed (1 expected fail); both typechecks exit 0. After merging origin/main (cc5586da touched the lender plugin.ts) the borrow and lender tests re-run green (21 passed).", "gates": "dispatch-gates --commands derived 63 families; all run with exit codes recorded after building ./packages/**. First pass 1 red: check:slot-lookup (getService any in the new test), fixed in 3ab79536. --ran: 63 derived, 63 run, 0 NOT-MEASURED (derived zero). Derived list unchanged after the main merge at a5d4ed3f.", "mcp_calls": "github issue_read x2 (#28032 get, get_comments); subscribe_pr_activity x1; no MCP write tool", "api_writes": "2: relay pr_create (run 41041880235, PR #28046, 6788 bytes read back identical, assignee marchtian); relay comment on #28032 (this report).", "open_questions": [], "out_of_scope_findings": [ "carrier: epic PM · by reading only: the manifest service still registers only the residual's objects and connectors. The other registry-read collections a residual can carry (flows, permissions, the rest of METADATA_ARRAY_KEYS in objectql engine.ts) reach the metadata service only, so a boot-time reader of the registry misses them the same way. Not measured, not widened here." ] }objectstack-fleet commentedon Oct 30, 2026
epic:#27261#1 · marchtian · session_017ihL2c5z3q4h8inrn5kwqV
Landed · 2026-10-30T13:01Z
PR #28046 merged through the queue as
5f314700a0at 2026-10-30T11:18:05Z, from heada5d4ed3f. It has no contract face (Clause-②: no, not governed), so CI plus the seat read in the ACCEPT is the review of record.Measured first: a real kernel with the card's
preserveshape returned an emptyregistry.listItems('connector'), and the borrow was refused 422 as undeclared. The fix is in the ObjectQLmanifestservice, which now registers a multi-package stack's residual connectors under the residual id, the same way it registers residual objects, so the lender sees them at boot. The related residual-flows finding is #28048.