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
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ real interface and feature state
Pin Direct as a development dependency:

```sh
bun add --dev @hraness/direct@0.7.16
bun add --dev @hraness/direct@0.7.17
# or
npm install --save-dev @hraness/direct@0.7.16
npm install --save-dev @hraness/direct@0.7.17
```

Keep Direct in `devDependencies`. A production entry must not import Direct,
Expand All @@ -58,7 +58,7 @@ composition. It requires Git and Bun 1.3.14, then downloads the source and its
development dependencies:

```sh
git clone --branch v0.7.16 --depth 1 https://github.com/hraness/direct.git
git clone --branch v0.7.17 --depth 1 https://github.com/hraness/direct.git
cd direct
bun install --frozen-lockfile --ignore-scripts
bun run example:direct
Expand Down Expand Up @@ -132,9 +132,9 @@ claim separate as `direct` evidence.
Install Direct's single bundled skill from the public repository:

```sh
npx skills add hraness/direct#v0.7.16
npx skills add hraness/direct#v0.7.17
# or
bunx skills add hraness/direct#v0.7.16
bunx skills add hraness/direct#v0.7.17
```

The skill is invoked as `$direct`. It routes installation, adoption, and
Expand All @@ -148,7 +148,7 @@ Copy this prompt into Codex, Claude Code, or another coding agent:

```text
Use $direct to install hraness/direct from
the npm registry at the exact 0.7.16 version. Follow the repository README, add
the npm registry at the exact 0.7.17 version. Follow the repository README, add
`@hraness/direct` to devDependencies only, and verify that the production
dependency graph excludes Direct. Do not add a fixture composition until I
ask.
Expand All @@ -164,7 +164,7 @@ Pin the public npm package to an exact immutable version:
```json
{
"devDependencies": {
"@hraness/direct": "0.7.16"
"@hraness/direct": "0.7.17"
}
}
```
Expand All @@ -186,8 +186,8 @@ quiescence, coverage claims, cleanup, and emitted production boundaries. The
package smoke test keeps that future packaged copy byte-identical to the
repository skill.

Prefer `npx skills add hraness/direct#v0.7.16` or
`bunx skills add hraness/direct#v0.7.16` for runner discovery. You can also copy
Prefer `npx skills add hraness/direct#v0.7.17` or
`bunx skills add hraness/direct#v0.7.17` for runner discovery. You can also copy
or link that one skill directory into a runner's configured location, then
invoke `$direct`. Package installation leaves the skill inert: it does not run
a `postinstall` hook or edit repository or user configuration.
Expand Down
2 changes: 1 addition & 1 deletion dist/tooling/bombadil.js
Original file line number Diff line number Diff line change
Expand Up @@ -1469,8 +1469,8 @@ class LiveChromeDownloadRenameRetry extends Error {
completion;
constructor(completion) {
super("Chrome download renamed during live artifact inspection");
this.completion = completion;
this.name = "LiveChromeDownloadRenameRetry";
this.completion = completion;
}
}

Expand Down
4 changes: 2 additions & 2 deletions docs/adoption.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
Add Direct after identifying the product behavior and external boundary under review. Do not begin by designing fixtures around a provider SDK.

The repository carries one `$direct` Agent Skill under `skills/direct`.
Install it with `npx skills add hraness/direct#v0.7.16` or
`bunx skills add hraness/direct#v0.7.16`, or copy that directory into the runner's
Install it with `npx skills add hraness/direct#v0.7.17` or
`bunx skills add hraness/direct#v0.7.17`, or copy that directory into the runner's
discovery location. Invoke `$direct` for installation, adoption, and
verification work. Skill installation is independent from library package
installation and does not activate Direct in a product.
Expand Down
6 changes: 3 additions & 3 deletions docs/publishing.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ cookie, one-time password, recovery code, or write token to GitHub.
`v<package.json version>`.

```sh
git tag v0.7.16
git push origin refs/tags/v0.7.16
git tag v0.7.17
git push origin refs/tags/v0.7.17
```

