Repository navigation
Closed
Labels
area:databugSomething isn't workingSomething isn't workingdomain:specDomain lane — seat card indexed by label:pm:seatDomain lane — seat card indexed by label:pm:seatpm:epicReserved by a dedicated epic PM, parent or sub-issue; other PMs never take it; never with pm:queueReserved by a dedicated epic PM, parent or sub-issue; other PMs never take it; never with pm:queuepriority:p3
Description
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
维护者速读
- 问题: 合成栈(
composeStacks)里,如果某个输入既带packages[]包体,又只在顶层声明了一个连接器实例(没有包体声明同名),那么开机时这个实例只注册进元数据服务,而凭据出借方读的是 ObjectQL 注册表,看不到它。结果数据源external.connector借用它时,开机借不到凭据;要等一次开发态重载后才能借到。但构建期的合成检查认为它可借、放行了,构建和运行结论不一致。 - 影响: 只有手工构造的嵌套或混合输入(多包项目的
preserve合成)会遇到,常规单栈和last扁平合成不受影响。属于边缘形状,p3。 - 需要您做的: 无。修法有两个方向(运行时把残留顶层连接器注册进出借方能看到的地方,或者合成检查拒收这种借用),先实测再定;会改变作者能写什么的,回报 epic PM 再定。
Measured by reading (record 6519281283 ③ item 3, at origin/main 3f02da1)
MetadataPlugin.registerUnclaimedTopLevel(metadata/plugin.ts :1475-1497) registers a residual top-level item through the door's sink. On the artifact door that ismemLoader.save+this.manager.register(:1385-1391). On the config door it ismetadata.registerInMemory(runtime/app-plugin.ts :1127-1148). Both go into the metadata service's registry.- The ObjectQL
manifestservice registers the bodies viaql.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 isprotocol.getMetaItemsForExecution({ type: 'connector' }), which isengine.registry.listItemsplus thesys_metadataoverlay (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 slotpackage:<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.
Metadata
Metadata
Assignees
Labels
area:databugSomething isn't workingSomething isn't workingdomain:specDomain lane — seat card indexed by label:pm:seatDomain lane — seat card indexed by label:pm:seatpm:epicReserved by a dedicated epic PM, parent or sub-issue; other PMs never take it; never with pm:queueReserved by a dedicated epic PM, parent or sub-issue; other PMs never take it; never with pm:queuepriority:p3
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.