Repository navigation
Conversation
4d3174d to
dc53404
Compare
Why: Train C1 needs package-owned business implementations and connector adapters before Core can perform a no-double-run cutover. Freeze the eleven-item inventory, add the public SDK session surface, migrate three business plugins and five provider adapters, and keep unresolved Host binding/checkpoint activation fail-closed outside the catalog. Verification: connector package typecheck and 30/30 tests pass; SDK 313/313 passed before checkpoint; fresh-consumer covered the three cataloged business packages; packed runtime entrypoint guard 3/3 passes; inventory remains intentionally RED at the first uncataloged connector. [砚砚/gpt-5.6-sol🐾]
Why: the aggregate migration needs package-owned Feishu, Weixin, and GitHub operation surfaces without freezing unapproved Host binding or checkpoint APIs. Explicit configuration and Host ports preserve authority while catalog and publication remain fail-closed until Core composition is approved. Also closes the existing WeChat visible-reader release workflow omission and updates the publication conformance count to the nine currently cataloged public packages. Verification: pnpm -r --workspace-concurrency=1 typecheck; pnpm -r --workspace-concurrency=1 test; connector manifests validated through the built contract; exact-toolchain dry-run packs include README, manifest, shrinkwrap, icon, and dist. [砚砚/gpt-5.6-sol🐾]
Why: the C1 checkpoint exposed two semantic gaps: publication coverage was pinned to duplicated literals instead of catalog truth, and the GitHub Operations package shell was described like a runnable adapter despite depending on unapproved Host D/E authority. Derive the release invariant from catalog provenance, make the blocked port status machine-readable, and record the already-wired packed-entrypoint gate without advancing catalog or publication. [砚砚/gpt-5.6-sol🐾]
Why: protected Linux CI and two exact local Node 24.18.0/npm 11.16.0 packs agree on the final video-generation bytes, while the catalog still recorded an earlier pre-final-build candidate. Refresh only the immutable SHA-1/SHA-512 coordinates so the existing fail-closed catalog check proves the actual reviewed source. [砚砚/gpt-5.6-sol🐾]
Why: Train C1 was incorrectly reframed as waiting on a new D/E public contract even though the contract and SDK surfaces were already closed. Restore the agreed split: Plugins completes package code while Core maps existing Host authority, cuts over, and deletes legacy implementations. [砚砚/gpt-5.6-sol🐾]
Why: Core can delete provider-specific connector wrappers only after the packages own explicit provider lifecycle and ingress normalization while Host binding, wake, retry, and settlement authority stay outside package code. [砚砚/gpt-5.6-sol🐾]
Why: Host disable can arrive while a provider start is still connecting. Waiting for that transition before provider shutdown prevents a late live stream from surviving drain, while a shared async idempotent lifecycle lets Core map both connectors without provider branches. [砚砚/gpt-5.6-sol🐾]
Why: standalone connector manifests declare provider ingress methods, but the closed stdio registry cannot execute them and the handshake exposes no Host-issued binding handle. Preserve the exact fail-closed evidence before choosing an authority-safe composition path. [砚砚/gpt-5.6-sol🐾]
Why: events.publish is already a valid authority-safe provider ingress, but the closed Host delivery shape still cannot carry a Host-resolved provider coordinate and manifest outbound methods are not executable wire rows. Keep the reproduction precise so implementation can continue on every satisfiable half. [砚砚/gpt-5.6-sol🐾]
Why: Train C1 must finish as one repository-wide package compatibility pass, with packages as distribution units and runtime carriers hidden behind one Host lifecycle/action boundary. Freeze that terminal contract, classify every package directory, and checkpoint the reviewed SDK module seam plus Telegram/DingTalk consumers without inventing a provider-specific wire. Verification: plugin-sdk 325/325; Telegram 10/10; DingTalk 11/11; all three typechecks pass; repository inventory 7/8 with the sole intentional catalog RED for official.connector.dingtalk. [砚砚/gpt-5.6-sol🐾]
Why: the pause gate requires the executable Plugins ledger to record the exact Core counterpart that was actually read and to disambiguate retained physical-hardware limb work from C1 agent-side limb/skill consumers. Verification: inventory contract/provenance checks pass; the suite remains intentionally 7/8 with only official.connector.dingtalk missing from catalog. [砚砚/gpt-5.6-sol🐾]
Why: the C1 cutover requires every connector package to expose the same Host-loadable module lifecycle, preserve Host-owned binding and state authority, and ship a deterministic packed entrypoint instead of a dangling stdio declaration. Also pins the builtin default-export discovery guard and registry-canonical production shrinkwraps so catalog and fresh-consumer admission can fail closed. [砚砚/gpt-5.6-sol🐾]
Why: the migrated connector runtimes need deterministic catalog coordinates, dependency-ordered publication, and a fresh-consumer proof that imports each manifest-selected module default through the SDK guard. This closes all seven connector artifacts while leaving GitHub Operations as the sole explicit aggregate RED. [砚砚/gpt-5.6-sol🐾]
Why: the aggregate connector publish gate adds two multiline shell blocks, so the workflow syntax regression must count and parse all seven instead of failing on its stale five-block inventory. [砚砚/gpt-5.6-sol🐾]
Why: all seven connector modules are now cataloged and fresh-consumer installable, but their packed READMEs still claimed standalone runtime implementation remained pending. Describe the completed Host-loadable builtin modules, refresh the unpublished candidate coordinates with the pinned toolchain, and make catalog admission reject stale runtime status. [砚砚/gpt-5.6-sol🐾]
Why:
- B8: remove ambient node:child_process/ffmpeg authority from connector-feishu
(no process/filesystem capability in the contract vocabulary); non-opus audio
is now delivered as msg_type:file under its original name, source-guard test
pins the absence of the ambient path.
- N1/N3: feishu handleWebhook returns {kind:'skipped',reason:'not_running'}
when not running instead of silently dropping and reporting 'processed';
running-phase routeCard false maps only to chat_type_unknown.
- N2+B5 residual: dingtalk client.connect and feishu client.start are bounded
by a 30s timeout; stop-during-connect swallows the stale-generation path so
stop() cannot surface an unhandled rejection.
- B3 residual: wecom-bot stopStream detaches SDK listeners via removeAllListeners.
- B7: pnpm test:train-c1-inventory is now wired into contract-ci validate job,
making clause 3 repository-wide compatibility closure executable evidence.
The github-operations catalog exemption is pinned exactly to
implementationStatus 'port-declared, implementation-pending-in-plugins' with
deepEqual ['github'] so it tightens automatically when the status flips.
- catalog shasum/integrity tuples for all 7 connectors regenerated with the
pinned pack toolchain (Node 24.18.0 / npm 11.16.0) since package bytes changed.
Evidence: pnpm test 212/212 across 10 packages, catalog:check ok,
test:fresh-consumer 1/1, test:train-c1-inventory 8/8, conformance 34/34 + 18/18,
typecheck clean, git diff --check clean.
Co-authored-by: sol's uncommitted work reviewed and landed in this commit.
[小狸/k3🐾]
…nsent-surface gate Why: - F1: the production outbound path always carries `url:` (never absPath); downloadToTempFile mapped every non-image Content-Type to `.jpg`, so even true OPUS audio degraded into a `.jpg` file card once the ffmpeg sniffing was removed. Extension now comes from Content-Type (audio/opus keeps `.opus`), with URL-path fallback and a derived display name, and the url: branch is covered by a test. - F2: lark WSClient.close() only terminates the socket registered after 'open'; a stop() landing pre-open left an authenticated, self-reconnecting socket nobody could kill. PausableLarkWsClient terminates the current socket, installs a birth guard that kills any socket the SDK opens after stop, and no-ops pingLoop so a late 'open' cannot restart the ping timer. autoReconnect is disabled deliberately: SDK-owned reconnection was the revival mechanism; reconnect supervision belongs to the Host lifecycle. - F3: lark WSClient.start() and DWClient.connect() both resolve before any connection exists, so startStream/start settled early and the runtime reported 'running' over a dead connection. start now waits until the SDK registers an open socket (feishu: wsConfig.getWSInstance(); dingtalk: client.connected), bounded by the existing 30s timeout, and aborts cleanly when stop() races. - F4: packaged READMEs are the install consent surface but under-reported capabilities (7/7 drift). READMEs now disclose the exact plugin.yaml capability set, and a new inventory gate fails if any packaged README omits a declared capability. - Also: TOCTOU state recheck after the name-resolution await in routeEvent/ routeCard; overclaim comment corrected; dead uploadToFeishuInner collapsed; catalog shasum/integrity tuples regenerated for the 9 packages whose bytes changed (pinned toolchain Node 24.18.0 / npm 11.16.0). Evidence: pnpm test 1083/1083 across the repo, catalog:check ok, test:fresh-consumer 1/1, test:train-c1-inventory 9/9, conformance 34/34 + 18/18, typecheck clean, git diff --check clean. Co-authored-by: 缅因猫 sol (cat-eqdvbcxw) <sol@cat-cafe.local> [小狸/k3🐾]
…regen
Why:
- G1: both connectors reported `running` over a dead ingress. Feishu now
treats the socket's own 'close' as the liveness truth (lark leaves a dead
socket registered with autoReconnect off): unexpected close drops the
runtime out of 'running' and drives a supervised backoff reconnect, the
same acceptReconnects pattern WeComBotAdapter already owns. Dingtalk gets
a stream watchdog polling the client's connected+registered truth and
drains + restarts dead streams. The watchdog is armed only on transitions
into 'running'; arming at the top of start() leaked the interval for the
process lifetime whenever startStream rejected (found via test hang).
- G2: static servers serve OPUS voice data as audio/ogg (the ogg
container); the MIME map now keeps it on the .opus path instead of
degrading into a .ogg file card, and a display name without an extension
gets .opus appended so file_type/file_name stay consistent.
- G3: the webhook TOCTOU fix reported {kind:'processed'} with delivered=0.
routeEvent/routeCard now return the real delivery outcome and the
webhook derives 'processed' strictly from it; a guard-killed route
reports skipped/not_running.
- G4: the consent-surface gate read the first feature block of
disposition==='migrate' packages with a hand-rolled YAML scan. It now
parses plugin.yaml with a real parser (fail-closed), covers every
Manager-installable package (managerInstallable, not disposition), and
unions capabilities across ALL features; companion gains a README
consent surface. A mutation test that added a second-feature capability
and a companion capability previously passed silently.
- G5: downloadToTempFile used tmpdir()/...-${Date.now()}, so two concurrent
sendMedia calls in the same millisecond wrote each other's bytes and both
reported success. Each download now gets a private mkdtemp directory.
- N2/N5: dingtalk startStream shares one deadline between the connect()
race and the connected+registered liveness poll (was 2x30s), rejects when
the SDK gives up, and is covered by tests.
- Catalog: connector-feishu, connector-dingtalk, companion artifact
shasum/integrity regenerated with the pinned Node 24.18.0 + npm 11.16.0
toolchain after rebuilding dist; pnpm catalog:check passes end-to-end.
[小狸/k3🐾]
…backoff, mechanical class scans, catalog regen
Why:
- H1: feishu start() accepted any registered socket as connected; the lark SDK
leaves a CLOSING/CLOSED socket registered when autoReconnect is off, so a
flash-close resolved start() as "running" with a dead socket and no recovery
(permanent death on the second reconnect). Registration is not liveness: the
poll loop now accepts only readyState === OPEN (the SDK's own isOpen truth)
and throws otherwise, routing the failure into the supervised reconnect.
The synchronous CLOSING/CLOSED branch in watchSocketClose is gone — the
accept loop guarantees OPEN in the same tick, and the sync branch fired while
state was still 'starting', where the hook signal was dropped. Fakes carry
readyState like a real ws socket.
- H2: the audio/ogg MIME special-case declared real Vorbis/Speex ogg as opus.
Opus is now derived from bytes (OggS magic + OpusHead at offset 28), not from
the MIME header; a non-opus ogg degrades back to the file card it produced
before. Bidirectional tests pin both directions (revert = red).
- H3: inferFeishuFileType still did a bare index into FEISHU_EXT_TO_FILE_TYPE,
so 'constructor'/'__proto__' URL segments mapped to prototype values
(file_type "function Object()..."). Object.hasOwn + unit tests.
- H4: genoffice-docx was the only managerInstallable package with no README;
the gate's capabilities.length===0 early-continue skipped even the README
existence check. Added the README (zero-capability disclosure page) and the
gate now requires an install page for every installable package regardless
of capability count.
- Backoff: reconnect delay was a constant; commit messages said backoff while
the code retried ~700x/hour, each hammering a fresh tenant_access_token.
Both connectors now double from a base (default 5s) to a cap (default 60s)
with ±20% jitter, and reset on every transition into 'running'.
- Mechanical class scans (audit scope derived from commands, not memory):
* prototype-chain reads on Record maps: weixin-mp EXTENSION_MIME_MAP (bare
[ext] after slicing the dot — same H3 shape) and video-generation
'ext in MEDIA_MIME' (in walks the prototype chain) both fixed with
Object.hasOwn; plugin-contract CAPABILITY_TABLE is safe (keys iterated
from Object.keys); feishu's two maps were already guarded this round.
* tmpdir() + non-random names: weixin convertWavToSilk used
tmpdir()+Date.now().silk — the G5 twin in a live connector; now mkdtemp
private dir + recursive cleanup in sendMedia's finally. weixin :1001
(randomUUID) is the control; weixin-mp handlers:38 combines
Date.now()+hrtime.bigint()+seq (effectively unique, justified);
wechat-visible-reader cache files are content-addressed by source digest
(justified).
* existence-as-liveness: the only !== null liveness gate left is feishu's
registration gate, which now derives liveness from readyState === OPEN;
dingtalk's isStreamLive gates on the SDK's connected && registered truth;
xiaoyi checks readyState === OPEN everywhere.
- Catalog: regenerated artifact hashes for the six repacked packages. The
companion entry was additionally corrected: its recorded hash did not
reproduce from committed sources even on a pristine de3a93c checkout
(pre-existing round-4 drift, verified by stashing all round-5 changes and
re-running the check); the entry now carries the deterministic pack bytes.
pnpm catalog:check EXIT=0; pnpm test 1103/1103.
[小狸/k3🐾]
Why: round 5's five blockers share one root cause — the acceptance evidence source (wrong remote pushed, local env treated as authority, no pre-merge gate sees publishability). Fixes plus two gates that see the class, not the instance. - B1: round-5 commit was pushed to origin (upstream) instead of the PR's head repo (fork); the PR never moved. This round pushes to the fork. - B2: revert companion catalog shasum/integrity to the recorded values — CI's pinned toolchain reproduces the recorded bytes; my round-5 regen had diverged locally, the record was truth. - B3: startIngress() now force-closes a ws client whose start() throws (H1 made that the routine path; the leak was the F2 orphan reborn) and handleUnexpectedClose() checks caller identity — an orphaned client's late close can no longer tear down the healthy current connection. - B4: genoffice-docx README.md enters package.json files[] and both assert-pack-ready allowlists; the undeclared entry would have failed prepack only in the post-merge publish job (pack-publish-artifact uses --ignore-scripts, and CI's publish job is push-to-main only). - B5: prototype-chain lookups hardened at companion/src/errors.mjs and feishu-card-formatter.ts (hasOwn; ?? and || pass truthy prototype hits); wechat-visible-reader compiles in a per-process mkdtemp staging dir and atomically renames into the shared digest-keyed path (concurrent swiftc writers can no longer leave a half-linked binary that access(X_OK) approves and we execute). weixin-mp handlers.ts:38 needs no change: Date.now()+process.hrtime.bigint()+monotonic counter is unique per process even under same-ms bursts; collision needs cross-process ms equality AND counter reset, and the payload is a non-sensitive session transcript, not a shared build artifact. - Gate 1: scripts/pack-gate.mjs packs every publishable package WITH lifecycle scripts (prepack) on the PR; catalog:check structurally cannot see this class. Root script pack:gate; CI step after Machine catalog. Build order in pack:gate is explicit and sequential — pnpm -r build races plugin-sdk against companion and loses. - Gate 2: scripts/assert-pr-head.mjs asserts the sha under test equals the PR's live head via the GitHub API; CI runs it first on pull_request. Kills the stale-green class that let a wrong-remote push stand. - CI push path table gains stackchan/** and the two new scripts. - Catalog regen for the four byte-changed packages (feishu, companion, wechat-visible-reader, genoffice-docx); catalog verified against the pinned toolchain. Verification: full pnpm test 1105/1105 fail=0 (35 feishu runtime tests including two new B3 cases); pnpm catalog:check EXIT=0; pnpm pack:gate 19/19 publishable packages pack clean with prepack; fresh-consumer green. [小狸/k3🐾]
Why: - C2: weixin-mp convert_markdown derived its output path from Date.now()+hrtime+module counter — opus measured 35.67% consecutive hrtime collisions and per-worker counters restarting at 0, so concurrent conversions could overwrite each other's article HTML. Now each conversion gets a private mkdtemp(0700) directory; test pins distinct output paths per conversion. - A4 residue: wechat-visible-reader native runner no longer branches on execute === defaultExecutor — staging compile is unconditional, so an injected execute seam covers the same path production takes (the old gate made the only compile test unable to reach the staging branch). Default cache moved from bare tmpdir() to a private cat-cafe-wechat-reader-cache dir created 0700. Compile test now writes the -o target and asserts the staged path != final executable. - C1: pack gate deterministically fails on feishu-meeting-intake (rerun of CI run 35522543157 reproduced the npm-internal "Exit handler never called!" exit 1). It is the only bundledDependencies package; the real publish path packs with --ignore-scripts and never runs its prepack, so the gate cannot make that release safer. Explicit, commented exemption instead of a silent skip. - Gate honesty follow-ups from opus: pack-gate step renamed (18/19 prepacks are just pnpm build), validate job gets permissions block (contents+pull-requests read; gh api 403s on private repos otherwise), CI asserts git rev-parse HEAD == PR head before the script, assert-pr-head comment narrowed to what it can actually catch (a wrong-remote push produces no run; the delivery ritual in CONTRIBUTING is the local half), pack-gate uses fileURLToPath and a 16MB maxBuffer. Verified: weixin-mp/wechat-visible-reader test+typecheck green; pack gate 18 ok + 1 explicit exempt; full pnpm test 1105/1105; catalog regen for the two source-changed packages, catalog:check EXIT=0. [小狸/k3🐾]
Why: - Rebasing onto main (7251983, PR zts212653#55) conflicted on plugin-sdk version pins and the fresh-consumer assertions; main is ahead (sdk 0.1.0-beta.13, contract 0.1.0-beta.17) so the branch takes main's higher versions instead of its own older bumps (beta.12/beta.16). - catalog.json companion block regenerated during the rebase picked up the stale alpha.2 artifact; restored main's alpha.3 artifact metadata (integrity/shasum) since packages/companion is alpha.3 on main. - pnpm-lock.yaml already matched main's versions after auto-merge; no lockfile change needed. 小狸 [狸花猫/k3🐾]
Why: - The rebase onto main (7251983) changed package contents (companion README merge + errors.mjs hardening, version-pin reconciliation), so every packed tarball hash drifted from the catalog entries that round 6 regenerated pre-rebase. catalog:check packs each plugin via scripts/pack-publish-artifact.mjs and asserts integrity/shasum; all 13 entries are refreshed from actual packs. No versions changed. 小狸 [狸花猫/k3🐾]
Why: - After the version reconciliation with main (785626d), plugin-sdk is 0.1.0-beta.13 but the seven connector packages still pinned 0.1.0-beta.12, which no longer resolves on the npm registry (fresh-consumer install failed with ETARGET). The pins move to beta.13; pnpm-lock and catalog artifact hashes regenerate accordingly (packing verified deterministic across repeated packs). 小狸 [狸花猫/k3🐾]
Why: - video-analysis/video-generation dist had been built against the stale pre-rebase plugin-sdk d.ts, so their packed hashes drifted again after the full rebuild. Re-verified determinism: repeated clean rebuilds produce identical dist and identical tarballs. The flip source was the stale SDK d.ts, not the pack pipeline. 小狸 [狸花猫/k3🐾]
Why: npm registry no longer carries plugin-sdk beta.12 (replaced by beta.13 when PR zts212653#55 bumped plugin-sdk on main), so connector shrinkwraps must pin beta.13 or fresh-consumer install fails with ETARGET. npmmirror-based regeneration rewrote resolved URLs off registry.npmjs.org and violated the catalog resolved-URL conformance rule, so instead restore the original shrinkwrap trees and patch only the plugin-sdk/plugin-contract entries with registry.npmjs.org metadata pulled from the live registry. 小狸 [狸花猫/k3🐾]
Why: macOS cleaned the pinned Node/npm installation under /tmp during the train, leaving later artifact checks incomplete or silently using the system npm. Document a persistent install path and make /tmp-only toolchains explicitly unsupported. [砚砚/gpt-5.6-sol🐾]
…onnection status Why: each Host poll currently opens another socket while the helper is absent, and authorization status hides the helper state. Observe actual socket connections independently of business results, gate only list with lazy 2s-to-60s backoff, show last-known reachability in the rendered status label, and log only state transitions. Preserve explicit probes and dispose pending exchanges without retry timers. Evidence: new real-socket reachability checks fail on afeaa70; targeted p2b/p2c/carrier tests 41/41, visible status and lifecycle checks 13/13, package typecheck passed. Full package suite and final post-sync catalog/gate remain pending; no remote push. [astra/gpt-6-astra🐾]
Why: rejected pairing records must replace stale reachability in owner-visible status, with repair guidance and transition-only logging, without activating reconnect backoff. [缅因猫/astra/gpt-6-astra🐾]
Why: the p2c runtime and repair guidance change packed bytes; compute the catalog identity after rebasing onto the attested beta.27 and beta.11 dependency closure. [缅因猫/astra/gpt-6-astra🐾]
Incremental maintainer review request — completed #54 slices through
|
| # | Slice | Commits / range | Scope and size | Local approval |
|---|---|---|---|---|
| 1 | W2-3 p1: move the Host's Personal Chrome extension and native host into personal-chrome-companion |
fcc594d d350937 63b551a fd79279 7a9087e 678681a (e2aef8f..678681a) |
46 files, +8,392 −846; package extension/native-host, their real tests and fresh-consumer coverage | Opus approved exact 678681aef1ca1c7bccd4c2c662b68d35833274a7 (local review …000180) |
| 2 | Upstream sync through #60–#62 and companion collision-safe bump | merge d25c4eb, then 1ba2423 (678681a..1ba2423) |
2 first-parent commits; 38 files, +639 −36; companion source/tests/assets, catalog and ledger | Opus approved exact 1ba2423a02d192c38664d010e64af7138fcd52c2 (…000309) |
| 3 | Freeze h1/h2/h3 contract shapes as contract beta.24 / SDK beta.7 and close review gaps | 4e54f1d 7c789df 29d82fe (1ba2423..29d82fe) |
3 commits; 54 files, +1,684 −184; contract/SDK plus the complete consumer pin closure | Opus approved exact 29d82fe20c1f34aeab0adef2a04f2242dbffa9e9 (…000627); Fable independently verified the canonical artifacts (…000640) |
| 4 | Sync main #63 as contract beta.25 / SDK beta.8, fix loopback timing, and finish the extension escape-hatch audit | 82ecb15 merge a9eecab d51a664 aae96e0 55862d3 736256a (29d82fe..736256a) |
6 first-parent commits; 57 files, +1,168 −317; contract/SDK/consumer closure, loopback test, one Personal Chrome audit test | Opus approved beta.25 exact 55862d36128bcb580434c408411b9bb67716834c (…000702) and the audit content later pushed byte-identically as 736256a (…000660, continuity …000713) |
| 5 | SDK h2 carrier repair: pass the granted Host data directory through the real module carrier and fail closed without the grant | 6c02298 (383ef60..6c02298) |
1 commit; 43 files, +371 −176; SDK implementation/tests plus 12 exact dependency re-pins and catalog closure | Sol approved exact 6c022987cba19e646f8523f422c38d16826f9c50 (…000934); Astra independently verified the canonical artifact (…000937) |
| 6 | W2-3 p2a: module-plugin skeleton, manifest/capabilities, authorization list and per-row revoke, status/test/stop, install docs and real create().start() test |
direct commits f2adca6 e76cd3b e692308 dc1b3f2 7ca22be 666f7f0 9907d13, merge 262f721, then 303f0ec 383ef60 aef8d6a |
10 direct commits plus 1 merge; direct-commit delta 19 unique files, +1,346 −25; merge conflict resolution covers 4 files. Primarily packages/personal-chrome-companion, plus catalog/release/fresh-consumer evidence |
Sol reviewed the merge in the p2a rounds (383ef60 changes requested → exact aef8d6a63a7d47a31888caa9e08ddc327a1b48a1 approved, …000022) |
| 7 | R3/version sync #1: account for the p2b implementer's interim beta.25 reuse, absorb upstream #64/#67 without reusing a frozen identity, then move to contract beta.26, SDK beta.10 and companion alpha.16 with an attested-identity guard | c92a8c6, merge 75481fb, 7c16e03 3fc4b0b 0d30250, merge b5ad781, b7a08af f1e10d4 c53520d a17b998 (33abebb..a17b998) |
10 first-parent commits; 53 files, +780 −231; contract/SDK/companion, 11 production consumers, catalog and release guards. Review 75481fb's six-file conflict resolution with this slice |
Sol requested changes at 0d30250 because the interim commits reused frozen beta.25 bytes (R3 …000132 / …000135); Opus chose forward-fix option A (…000137); Sol approved the sync at c53520d (…000220); Astra rejected and then verified closure at exact a17b9982c6981390e577fe1aa196d63840e87872 (…000223, …000239); Sol's later c53520d..afeaa70 approval explicitly includes that closure fix |
| 8 | W2-3 p2b: v2 protocol and real socket-backed append/list/ack, including stop cancellation and post-write ambiguity semantics | direct commits 7c9c80b f226c8b f638d58 25a6c36 33abebb c6c3381 00c184d e4b3284 afeaa70 |
9 direct commits; 14 unique files, +2,025 −423; Personal Chrome source/tests plus its catalog pin and closure guard | Sol approved exact afeaa705c9b74b4f7e7d502ce6a876ed249a4275 (…000298) after the R1/R2 red-to-green repair |
| 9 | Version sync #2: absorb upstream #68/#69; contract beta.27, SDK beta.11, companion alpha.18; extend the attested guard and move the frozen-toolchain instructions out of ephemeral /tmp |
644d66a, merge b5f218e, e5ae546, 6fa5c46 (afeaa70..6fa5c46) |
4 first-parent commits; 60 files, +973 −247; contract/SDK/companion, 11 production consumers, catalog/guards and CONTRIBUTING.md |
Sol approved exact 6fa5c46e0ec1fe53f8a52ea19f8010cc35ac1df7 (…000114); Astra independently verified the canonical artifacts (…000129) |
For a first-parent overview:
git log --first-parent --oneline e2aef8f..6fa5c46For p2a and p2b, use the explicit commit sets in the table rather than treating their work as one contiguous range; the intervening sync commits are separate review slices above.
First-parent completeness and merge audit
Every first-parent commit in e2aef8f..6fa5c46 belongs to exactly one slice above. The six merge commits are:
| Merge | Upstream parent | git show --cc result / resolution scope |
|---|---|---|
d25c4eb |
264266347dcf1eada31a5f1646c4a2c1ac71afec |
non-empty combined diff: catalog/catalog.json, packages/companion/README.md, packages/companion/package.json |
a9eecab |
0487e482148334563dc38d47027aa4bf55164b35 |
non-empty combined diff: packages/companion/README.md, packages/plugin-contract/src/generated/contract.generated.ts |
262f721 |
d5cc46aac57d8b746056dd98989f7993586067dd |
non-empty combined diff; four resolved files: .github/workflows/contract-ci.yml, migration/f202-train-c1-inventory.json, pnpm-lock.yaml, scripts/fresh-consumer-install.test.mjs |
75481fb |
0a2783978a78627378c76574a40104a847d9cab1 |
combined diff empty. Six conflict files were resolved to parent-compatible content: companion decision-view.mjs plus two tests, contract companion-bridge.schema.json plus its test, and SDK companion-client.test.ts. Please review this resolution with slice 7 |
b5ad781 |
791d63ce4397eaead1c363221b622b4488718f07 |
non-empty combined diff: catalog/catalog.json |
b5f218e |
fdd1a83fa40711b755e20cf4afef7f231c7a4b15 |
non-empty combined diff: catalog/catalog.json, packages/companion/README.md, packages/plugin-contract/src/generated/contract.generated.ts |
2. Acceptance checks already complete
All canonical packs below were produced with the frozen Node 24.18.0 / npm 11.16.0 / zlib 1.3.1-e00f703 toolchain and independently rebuilt before attestation.
| Slice | Reproducible evidence |
|---|---|
| p1 | The migrated extension's 11 files and native host's 15 files are byte-identical to the Host source; 11 tests, 2 helpers and 1 fixture were moved with them. Exact-head CI: Contract 36171504155, Personal Chrome 36171504299, both success. |
| Sync #60–#62 | Exact-head CI: Contract 36224064202, Companion 36224064197, both success. The merge was reviewed separately from the companion version bump. |
| beta.24 / beta.7 | pnpm gate:ci 27/27 on the exact tree; targeted contract/SDK validation and artifact byte comparison passed. The PR was temporarily conflicting, so this slice has no exact-head GitHub run; that absence is explicit rather than being inferred green. |
| beta.25 / beta.8 + audit | pnpm gate:ci 27/27. Exact-head CI at 55862d3: Contract 36326898937, Companion 36326898927; the audit-only successor 736256a has Contract 36327598966, Companion 36327598947. All passed. |
| SDK beta.9 carrier | Real create(plugin.yaml).start(host) changed from the beta.8 PERMISSION failure to a successful start/list/stop; the no-grant case still throws PERMISSION. SDK-focused tests 49/49, fresh-consumer 1/1 and pnpm catalog:check 17/17 passed. Exact-head CI: Contract 36337656573, Companion 36337656615. |
| p2a | pnpm --filter @clowder-ai/personal-chrome-companion test 137/137; the real entrypoint test covers granted-directory access, list/status/test, own-function contribution methods, contract validators and stop cleanup. pnpm gate:ci 27/27. Exact-head CI: Contract 36339676700, Personal Chrome 36339676692. |
| Version sync #1 | The new attested-identity guard first fails on the old beta.25/new-bytes incident and passes after the version bump. pnpm gate:ci 28/28; all 11 production shrinkwraps close over the independently packed bytes. Exact-head CI at the final closure head a17b998: Contract 36397386904, Companion 36397387095. |
| p2b | Nine real Unix-socket seam regressions cover stop races, malformed/truncated/post-write receipts and a typed-failure control. Package tests 161/161, production shrinkwrap gate 15/15, pnpm gate:ci 28/28. Exact-head CI: Contract 36404795396, Personal Chrome 36404795347. |
| Version sync #2 | Attested-identity plus production-closure tests 18/18; companion-bridge contract tests 7/7; SDK companion-client tests 7/7; pnpm gate:ci 28/28; pnpm catalog:check 17/17 across all 11 production consumers. Exact-head CI: Contract 36689132119, Companion 36689132264. |
Attested artifact coordinates
| Package | SHA-256 | Size |
|---|---|---|
@clowder-ai/plugin-contract@0.1.0-beta.24 |
d0dda313a6689efdf81dede6983cf2430ff5ae97d5ec529e1fbfcf9a34aaaeff |
220,820 B |
@clowder-ai/plugin-sdk@0.2.0-beta.7 |
d4d9a568f72cb523b6e08054e59f5c83144f300794d0a293f53a5d10bfbfbb84 |
54,762 B |
@clowder-ai/plugin-contract@0.1.0-beta.25 |
80816b015dbf035b322a60e218e298be48d889499b3a12018118bf4648e71dde |
222,009 B |
@clowder-ai/plugin-sdk@0.2.0-beta.8 |
886bb594f53989dd318acadd875d6e36a679babfe011b890df39c5a267876f26 |
54,761 B |
@clowder-ai/plugin-sdk@0.2.0-beta.9 |
8579f442d0a68c37d12a0e887685012d7d386939b621c0a3a7bad42e082a98b7 |
54,926 B |
@clowder-ai/plugin-contract@0.1.0-beta.26 |
c190d21756023d3552cc6b3427d2441fee7b30099c3e5763bdbff9b64efe7927 |
222,014 B |
@clowder-ai/plugin-sdk@0.2.0-beta.10 |
0c7c6e0a46d76d95f3c10502235be462749b84533d85095fc0653493e1d7e28e |
54,928 B |
@clowder-ai/plugin-contract@0.1.0-beta.27 |
5dedbe7e49e7153348608124db530415ed4aff57f451ca0b71e841412f7629f6 |
222,858 B |
@clowder-ai/plugin-sdk@0.2.0-beta.11 |
c62e138e9ed0bccd9c3d11aeb9bfbf6d752b1d6a136837baefa2f791b6072482 |
55,056 B |
The version-to-version member diffs were also independently checked: beta.24/beta.7 only the frozen h1/h2/h3 surface; beta.25/beta.8 only main #63 plus versions; beta.9 exactly 8 SDK members; beta.26/beta.10 exactly 2 contract and 1 SDK members; beta.27/beta.11 exactly 8 contract and 5 SDK members. No unlisted member was added, removed or changed in those syncs.
3. What we need from you
- A scoped code review of the nine completed slices above. The local approvals and artifact attestations are evidence, not upstream approval or merge authority.
- Please pay particular attention to three boundaries:
- the p1 extension/native-host files remain byte-identical to the Host copies while package-owned tests close the escape hatches;
- p2b never reports
HOST_UNAVAILABLEafter a request may have been written, andstop(reason)settles every in-flight request without leaking sockets; - the attested-identity guard makes any frozen version whose bytes drift fail closed before publication.
- No architecture decision is pending for these completed slices.
4. Remaining work — not waiting on this review
- p2c is in progress and excluded from this request. Its three commits are currently at the live PR tip (
68f15b6,16287c4,847176e; 8 files, +501 −46). They add lazy 2s→60s list backoff, honest helper status including invalid installation, transition-only logging and the catalog pin. It still needs its exact-head CI/local Sol verdict before it can be offered as ready. - p2d has not started: stable extension load path in the plugin data directory, update/reload and tested rollback behavior, the helper-update decision, package-owned extension checks and icon hashes. p2d owns the acceptance evidence needed by Host h3c-3.
- Batch 6 artifacts come only after p2a–p2d are all approved: the seven connectors plus
personal-chrome-companion, independently packed and verified by Astra. - Host h3c-3 then switches ChatGPT Pro to the package and removes the Host copy. The Host's h3c-1 and h3c-2 slices are already approved; h3c-3 intentionally waits on p2d and Batch 6.
- Hands-on acceptance still needs the operator's real accounts for QR login and real IM send/receive.
This does not change the merge policy: #54 remains draft, and #54 plus #1487 merge together only after the remaining work and the operator's hands-on acceptance. No merge or publication is requested by this comment.
… on start Why: keep the Chrome load path stable across updates and rollbacks, preserve pairing identity, and make owner reload requirements durable and truthful. Publish only within the granted data directory under the installer lease; drain ordered revision observations on stop. Authored by astra (gpt-6-astra).
Why: bind the catalog to the final p2d-1 packed bytes after extension/helper delivery, reload observation, tests and README are complete. Authored by astra (gpt-6-astra).
Slice 10 ready for review — W2-3 p2cFollow-up to the nine-slice review request: p2c has now completed local review and is ready as slice 10.
What changed
Local approval and evidence
Still pendingp2d-1 is currently in local review at p2d, batch 6, Host h3c-3, and Landy's hands-on acceptance remain pending. This slice being ready for review does not change the merge policy: #54 remains draft, and #54 and #1487 still merge together only after hands-on acceptance. No merge or publish is requested here. |
…epted observations Why: helper activation failures must restore the prior extension under the same installer lease; stopping must persist STALE observations accepted before admission closes. Covers both review regressions and re-pins the packed artifact. Author: astra / gpt-6-astra
Why: p2d removes the Host-owned extension copy, so the package must own its manifest, revision, generated bundle, executable budget, and icon identity checks. Port the deterministic generator with a direct pinned tool dependency while preserving the shipped script body byte-for-byte. [砚砚/gpt-5.6-sol🐾]
Why: the package now owns the extension contract assertions and generator, so the catalog must identify the exact packed bytes whose content-script body, protocol revision, permissions, and icon hashes were verified. [砚砚/gpt-5.6-sol🐾]
Why: delayed identity failures could log through a revoked Host context, and load-sensitive tests plus a single npm reset prevented reliable C1 validation. Drain cancelled identity work, exercise watchdog transitions with a clock, bound each connector test file, and retry only transient registry transport failures. Re-pin the un-attested Feishu alpha.1 artifact; keep versions and p2d surfaces unchanged. Authored-by: astra (gpt-6-astra)
Why: release-config intentionally verifies package test script invocation. Scope the deadline preload through NODE_OPTIONS instead of replacing those entrypoints, and exercise that exact transport in the hung-file fixtures. Authored-by: astra (gpt-6-astra)
Why: the explicit script inventory must execute the new hung-file fixtures on every full gate, not only during targeted local validation. Authored-by: astra (gpt-6-astra)
Two more finished slices ready for maintainer review (11–12)This follows the per-slice review request in the earlier checklist and its p2c follow-up. The PR is still an aggregate and remains draft, but these two additional slices are locally complete and independently approved. The current PR HEAD is Slice 11 — W2-3 p2d-1: extension/helper delivery and reload lifecycle
Slice 12 — W2-3 p2d-2: package-owned extension assertions and generator
Boundary and remaining work
|
Why: repeated gates should not require a fresh TLS connection for immutable source bytes. Validate cached SHA-256 before reuse, retry only bounded transient transport failures, and retain all archive/source admission checks. Added deterministic offline, corruption, timeout, and fail-closed tests. Authored-by: astra (gpt-6-astra)
Why: the release packer ignored canonical shrinkwrap resolution and archived wall-clock metadata, so registry drift and gzip timestamps could change self-contained bytes without a source change. Drive production installs from the shrinkwrap, restore canonical manifests, and normalize archive framing before hashing. [砚砚/gpt-5.6-sol🐾]
Two more finished slices are ready for review (slices 13–14)The live PR head is Slice 13 — gate stabilization, including a Feishu production lifecycle fix
Slice 14 — reproducible self-contained release packing
Batch 6 release evidenceThe reviewed packer produced the non-draft prerelease Astra independently rebuilt all eight canonical npm packages and all eight self-contained archives from a clean exact-HEAD worktree, without reusing the release files. All eight rebuilt archives equal the downloaded assets byte-for-byte; canonical SHA-256/SHA-1/SRI/member counts match the catalog; Self-contained SHA-256: The reproducibility claim is deliberately limited to the frozen macOS/darwin-arm64 toolchain; it does not claim arbitrary cross-platform tar/gzip/xattr byte identity. Still pending on our side
These pending integration/acceptance steps do not change that slices 13 and 14 are complete and locally approved at the exact ranges above. |
Why: removing the Host copy must retain readable recovery titles. Reuse the paired helper exchange and stop/backoff boundaries, expose the existing titleSync union, and advance the attested alpha.0 package to alpha.1.
Why: bind the new owner action to frozen npm artifact bytes while retaining the independently attested alpha.0 coordinates from batch 6.
Why: p2e advances the already attested alpha.0 package; the consumer gate must assert the new approved version instead of the old fixture.
Slice 15 ready for review — p2e title refresh actionThe ready-for-review boundary is now exact HEAD Slice 15 — personal Chrome
|
…bins Why: real Host acceptance exposed a missing rows-renderer declaration in personal-chrome. Merge exact upstream 8ee84f6 before the required push, retain both C1 and upstream capabilities, and version all changed attested artifacts. The package-bin audit also found build-state-dependent executable modes; normalize declared bins after builds and reject non-executable archives. Preserve historical catalog coordinates and existing releases.
Why: preserving both main and C1 history appended newer upstream companion entries after older versions, violating catalog semantic ordering. Reorder records without changing any historical coordinates or package bytes.
Why: valid subpath-only dependencies were rejected after successful entrypoint imports. Retain exact physical closure and real main/runtime import checks, require all direct packages in the checked installed set, and cover missing subpaths, packages, version drift and escaping links.
Why: Xiangqi declares its valid library entry as a string root export rather than main or a conditional import object. Exercise that actual entry and keep missing-entry rejection; cover both exports shorthand and root-map forms.
Why: Fresh Chrome setup must be reachable through the owner-confirmed Host journey rather than README commands. Supply a bounded install/inspect/uninstall protocol with stable identity, registration ownership and preserved user data; keep browser loading explicit and connection status honest. Attest the new alpha.3 identity with canonical and real archive setup coverage.
Why: Independent review reproduced a helper-start race during setup and a successful uninstall that retained an owned orphan registration. Hold the existing helper socket fence across mutations, validate borrowed inactive leases, remove owned orphan registrations, and cover both race orders and data-preserving cleanup with deterministic regressions.
The text below is preserved from the original aggregate description. Its checkpoint/evidence numbers predate the 2026-09-30 status above.
What
Completes the Plugins half of the F202 Train C1 two-PR cutover as one aggregate migration.
C1 terminal acceptance
The durable finish line is in
docs/plans/2026-09-19-train-c1-plugins-aggregate-migration.mdandmigration/f202-train-c1-inventory.json.PR #54 closes repository-wide contract/SDK/YAML/runtime/catalog/pack/fresh-consumer compatibility, not only the new package directories. Every Manager-installable package has one canonical manifest truth, an explicit runtime/lifecycle disposition, honest package contents, catalog status, and a fresh-consumer path.
Core PR #1487 consumes exact reviewed artifacts through one carrier-neutral lifecycle/action boundary, proves no-double-run and recovery, switches defaults, and deletes legacy execution paths without package-specific runtime branches. The dependency order is Plugins exact Linux pack → Core integration journey → Plugins merge/automatic publication → Core registry pin/final journey/merge. There is no third C1 cleanup PR.
Historical checkpoint from the original description
Exact HEAD
9e285ecdb53627250a6bca5894f5c68556ed4746:@clowder-ai/plugin-sdk@0.1.0-beta.12exportsPluginModuleEntrypoint,definePluginModule,activateDefinedFeature, andActivePluginFeature; builtin entrypoints default-export the validated module shape.dist/plugin-entrypoint.jsmodules and retain provider-specific egress behavior behind the common Host lifecycle/action boundary.Evidence
official.github-operations is missing from catalog.git diff --check: clean.Boundaries
0001789870442375-002134-eaaa5365.[砚砚/gpt-5.6-sol🐾]