fix(daemon): slice 3.2 truth-in-labeling repair — README + test pins for v0 probe-only fetch path

Per velocity-guard BLOCKING-CONCERN on 67cafec (2026-05-10): vendored
README claimed GitHub auto-fetch + version-compare + hot-update behavior
that the implementation does not actually deliver at v0 (success path
only logs; no tarball extraction; no version-compare; no .version file
write). README + slice-close ACK language must match reality OR
extract/version-compare/update must be implemented.

Choosing truth-in-labeling path per IMPL-PRD §2.5 explicitly scoping
extract+install to slice 3.6 (marketplace-consumption phase) and per
orch direction 2026-05-10 (vendored is source of truth at v0; repo
currently empty per founder authorization; publish authorization
deferred).

REPAIR:

1. README rewrite:
   - 'At v0 (today)' explicitly framed: vendored copy is source of truth;
     copied to ~/.openrig/plugins/openrig-core/ on first run; offline-safe
     baseline; always available
   - 'Auto-fetch from GitHub at v0' explicitly framed as PROBE-ONLY:
     daemon hits releases tarball URL on launch with 5s timeout;
     **success path only logs the response and does NOT extract a tarball,
     compare versions, or update the local copy** — extract/version-
     compare/update scoped to slice 3.6
   - 404/network/timeout all tolerated silently with vendored remaining
     authoritative
   - 'Future (slice 3.6)' framed as the eventual hot-update path

2. New tests pin v0 contract (so any accidental extract-on-200 lands as
   TDD-red signal in slice 3.6, not silently in 3.2):
   - timeoutMs=5000 explicit assertion (per IMPL-PRD §2.5)
   - v0 success-path probe-only contract: even on 200, user plugin
     content unchanged + no .version file written

3. (Below — separate slice-close ACK packet authoring task) HG-2.3 status
   downgraded from 'fully green' to 'service-unit + startup-wire proof,
   not fresh daemon-start proof — fresh-daemon-start coverage requires
   QA/dogfood window'. HG-2.6/HG-2.7/HG-2.8 status flagged as 'live
   hook/UI behavior remains QA/dogfood proof'.

Verification:
- plugin-vendor-service.test.ts: 12/12 pass (10 existing + 2 new)
- All other 3.2 tests still green (openrig-core-plugin.test.ts: 25/25)
- Full daemon suite: 3208 pass; 1 fail (pre-existing rsi-v2)
- daemon tsc clean

Per velocity-guard BLOCKING-CONCERN on 67cafec + IMPL-PRD §2.5
(extract/install scoped to slice 3.6) + plugin-primitive Phase 3a
slice 3.2.
This commit is contained in:
mvschwarz committed 2026-05-10 04:56:13 -07:00
1 parent 67cafeca97
commit c6e06705f2
2 files changed
+54 -5

No files matched your search