3. Wait for **Release**. The workflow runs these boundaries in order:
Expand Down Expand Up @@ -123,7 +123,7 @@ Merge the fix to `main`, then dispatch **Release** from current `main` with
the exact existing stable tag:

```sh
gh workflow run release.yml --ref main -f tag=v0.7.16
gh workflow run release.yml --ref main -f tag=v0.7.17
```

The recovery path skips npm publication. It accepts only the newest stable
Expand Down
4 changes: 2 additions & 2 deletions docs/verification.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ definition with `parseDefinitionCoverageSnapshot` so a valid but stale catalog
cannot be mistaken for the catalog under review.

The repository carries one `$direct` Agent Skill under `skills/direct`.
Install it with `npx skills add hraness/direct#v0.7.16` or
`bunx skills add hraness/direct#v0.7.16`, or copy that directory into the runner's
Install it with `npx skills add hraness/direct#v0.7.17` or
`bunx skills add hraness/direct#v0.7.17`, or copy that directory into the runner's
discovery location. Invoke `$direct` for the workflow below. The skill is
independent from library package installation and structures the audit; it
does not turn deterministic evidence into proof of a substituted live system.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@hraness/direct",
"version": "0.7.16",
"version": "0.7.17",
"description": "A TypeScript harness for deterministic frontend testing and development with repeatable scenarios, local fixtures, and browser verification for coding agents.",
"license": "MIT",
"type": "module",
Expand Down
26 changes: 13 additions & 13 deletions scripts/npm-publish-workflow.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ import { isUtf8ByteLengthAtMost } from "./utf8-byte-boundary.js";
readonly version?: unknown;
};
expect(manifest).toEqual(expect.objectContaining({
version: "0.7.16",
version: "0.7.17",
description: "A TypeScript harness for deterministic frontend testing and development with repeatable scenarios, local fixtures, and browser verification for coding agents.",
keywords: [
"frontend-development",
Expand Down Expand Up @@ -567,7 +567,7 @@ import { isUtf8ByteLengthAtMost } from "./utf8-byte-boundary.js";
const binaryDirectory = join(directory, "bin");
const commandLog = join(directory, "commands.log");
const publishMarker = join(directory, "published.txt");
const tarball = join(directory, "hraness-direct-0.7.16.tgz");
const tarball = join(directory, "hraness-direct-0.7.17.tgz");
const metadata = join(directory, "npm-pack.json");
const digest = join(directory, "npm-package.sha256");
const sourceSha = "b".repeat(40);
Expand All @@ -585,7 +585,7 @@ import { isUtf8ByteLengthAtMost } from "./utf8-byte-boundary.js";
writeFile(metadata, "reviewed metadata fixture\n", "utf8"),
writeFile(digest, "reviewed digest fixture\n", "utf8"),
]);
await writeFile(gitStub, `#!/bin/bash\nset -euo pipefail\nprintf 'git %s\\n' "$*" >> "$COMMAND_LOG"\ncase "$*" in\n *"rev-parse refs/heads/main"*) printf '%s\\n' "$DEFAULT_SHA" ;;\n *"rev-parse refs/tags/v0.7.16^{commit}"*) printf '%s\\n' "$TAG_SHA" ;;\n *"merge-base --is-ancestor"*) [[ "$ANCESTRY_STATE" == ancestor ]] ;;\n *"tag --list v*"*) printf '%s\\n' "$REMOTE_TAGS" ;;\nesac\n`, "utf8");
await writeFile(gitStub, `#!/bin/bash\nset -euo pipefail\nprintf 'git %s\\n' "$*" >> "$COMMAND_LOG"\ncase "$*" in\n *"rev-parse refs/heads/main"*) printf '%s\\n' "$DEFAULT_SHA" ;;\n *"rev-parse refs/tags/v0.7.17^{commit}"*) printf '%s\\n' "$TAG_SHA" ;;\n *"merge-base --is-ancestor"*) [[ "$ANCESTRY_STATE" == ancestor ]] ;;\n *"tag --list v*"*) printf '%s\\n' "$REMOTE_TAGS" ;;\nesac\n`, "utf8");
await writeFile(sha256Stub, `#!/bin/bash\nset -euo pipefail\nprintf 'sha256sum %s\\n' "$*" >> "$COMMAND_LOG"\ncase "$1" in\n "$TARBALL") value="$EXPECTED_ARCHIVE_SHA256" ;;\n "$METADATA") value="$EXPECTED_METADATA_SHA256" ;;\n "$DIGEST") value="$EXPECTED_DIGEST_SHA256" ;;\n *) echo "unexpected hash target: $1" >&2; exit 1 ;;\nesac\nprintf '%s %s\\n' "$value" "$1"\n`, "utf8");
await writeFile(npmStub, `#!/bin/bash\nset -euo pipefail\nprintf 'npm %s\\n' "$*" >> "$COMMAND_LOG"\nif [[ "\${1-}" == view ]]; then\n printf '%s\\n' "$PUBLISHED_VERSIONS_JSON"\n exit 0\nfi\nprintf 'published\\n' > "$PUBLISH_MARKER"\n`, "utf8");
await Promise.all([chmod(gitStub, 0o755), chmod(npmStub, 0o755), chmod(sha256Stub, 0o755)]);
Expand All @@ -601,15 +601,15 @@ import { isUtf8ByteLengthAtMost } from "./utf8-byte-boundary.js";
EXPECTED_DIGEST_SHA256: digestSha256,
EXPECTED_METADATA_SHA256: metadataSha256,
EXPECTED_SOURCE_SHA: sourceSha,
EXPECTED_VERSION: "0.7.16",
GITHUB_REF: "refs/tags/v0.7.16",
EXPECTED_VERSION: "0.7.17",
GITHUB_REF: "refs/tags/v0.7.17",
GITHUB_REPOSITORY: "hraness/direct",
GITHUB_SHA: sourceSha,
METADATA: metadata,
PATH: `${binaryDirectory}:${process.env.PATH ?? ""}`,
PUBLISHED_VERSIONS_JSON: '["0.7.4","0.7.5","0.7.6","0.7.7","0.7.8","0.7.9","0.7.10","0.7.11","0.7.12","0.7.13","0.7.14","0.7.15"]',
PUBLISHED_VERSIONS_JSON: '["0.7.4","0.7.5","0.7.6","0.7.7","0.7.8","0.7.9","0.7.10","0.7.11","0.7.12","0.7.13","0.7.14","0.7.15","0.7.16"]',
PUBLISH_MARKER: publishMarker,
REMOTE_TAGS: "v0.7.4\nv0.7.5\nv0.7.6\nv0.7.7\nv0.7.8\nv0.7.9\nv0.7.10\nv0.7.11\nv0.7.12\nv0.7.13\nv0.7.14\nv0.7.15\nv0.7.16",
REMOTE_TAGS: "v0.7.4\nv0.7.5\nv0.7.6\nv0.7.7\nv0.7.8\nv0.7.9\nv0.7.10\nv0.7.11\nv0.7.12\nv0.7.13\nv0.7.14\nv0.7.15\nv0.7.16\nv0.7.17",
RUNNER_TEMP: directory,
TAG_SHA: sourceSha,
TARBALL: tarball,
Expand Down Expand Up @@ -640,7 +640,7 @@ import { isUtf8ByteLengthAtMost } from "./utf8-byte-boundary.js";
});
expect(moved.exitCode).not.toBe(0);
expect(`${moved.stdout}${moved.stderr}`).toContain(
"Tag v0.7.16 changed after artifact verification",
"Tag v0.7.17 changed after artifact verification",
);
expect(await Bun.file(publishMarker).exists()).toBe(false);

