Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions evidence/2026-09-22-plugin-0.4.0-release.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Plugin 0.4.0 publication

Observed September 22, 2026 in America/Chicago; provider timestamps fall on September 23 UTC.

Protected tag `claude-v0.4.0` selected Skills `5f544bff149173a249899d2b5dfd403057cc5a30` and published
`@firstdraft.com/claude-code@0.4.0` directly to `latest` through
[GitHub trusted publishing](https://github.com/firstdraft/skills/actions/runs/35808094004). The package bundles CLI
`0.4.0` from `a555f8d39862109b8c28b392c0439470e88f4ba8`; the workflow matched all 27 CLI files to its published package.

The registry plugin's SHA-256 is `7f796017074ecbfd5a5459f7686a615f53dbb3c95525ca2594601128e706748d`, matching the
selected compatibility declaration and locally packed candidate. Public installation and npm signature/attestation
verification passed. Both packages' `latest` tags selected `0.4.0`; their `next` tags remained `0.3.0`.

Catalog `9c1774c7094f20d76248dfec86a09857be29256f` selected the published plugin after publication. Its
[selection-only CI](https://github.com/firstdraft/skills/actions/runs/35808399252) passed. This does not establish
refresh of an existing agent installation or a new authenticated agent session.

The packed candidate's CLI compiled the existing reviewed Reading List Plan against deployed service `2bfdf6bf`.
Zero-flag Compilation wrote 360 files into the local folder and preserved the planning state under
`.firstdraft/design/`. Generated setup, Rails boot, a browser write, and a local source edit followed by refresh
passed. The analysis warning and two known gaps remained disclosed. The smoke used no Codespace, GitHub Publication,
native build, tunnel, or Revyl device. Its task-only service token was revoked and local processes were stopped.

[Drawing Board PR #49](https://github.com/firstdraft/drawing-board/pull/49) merged the released tooling pins after
publication. Its container check and prebuild establish fallback availability, not a fresh Codespace journey.
Earlier source and journey records remain observations of their own revisions and package bytes.
1 change: 1 addition & 0 deletions evidence/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ The source/public split observed at the start of this documentation change is ca

| Record | Observed boundary |
|---|---|
| [`2026-09-22-plugin-0.4.0-release.md`](2026-09-22-plugin-0.4.0-release.md) | GitHub publication directly to latest, exact registry bytes and provenance, catalog selection, and one local compile-and-boot smoke |
| [`2026-09-22-npm-promotion-retirement.md`](2026-09-22-npm-promotion-retirement.md) | Revoked the promotion token, removed its GitHub secret and environment, disabled the legacy workflow, and restored the CLI's restrictive publishing policy while preserving GitHub trusted publishing |
| [`2026-09-15-shared-plugin-0.2.4-default-promotion.md`](2026-09-15-shared-plugin-0.2.4-default-promotion.md) | Protected-tag promotion, one plugin write with bounded stale-read reconciliation, and independent final tags/archive hashes; [machine receipt](2026-09-15-shared-plugin-0.2.4-default-promotion.json) |
| [`2026-09-15-shared-plugin-0.2.4-publication.md`](2026-09-15-shared-plugin-0.2.4-publication.md) | Protected publication, delayed registry visibility, verified provenance, exact registry-package adapters, and observed staging readiness before catalog/default promotion; [machine receipt](2026-09-15-shared-plugin-0.2.4-publication.json) |
Expand Down
16 changes: 13 additions & 3 deletions test/plugin-release-order.test.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import assert from "node:assert/strict";
import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
import { fileURLToPath } from "node:url";
import { tmpdir } from "node:os";
import path from "node:path";
import test from "node:test";
Expand Down Expand Up @@ -149,11 +148,22 @@ test("prospective release order rejects incoherent current identities", () => {
);
});

test("unpublished candidate reconciliation reads npm, fetched tags, and the catalog", async () => {
test("unpublished candidate reconciliation reads npm, fetched tags, and the catalog", async (t) => {
const root = await mkdtemp(path.join(tmpdir(), "firstdraft-unpublished-candidate-"));
t.after(() => rm(root, { force: true, recursive: true }));
await mkdir(path.join(root, "release"));
await mkdir(path.join(root, ".claude-plugin"));
await writeFile(path.join(root, "release", "compatibility.json"), JSON.stringify({
version: "0.4.0",
plugin_source: { package: "@firstdraft.com/claude-code" },
}));
await writeFile(path.join(root, ".claude-plugin", "marketplace.json"), JSON.stringify({
plugins: [{ version: "0.2.5", source: { package: "@firstdraft.com/claude-code" } }],
}));
const invocations = [];
const result = await checkPluginReleaseOrder({
requireCurrentTag: false,
root: fileURLToPath(new URL("../", import.meta.url)),
root,
spawn(command, arguments_, options) {
invocations.push([command, arguments_, options]);
if (command === "git") {
Expand Down
Loading