@@ -12,8 +12,8 @@ Canonical OpenRig skills and hooks for cross-runtime agent topology coordination
This plugin ships dual-manifest packaging — both `.claude-plugin/` and `.codex-plugin/`. Use it with:
- **Claude Code** — install via `/plugin install openrig-core@mvschwarz/openrig-plugins` (or via the OpenRig daemon's auto-vendor on first run)
- **Codex CLI** — install via `/plugins` (or via OpenRig daemon)
- **Claude Code** — install via `/plugin` after the OpenRig daemon vendors `openrig-core/` to `~/.openrig/plugins/openrig-core/` on first run, or install the plugin directly through Claude Code's own plugin commands when remote distribution is available
- **Codex CLI** — install via `/plugins` after the same vendoring step, or directly through Codex's own plugin commands
Two skills target Claude Code's compaction behavior specifically:
- `claude-compaction-restore` — used to rebuild a Claude Code agent's working mental model after `/compact`, from JSONL transcripts and touched files
@@ -25,11 +25,11 @@ All other skills are cross-runtime by design.
## Distribution
This plugin is published two ways:
**At v0 (today):** the vendored copy inside the OpenRig npm package is the source of truth. When you install `@openrig/cli` (or run the daemon), `openrig-core/` is copied to `~/.openrig/plugins/openrig-core/` on first run. This is the offline-safe baseline and is always available.
1. **Vendored inside the OpenRig npm package.** When you install `@openrig/cli` (or run the daemon), `openrig-core/` is copied to `~/.openrig/plugins/openrig-core/` on first run. This is the offline-safe baseline.
**Auto-fetch from GitHub at v0:** the OpenRig daemon probes `github.com/mvschwarz/openrig-plugins/releases/latest/download/openrig-core.tar.gz` on launch with a 5s timeout. **At v0 the success path only logs the response and does NOT extract a tarball, compare versions, or update the local copy** — extraction + version-compare + update are scoped to a later marketplace-consumption phase (mission slice 3.6). 404 (the expected normal-state response while the GitHub repo is empty), network errors, and timeouts are all tolerated silently with the vendored copy remaining authoritative.
2. **GitHub auto-fetch.** When network is available, the OpenRig daemon checks `github.com/mvschwarz/openrig-plugins` for a newer version of `openrig-core` and updates the local copy. This is the "hot update" path — skill improvements ship without bumping the OpenRig CLI version.
**Future (slice 3.6, marketplace-consumption phase):** when the GitHub releases workflow is set up and authorization to publish lands, the daemon will start extracting fetched tarballs + comparing versions + updating the local copy as the "hot update" path that skips OpenRig CLI version bumps.
You can also install directly via Claude Code or Codex's own plugin commands if you prefer to manage plugins outside OpenRig.
@@ -189,6 +189,55 @@ describe("PluginVendorService — auto-fetch (HG-2.4 + HG-2.5)", () => {
const url = httpClient.mock.calls[0]?.[0] as string;
expect(url).toMatch(/github\.com\/mvschwarz\/openrig-plugins|api\.github\.com.*mvschwarz\/openrig-plugins/);
});
it("attemptAutoFetch passes timeoutMs=5000 to httpClient (per IMPL-PRD §2.5 5s timeout)", async () => {
const fs = mockFs(VENDORED_OPENRIG_CORE);
const httpClient = vi.fn().mockResolvedValue({ ok: false, status: 404 });
const svc = new PluginVendorService({
vendoredAssetsDir: "/asset-root",
userPluginsDir: "/home/test/.openrig/plugins",
fs,
httpClient,
logger: vi.fn(),
});
await svc.attemptAutoFetch("openrig-core");
expect(httpClient).toHaveBeenCalled();
const opts = httpClient.mock.calls[0]?.[1] as { timeoutMs?: number } | undefined;
expect(opts?.timeoutMs).toBe(5000);
});
it("attemptAutoFetch v0 success-path is probe-only — does NOT extract tarball or update vendored copy", async () => {
// Per slice-3.2 v0 scope (per orch-lead 2026-05-10 + velocity-guard 60344b3 BLOCKING-CONCERN):
// - 404 is the expected normal-state response (repo currently empty per founder authorization)
// - Even on a 200 success, v0 does NOT extract or update — extraction/version-compare/update
// is explicitly scoped to slice 3.6 (marketplace-consumption phase)
// This test pins the v0 contract so an accidental "implement extract" lands as a TDD-red
// signal in slice 3.6 (where it's intentional) rather than silently in 3.2.
const initialUserPlugin = "/home/test/.openrig/plugins/openrig-core/.claude-plugin/plugin.json";
const initialContent = '{"name":"openrig-core","version":"0.1.0"}';
const fs = mockFs({
...VENDORED_OPENRIG_CORE,
[initialUserPlugin]: initialContent,
});
// Mock a successful 200 response (normally repo returns 404 today)
const httpClient = vi.fn().mockResolvedValue({ ok: true, status: 200, body: "would-be-tarball-bytes" });
const svc = new PluginVendorService({
vendoredAssetsDir: "/asset-root",
userPluginsDir: "/home/test/.openrig/plugins",
fs,
httpClient,
logger: vi.fn(),
});
await svc.attemptAutoFetch("openrig-core");
// User plugin content unchanged — v0 doesn't extract/install on 200
expect(fs._store[initialUserPlugin]).toBe(initialContent);
// No .version file written either
expect(fs._store["/home/test/.openrig/plugins/openrig-core/.version"]).toBeUndefined();
});
});
describe("PluginVendorService — ensureLatest orchestration", () => {