Skip to content

feat(showcase): live provider:'mcp' declarative connector demo + CI-pinned dogfood proof (#3056) - #3062

Merged
os-zhuang merged 6 commits into
mainfrom
claude/adr-0097-default-preset
Jul 16, 2026
Merged

feat(showcase): live provider:'mcp' declarative connector demo + CI-pinned dogfood proof (#3056)#3062
os-zhuang merged 6 commits into
mainfrom
claude/adr-0097-default-preset

Conversation

@os-zhuang

@os-zhuangos-zhuang commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

实现 #3056showcase 演示部分:落地 ADR-0097 最初设想的 provider: 'mcp' 验收演示(#3017 延后项),并用 dogfood 测试把它钉进 CI。前置安全闸 #3055(默认拒绝声明式 stdio)已随 #3059 合入,本 PR 是其第一个 dogfood 用户。

范围说明:#3056 的另一半——create-objectstack 模板默认内置三个通用执行器——首版曾包含在本 PR,但 scaffold-e2e 作业从 npm registry 安装脚手架应用,而 ConnectorOpenApiPlugin#3055declarativeStdio 只存在于未发布的 15.1.0(排队于 Changesets release PR)。模板不能引用未发布 API(真实 npm create objectstack 用户会同样炸),故该部分已从本 PR 移除,待 15.1.0 发布后作为小跟进落地(届时模板现有 ^15.0.0 pin 自然解析到 15.1.0)。#3056 保持打开跟踪。

变更

showcase:live provider: 'mcp' 演示(CI 确定性)

  • scripts/mcp-fixture.mjs —— 仓内极小 stdio MCP 服务器,一个确定性工具 echo_upper。选 stdio fixture 而非 http 自连:spawn 发生在 materialization 时刻,无网络、无端口、无启动时序耦合,Dogfood 门不会时序抖动。
  • DevToolsMcpConnector(provider: 'mcp',transport node ./scripts/mcp-fixture.mjs)+ ShowcaseMcpConnectorEchoFlow(connector_action → echo_upper,输出变量携带 structuredContent)。
  • objectstack.config.ts 接线 new ConnectorMcpPlugin({ declarativeStdio: ['node'] }) —— dogfood feat(connector-mcp): policy-gate declarative stdio transports — default-deny + host allowlist (ADR-0097 security follow-up) #3055 的 opt-in,注释如实说明粗粒度信任边界;coverage 注记同步(三个通用执行器的声明式实例现已全部演示)。

dogfood:把演示钉进 CI

showcase-declarative-mcp.dogfood.test.ts 启动真实 showcase(chdir 到应用根,与 os dev 的运行方式一致;vitest 每文件独立进程,chdir 隔离),经 extraPlugins 注入三个执行器(bootStack 不装配 stack 的 plugins:),断言:

  1. GET /automation/connectors 列出 showcase_mcp_tools:origin: 'declarative'state: 'ready'、含 echo_upper(即 fixture 成功 spawn + tools/list 映射);rest/openapi 姊妹实例同样 ready;catalog descriptor 不在注册表;
  2. 触发 flow → run 成功且输出含 OBJECTSTACK(fixture 的 tools/call 结果完成全链路往返)。

文档

content/docs/automation/flows.mdx 节点表后新增一段:connector_action 的连接器从哪来、三个通用执行器与声明式 provider 条目的关系(showcase 已全部接线)、stdio opt-in 的安全语义。

验证

  • dogfood 新证明 2/2 ✓;turbo test(dogfood + showcase + create-objectstack)63 任务全绿 ✓
  • showcase validate(23 flows / 8 plugins)+ typecheck + 55 测试 ✓;eslint ✓;lockfile 已更新(showcase/dogfood 新依赖)

Refs #3056(showcase 演示部分;模板预设部分待 15.1.0 发布)、#3055 / #3059#3017 / #3049、ADR-0097 §6。

🤖 Generated with Claude Code

https://claude.ai/code/session_01Pbmw3pMqNJfPbkvwh9Fkjs

claude added 5 commits July 16, 2026 11:31
…e upstream (#3017)
ADR-0097 made every declarative-connector materialization failure fatal at
boot — right for configuration faults, wrong for operational ones: a
provider: 'mcp' instance must contact its MCP server (tools/list) to
materialize, so a transient network blip aborted the whole app boot.
- spec: ConnectorUpstreamUnavailableError (code CONNECTOR_UPSTREAM_UNAVAILABLE,
structural guard isConnectorUpstreamUnavailable) lets a provider factory mark
a failure as 'upstream temporarily unreachable — degrade and retry' instead
of fatal. New integration/connector-provider-errors.ts; api-surface +3.
- service-automation: the reconcile degrades such instances in BOTH modes.
With no live connector under the name it registers an action-less husk —
state: 'degraded' + degradedReason on the GET /connectors descriptor,
status: 'error' on the def — so the instance stays visible instead of
silently missing; connector_action dispatch fails with the reason and a
'retries automatically' pointer. On a changed-config re-materialization the
old connector keeps serving. Degraded instances retry on an exponential
backoff (5s doubling to 5min, reset by config edits) and on every
metadata:reloaded reconcile; recovery swaps the husk atomically. Reconcile
runs (boot / reload / retry timer) are serialized; destroy() cancels the
retry loop.
- connector-mcp: connect / tools/list failures are classified unavailable;
transport-shape validation stays a plain (fatal) throw.
Configuration faults (unknown provider, invalid providerConfig, unresolvable
credentialRef, name conflicts) keep the ADR-0097 fail-loud contract, verified
by the existing tests. ADR-0097 gains an 'Upstream availability' section; the
deferred live-mcp showcase demo and the openapi remote-URL classification are
recorded as scope boundaries.
Tests: 10 new reconcile cases (degrade visibility, pointed dispatch error,
fake-timer recovery, exponential backoff, reload retry, removal while
degraded, changed-config keeps old serving, revert cancels retry, shutdown
cancels retry, plain-throw still fatal); 3 new mcp-provider classification
cases; 3 new spec error-contract cases.
Refs #3017 (mechanism; showcase demo deferred — see ADR scope boundaries)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pbmw3pMqNJfPbkvwh9Fkjs
…lt-deny + host allowlist (#3055)
A declarative provider: 'mcp' entry with a stdio transport spawns a local
child process from METADATA — which a runtime Studio publish can introduce
(the reload reconcile materializes new instances; soft mode skips failures,
not successes). Anyone who can publish metadata could otherwise execute
arbitrary commands on the server. Declarative stdio is now denied by default
and opt-in per host:
new ConnectorMcpPlugin({ declarativeStdio: ['my-mcp-server'] }) // allowlist
new ConnectorMcpPlugin({ declarativeStdio: true }) // full trust
- createMcpProviderFactory gains a declarativeStdio policy (undefined/false =
deny, string[] = strict-equality command allowlist, true = allow any);
ConnectorMcpPlugin plumbs it through. New export McpDeclarativeStdioPolicy.
- A violation is a CONFIGURATION fault: plain throw with an actionable opt-in
message (fatal at boot, skipped+logged on reload) — never classified
CONNECTOR_UPSTREAM_UNAVAILABLE, so a security rejection cannot be retried
into existence (#3049 seam).
- http transports are unaffected (same trust class as the http node), and so
are hand-wired connectors (plugin instance options / createMcpConnector) —
their command lives in host code, a different trust anchor than metadata.
- ADR-0097 gains a 'Declarative stdio policy' section (cross-ref ADR-0024 §4,
honest about the allowlist being a coarse boundary); this gate is the
precondition for shipping connector-mcp in default presets (#3056).
Tests: default-deny (plain, non-retryable, rejected before any connection
attempt), allowlist hit/miss, true passthrough, http unaffected, plugin
option plumb-through, hand-wired stdio path explicitly un-gated (e2e).
Refs #3055. Stacked on #3049 (claude/adr-0097-mcp-nonfatal-boot).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pbmw3pMqNJfPbkvwh9Fkjs
#3049's squash (4f8c2d1) is content-identical to this branch's base commit,
so this merge only rebases the PR surface — the three-dot diff vs main now
shows the #3055 gate alone.
# Conflicts:
#	docs/adr/0097-declarative-connector-instances.md
#	packages/connectors/connector-mcp/src/mcp-provider.test.ts
#	packages/connectors/connector-mcp/src/mcp-provider.ts
…ve provider:'mcp' showcase demo (#3056)
Closes the last authoring gap in ADR-0097's 'expressible AND executable as
pure metadata' promise, and lands the provider:'mcp' acceptance demo the ADR
originally envisioned (deferred at #3017).
create-objectstack (blank template):
- plugins: gains new ConnectorRestPlugin() / ConnectorOpenApiPlugin() /
ConnectorMcpPlugin() (zero-arg = provider factory only), so a scaffolded
app materializes declarative provider-bound connectors with no
plugin-wiring step. README documents the default providers, credentialRef
rule, and the #3055 declarativeStdio opt-in. Deps added at ^15.0.0.
examples/app-showcase (live mcp demo):
- scripts/mcp-fixture.mjs — tiny in-repo stdio MCP server (one deterministic
echo_upper tool): no network, no ports, no boot-ordering coupling, so the
demo is CI-deterministic.
- DevToolsMcpConnector (provider: 'mcp', stdio transport 'node
./scripts/mcp-fixture.mjs') + ShowcaseMcpConnectorEchoFlow dispatching
echo_upper end-to-end; coverage notes updated.
- objectstack.config.ts wires new ConnectorMcpPlugin({ declarativeStdio:
['node'] }) — dogfooding the #3055 default-deny opt-in, with the
coarse-boundary caveat spelled out.
dogfood:
- showcase-declarative-mcp.dogfood.test.ts boots the REAL showcase (chdir to
the app root, exactly how os dev runs), injects the three executors, and
pins: GET /connectors lists showcase_mcp_tools origin=declarative
state=ready with echo_upper (rest + openapi siblings ready too; catalog
descriptor absent), and the flow trigger round-trips OBJECTSTACK from the
fixture's tools/call into the run output.
docs: flows.mdx explains where connector_action connectors come from, the
default preset, and the stdio opt-in.
Verified: dogfood proof 2/2; turbo test dogfood+showcase+create-objectstack
63 tasks green; showcase validate (23 flows / 8 plugins) + typecheck clean;
eslint clean; lockfile updated for the new deps.
Refs #3056 (template + showcase + demo + docs; issue also tracks nothing
further after this — see closing comment)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pbmw3pMqNJfPbkvwh9Fkjs
@vercel

vercelBot commented Jul 16, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
specReadyReadyPreview, CommentJul 16, 2026 2:37pm

Request Review

@github-actionsgithub-actionsBot added size/m documentation Improvements or additions to documentation dependencies Pull requests that update a dependency file tests tooling labels Jul 16, 2026
@github-actions

github-actionsBot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/dogfood.

2 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/permissions/authorization.mdx(via packages/dogfood)
  • content/docs/permissions/delegated-administration.mdx(via packages/dogfood)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

…he 15.1.0 publish
The scaffold-e2e job installs the generated app from the npm REGISTRY, and
ConnectorOpenApiPlugin (and the #3055 declarativeStdio option) only exist in
the unpublished 15.1.0 (queued in the Changesets release PR). A template must
not reference unpublished APIs — the same failure would hit real
'npm create objectstack' users. Reverted the template files + changeset;
once 15.1.0 publishes, the template's ^15.0.0 pins resolve to it and the
preset piece lands as a small follow-up. flows.mdx reworded to describe the
mechanism without the scaffold claim.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pbmw3pMqNJfPbkvwh9Fkjs
@os-zhuangos-zhuang changed the title feat: default preset ships the three generic connector executors + live provider:'mcp' showcase demo (#3056)feat(showcase): live provider:'mcp' declarative connector demo + CI-pinned dogfood proof (#3056)Jul 16, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review July 16, 2026 14:09
@os-zhuang
os-zhuang merged commit f8663b8 into mainJul 16, 2026
17 of 18 checks passed
@os-zhuang
os-zhuang deleted the claude/adr-0097-default-preset branch July 16, 2026 14:09
os-zhuang pushed a commit that referenced this pull request Jul 16, 2026
…dogfood test + regen lockfile after merge
showcase-declarative-mcp.dogfood.test.ts landed on main (#3062) against
the old packages/dogfood location; after the packages/qa migration its
'../../../examples/app-showcase' URL resolved inside packages/. One more
level, same as the other conformance tests. Lockfile regenerated after
taking main's side in the merge.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
os-zhuang added a commit that referenced this pull request Jul 16, 2026
…结论 (#2462) (#3037)
* feat(transport): prove the IHttpServer port is Hono-free — second adapter on raw node:http (ADR-0076 D11/OQ#10, #2462)
Multi-adapter was designed but unproven: only the Hono adapter existed, and
ADR-0076 D11 flagged 'the normalized context shows Hono-isms' as a caveat
blocking the transport decomposition. This adds the validation:
- New @objectstack/plugin-node-server: a thin IHttpServer implementation on
raw node:http with ZERO dependencies beyond @objectstack/core — :param +
trailing-* routing (registration-order first-match, same as the primary
adapter), eager JSON/urlencoded body parse with lazy rawBody() for binary,
SSE via native res.write/end, 404/405-with-Allow semantics, EADDRINUSE
retry, graceful drain on close. Deliberately no getRawApp()/mount().
- Cross-adapter conformance suite: boots the dispatcher bridge AND the REST
route generator (with ObjectQL + memory driver) on BOTH adapters over real
sockets — /data CRUD roundtrip, /meta reads, /ready, /health, discovery,
:param routing, 404/405 parity, plus a probe-for-probe response-shape
parity matrix between the two adapters. 40 assertions, all green.
Findings recorded in ADR-0076 (OQ#9/OQ#10/OQ#11 resolution notes):
- The port has NO hard Hono-isms. The Host-header backfill in the Hono
adapter is a Fetch-API artifact local to that adapter, not a port leak.
- All remaining Hono coupling is confined to the feature-detected
getRawApp() escape hatch (metadata HMR, cloud-connection routes,
static/SPA + CORS + Server-Timing) which degrades gracefully.
- Follow-up for the D11 window: codify res.write/res.end (SSE) and
getPort() — extensions consumers already rely on — plus 404/405
semantics into the IHttpServer contract.
- OQ#9 audit verdict (delineate, don't merge; only discovery + packages
are genuinely double-mounted) recorded in the ADR open-questions list.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
* fix(plugin-node-server): harden query/params against prototype pollution (CodeQL)
CodeQL flagged remote property injection: query-param keys come straight
from the request URL, so building the map on a plain object literal let
'?__proto__=…' write through the prototype chain. Use null-prototype
objects for query and params and drop the dangerous keys
(__proto__/constructor/prototype) outright; regression test pins that
'?__proto__=polluted' is dropped and Object.prototype stays clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
* fix(plugin-node-server): eliminate the dynamic property-write sink CodeQL flags
The blacklist guard added in the previous commit was not recognized as a
sanitizer by CodeQL's js/remote-property-injection rule — the sink is the
computed write itself (obj[userKey] = …). Build query and params via
Object.fromEntries (own data properties only, no prototype-chain walk) so
the sink no longer exists; the __proto__/constructor/prototype drop stays
as defense in depth. Regression test unchanged and green (41/41).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
* refactor(qa): reposition the port-conformance adapter as a private QA gate — packages/qa/http-conformance
Maintainer review: the node:http adapter is a validation instrument, not a
product server, so it must not ship as a publishable plugin- package.
Reposition it accordingly:
- Move packages/plugins/plugin-node-server → packages/qa/http-conformance;
rename @objectstack/plugin-node-server → @objectstack/http-conformance,
private: true, test-only (no build/publish), matching the existing
verification-gate packages (dogfood, downstream-contract).
- packages/qa/ becomes the unified home for non-published verification
gates (new pnpm-workspace glob); migrating dogfood/downstream-contract
there is proposed as a follow-up.
- Drop the changeset + fixed-group entry (private packages are not
versioned); update the ADR-0076 OQ#10 note to the new name.
Behavior unchanged: same adapter, same 41-assertion cross-adapter
conformance suite, all green.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
* refactor(qa): migrate dogfood + downstream-contract into packages/qa/ (unified verification-gate home)
Completes the packages/qa/ consolidation started with http-conformance:
all three non-published verification gates (dogfood regression gate,
downstream-contract compatibility gate, http-conformance port gate) now
live under one directory.
Mechanical path migration — no behavior change:
- git mv packages/{dogfood,downstream-contract} → packages/qa/
- rewrite every 'packages/dogfood' / 'packages/downstream-contract'
breadcrumb: spec liveness proof registry + JSON ledgers,
spec-liveness-check.yml path trigger, eslint ignore, docs/ADRs,
source comments
- bump the repo-root traversal one level in the four dogfood conformance
tests that resolve REPO_ROOT from __dirname
Verified from the new locations: dogfood 273 passed / 3 skipped,
downstream-contract typecheck + 14 tests, spec check:liveness resolves
all bound proofs, http-conformance 41/41.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
* chore: retrigger CI — Actions did not fire on dc6507c
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
* docs(changeset): fix dogfood path breadcrumb after packages/qa migration
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
* fix(ci): build the examples' dependency closure explicitly in the typecheck job + correct stale ADR-0076 D12 status
Two follow-ups after merging latest main:
- lint.yml: the example-app typecheck step built only ./packages/* (direct
children). The connector packages the showcase imports were built purely
by accident — through dogfood's dependency chain — which broke when
dogfood moved to packages/qa/. Request the examples' dependency closure
explicitly (--filter='./examples/*^...') so the step no longer depends
on which package happens to live at the top level.
- ADR-0076: the round-2 status verification merged from main (#3061) was
read against a pre-#3028 snapshot — svcAvailable no longer hardcodes
'available'; the D12 framework side shipped in #3028. Correct the status
line and note OQ#9/OQ#10 resolution (#3037).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
* fix(ci): cap turbo test concurrency at the runner's core count (OOM mitigation)
Test Core started failing deterministically on the hosted runner —
plugin-audit#test dies with ZERO vitest output (kernel OOM-kill
signature) while passing locally on Node 20 and 22 — first on main
@4f8c2d1, then twice on this PR (initial run + job re-run). Onset
correlates with the task graph growing past ~100 tasks (connector
packages + qa gates): turbo's default concurrency (10) schedules that
many vitest workers + tsup DTS builds onto a 4-vCPU runner and peak
memory tips over.
Cap test-step concurrency at 4 (PR affected-tests + push full-run).
CPU-bound workload, so wall-clock cost is minimal; peak memory becomes
bounded.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
* fix(qa): bump repo-relative path in the newly-merged declarative-mcp dogfood test + regen lockfile after merge
showcase-declarative-mcp.dogfood.test.ts landed on main (#3062) against
the old packages/dogfood location; after the packages/qa migration its
'../../../examples/app-showcase' URL resolved inside packages/. One more
level, same as the other conformance tests. Lockfile regenerated after
taking main's side in the merge.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
---------
Co-authored-by: Claude <noreply@anthropic.com>
os-zhuang added a commit that referenced this pull request Jul 16, 2026
* feat(transport): prove the IHttpServer port is Hono-free — second adapter on raw node:http (ADR-0076 D11/OQ#10, #2462)
Multi-adapter was designed but unproven: only the Hono adapter existed, and
ADR-0076 D11 flagged 'the normalized context shows Hono-isms' as a caveat
blocking the transport decomposition. This adds the validation:
- New @objectstack/plugin-node-server: a thin IHttpServer implementation on
raw node:http with ZERO dependencies beyond @objectstack/core — :param +
trailing-* routing (registration-order first-match, same as the primary
adapter), eager JSON/urlencoded body parse with lazy rawBody() for binary,
SSE via native res.write/end, 404/405-with-Allow semantics, EADDRINUSE
retry, graceful drain on close. Deliberately no getRawApp()/mount().
- Cross-adapter conformance suite: boots the dispatcher bridge AND the REST
route generator (with ObjectQL + memory driver) on BOTH adapters over real
sockets — /data CRUD roundtrip, /meta reads, /ready, /health, discovery,
:param routing, 404/405 parity, plus a probe-for-probe response-shape
parity matrix between the two adapters. 40 assertions, all green.
Findings recorded in ADR-0076 (OQ#9/OQ#10/OQ#11 resolution notes):
- The port has NO hard Hono-isms. The Host-header backfill in the Hono
adapter is a Fetch-API artifact local to that adapter, not a port leak.
- All remaining Hono coupling is confined to the feature-detected
getRawApp() escape hatch (metadata HMR, cloud-connection routes,
static/SPA + CORS + Server-Timing) which degrades gracefully.
- Follow-up for the D11 window: codify res.write/res.end (SSE) and
getPort() — extensions consumers already rely on — plus 404/405
semantics into the IHttpServer contract.
- OQ#9 audit verdict (delineate, don't merge; only discovery + packages
are genuinely double-mounted) recorded in the ADR open-questions list.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
* fix(plugin-node-server): harden query/params against prototype pollution (CodeQL)
CodeQL flagged remote property injection: query-param keys come straight
from the request URL, so building the map on a plain object literal let
'?__proto__=…' write through the prototype chain. Use null-prototype
objects for query and params and drop the dangerous keys
(__proto__/constructor/prototype) outright; regression test pins that
'?__proto__=polluted' is dropped and Object.prototype stays clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
* fix(plugin-node-server): eliminate the dynamic property-write sink CodeQL flags
The blacklist guard added in the previous commit was not recognized as a
sanitizer by CodeQL's js/remote-property-injection rule — the sink is the
computed write itself (obj[userKey] = …). Build query and params via
Object.fromEntries (own data properties only, no prototype-chain walk) so
the sink no longer exists; the __proto__/constructor/prototype drop stays
as defense in depth. Regression test unchanged and green (41/41).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
* refactor(qa): reposition the port-conformance adapter as a private QA gate — packages/qa/http-conformance
Maintainer review: the node:http adapter is a validation instrument, not a
product server, so it must not ship as a publishable plugin- package.
Reposition it accordingly:
- Move packages/plugins/plugin-node-server → packages/qa/http-conformance;
rename @objectstack/plugin-node-server → @objectstack/http-conformance,
private: true, test-only (no build/publish), matching the existing
verification-gate packages (dogfood, downstream-contract).
- packages/qa/ becomes the unified home for non-published verification
gates (new pnpm-workspace glob); migrating dogfood/downstream-contract
there is proposed as a follow-up.
- Drop the changeset + fixed-group entry (private packages are not
versioned); update the ADR-0076 OQ#10 note to the new name.
Behavior unchanged: same adapter, same 41-assertion cross-adapter
conformance suite, all green.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
* refactor(qa): migrate dogfood + downstream-contract into packages/qa/ (unified verification-gate home)
Completes the packages/qa/ consolidation started with http-conformance:
all three non-published verification gates (dogfood regression gate,
downstream-contract compatibility gate, http-conformance port gate) now
live under one directory.
Mechanical path migration — no behavior change:
- git mv packages/{dogfood,downstream-contract} → packages/qa/
- rewrite every 'packages/dogfood' / 'packages/downstream-contract'
breadcrumb: spec liveness proof registry + JSON ledgers,
spec-liveness-check.yml path trigger, eslint ignore, docs/ADRs,
source comments
- bump the repo-root traversal one level in the four dogfood conformance
tests that resolve REPO_ROOT from __dirname
Verified from the new locations: dogfood 273 passed / 3 skipped,
downstream-contract typecheck + 14 tests, spec check:liveness resolves
all bound proofs, http-conformance 41/41.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
* chore: retrigger CI — Actions did not fire on dc6507c
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
* docs(changeset): fix dogfood path breadcrumb after packages/qa migration
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
* fix(ci): build the examples' dependency closure explicitly in the typecheck job + correct stale ADR-0076 D12 status
Two follow-ups after merging latest main:
- lint.yml: the example-app typecheck step built only ./packages/* (direct
children). The connector packages the showcase imports were built purely
by accident — through dogfood's dependency chain — which broke when
dogfood moved to packages/qa/. Request the examples' dependency closure
explicitly (--filter='./examples/*^...') so the step no longer depends
on which package happens to live at the top level.
- ADR-0076: the round-2 status verification merged from main (#3061) was
read against a pre-#3028 snapshot — svcAvailable no longer hardcodes
'available'; the D12 framework side shipped in #3028. Correct the status
line and note OQ#9/OQ#10 resolution (#3037).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
* fix(ci): cap turbo test concurrency at the runner's core count (OOM mitigation)
Test Core started failing deterministically on the hosted runner —
plugin-audit#test dies with ZERO vitest output (kernel OOM-kill
signature) while passing locally on Node 20 and 22 — first on main
@4f8c2d1, then twice on this PR (initial run + job re-run). Onset
correlates with the task graph growing past ~100 tasks (connector
packages + qa gates): turbo's default concurrency (10) schedules that
many vitest workers + tsup DTS builds onto a 4-vCPU runner and peak
memory tips over.
Cap test-step concurrency at 4 (PR affected-tests + push full-run).
CPU-bound workload, so wall-clock cost is minimal; peak memory becomes
bounded.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
* fix(qa): bump repo-relative path in the newly-merged declarative-mcp dogfood test + regen lockfile after merge
showcase-declarative-mcp.dogfood.test.ts landed on main (#3062) against
the old packages/dogfood location; after the packages/qa migration its
'../../../examples/app-showcase' URL resolved inside packages/. One more
level, same as the other conformance tests. Lockfile regenerated after
taking main's side in the merge.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
* ci: TEMPORARY #3071 diagnostics — isolated verbose plugin-audit runs + dmesg OOM probe
plugin-audit#test dies on the hosted runner with zero captured output
(3x deterministic since main@4f8c2d1) while passing locally under Node
20/22 with the exact CI command. Bracket the turbo test step with an
isolated, verbose, ungrouped vitest run (before: fresh machine; after:
post-graph machine + kernel OOM traces) so the real failure output cannot
be lost to the GH log pipeline. SIGQUIT-on-timeout dumps Node thread
stacks if it hangs. To be REMOVED once #3071's root cause is fixed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
---------
Co-authored-by: Claude <noreply@anthropic.com>
baozhoutao pushed a commit that referenced this pull request Aug 7, 2026
Closes the two coverage holes the seed import left: nothing covered the AI
metadata kinds (agent/tool/skill, MCP surfaces) or the integration/system
services (declarative connectors, webhooks, jobs, email templates).
- areas/ai.json — agent/tool/skill metadata round-trip (variants matrix),
MCP HTTP transport both-sides (enabled 501/off + /mcp/skill public),
stdio fail-closed + RLS/FLS parity (from #3358 §9), run_action
ai.exposed gate + audit (15.1 §A9), validate_expression. Showcase ships
no AI seeds (ADR-0063) — fixture requirements declared explicitly.
- areas/integration-system.json — declarative connector lifecycle from the
15.1 §B rows (#2994/#3062 boot materialization, #3049 degraded husk +
atomic recovery, #3059 stdio default-deny allowlist, #3024 spec-path
escape rejection, #2985 descriptor-only boot audit, objectui#2563
designer picker), webhook live-fire + retired-trigger build gate, job
scheduled run, email-template variable rendering.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YD9f6FYyMraUWYeJf53V43
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependenciesPull requests that update a dependency filedocumentationImprovements or additions to documentationsize/mteststooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@os-zhuang@claude