Expand All @@ -651,30 +651,30 @@ import { isUtf8ByteLengthAtMost } from "./utf8-byte-boundary.js";
});
expect(detached.exitCode).not.toBe(0);
expect(`${detached.stdout}${detached.stderr}`).toContain(
"Tag v0.7.16 is no longer reachable from main",
"Tag v0.7.17 is no longer reachable from main",
);
expect(await Bun.file(publishMarker).exists()).toBe(false);

await rm(commandLog, { force: true });
const superseded = await runWorkflowScript(script, {
...baseEnvironment,
REMOTE_TAGS: "v0.7.4\nv0.7.5\nv0.7.6\nv0.7.7\nv0.7.8\nv0.7.9\nv0.7.10\nv0.7.11\nv0.7.12\nv0.7.13\nv0.7.14\nv0.7.15\nv0.7.16\nv0.7.17",
REMOTE_TAGS: "v0.7.4\nv0.7.5\nv0.7.6\nv0.7.7\nv0.7.8\nv0.7.9\nv0.7.10\nv0.7.11\nv0.7.12\nv0.7.13\nv0.7.14\nv0.7.15\nv0.7.16\nv0.7.17\nv0.7.18",
});
expect(superseded.exitCode).not.toBe(0);
expect(`${superseded.stdout}${superseded.stderr}`).toContain(
"Tag v0.7.16 is not the newest stable tag v0.7.17",
"Tag v0.7.17 is not the newest stable tag v0.7.18",
);
expect(await readFile(commandLog, "utf8")).not.toContain("npm publish");
expect(await Bun.file(publishMarker).exists()).toBe(false);

await rm(commandLog, { force: true });
const staleVersion = await runWorkflowScript(script, {
...baseEnvironment,
PUBLISHED_VERSIONS_JSON: '["0.7.4","0.7.17"]',
PUBLISHED_VERSIONS_JSON: '["0.7.4","0.7.18"]',
});
expect(staleVersion.exitCode).not.toBe(0);
expect(`${staleVersion.stdout}${staleVersion.stderr}`).toContain(
"@hraness/direct@0.7.16 is not newer than published stable 0.7.17",
"@hraness/direct@0.7.17 is not newer than published stable 0.7.18",
);
expect(await Bun.file(publishMarker).exists()).toBe(false);

Expand Down
10 changes: 5 additions & 5 deletions skills/direct/references/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,17 @@ global `direct` CLI.
For a new installation, pin the reviewed public release:

```sh
bun add --dev @hraness/direct@0.7.16
bun add --dev @hraness/direct@0.7.17
# or, in an npm project
npm install --save-dev @hraness/direct@0.7.16
npm install --save-dev @hraness/direct@0.7.17
```

The equivalent manifest entry is:

```json
{
"devDependencies": {
"@hraness/direct": "0.7.16"
"@hraness/direct": "0.7.17"
}
}
```
Expand All @@ -43,8 +43,8 @@ If the task starts with skill installation rather than a loaded skill, install
the single repository skill with either command:

```sh
npx skills add hraness/direct#v0.7.16
bunx skills add hraness/direct#v0.7.16
npx skills add hraness/direct#v0.7.17
bunx skills add hraness/direct#v0.7.17
```

Restart or reload the agent runner if it does not discover newly installed
Expand Down
19 changes: 10 additions & 9 deletions src/tooling/bombadil-runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -813,17 +813,18 @@ class BombadilArtifactPolicyError extends Error {
}

class LiveChromeDownloadRenameRetry extends Error {
public constructor(
public readonly completion: Readonly<{
device: bigint;
inode: bigint;
runId: string;
size: number;
unobserved: boolean;
}>,
) {
public readonly completion: Readonly<{
device: bigint;
inode: bigint;
runId: string;
size: number;
unobserved: boolean;
}>;

public constructor(completion: LiveChromeDownloadRenameRetry["completion"]) {
super("Chrome download renamed during live artifact inspection");
this.name = "LiveChromeDownloadRenameRetry";
this.completion = completion;
}
}

Expand Down
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"noUnusedParameters": true,
"useUnknownInCatchVariables": true,
"allowImportingTsExtensions": true,
"erasableSyntaxOnly": true,
"isolatedModules": true,
"skipLibCheck": true,
"noEmit": true,
Expand Down