@bigknoxy/hashpilot 4.8.1 → 4.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bun.lock +1004 -0
- package/docs/decisions/README.md +45 -0
- package/package.json +3 -2
- package/scripts/install.sh +29 -15
package/docs/decisions/README.md
CHANGED
|
@@ -52,3 +52,48 @@ Format:
|
|
|
52
52
|
- **Decision:** `runZg` returns a `ZgProcessResult` with separate `timedOut` and `spawnError` fields. The caller checks spawn errors first, then timeouts, then non-zero exits, then parses output.
|
|
53
53
|
- **Alternatives considered:** (1) throw on spawn error — rejected: the search command should return a structured error, not crash. (2) single `error` field — rejected: timeout and spawn-failure require different recovery paths.
|
|
54
54
|
- **Consequences:** `SEARCH_FAILED` errors now include actionable diagnostics (`spawnError`, `timedOut`, or `stderr`). Exit-1 with no stderr (ripgrep-style "no matches") returns empty hits, not an error.
|
|
55
|
+
|
|
56
|
+
## D005: release.yml keeps GH_TOKEN (PAT) — GITHUB_TOKEN can't trigger downstream workflows
|
|
57
|
+
|
|
58
|
+
- **Date:** 2026-09-05
|
|
59
|
+
- **PR:** #199
|
|
60
|
+
- **Context:** Audit finding B70 recommended switching all `secrets.GH_TOKEN` references to `secrets.GITHUB_TOKEN`. The default `GITHUB_TOKEN` is minted per-run, scoped, and auto-expires — strictly better for security. However, GitHub's design prevents `GITHUB_TOKEN` from triggering downstream workflows (to avoid recursive runs). semantic-release's `prepare` phase pushes a version-bump commit to `main`, which must trigger the `gh-pages` workflow. With `GITHUB_TOKEN`, that push is invisible to GitHub's event system.
|
|
61
|
+
- **Decision:** Keep `GH_TOKEN` in `release.yml` (lines 110, 137). Switch `gh-pages.yml` to `GITHUB_TOKEN` since it doesn't need to trigger further workflows.
|
|
62
|
+
- **Alternatives considered:** (1) Switch everything to `GITHUB_TOKEN` — rejected: gh-pages deploy would never trigger after a release. (2) Use `workflow_dispatch` trigger instead — rejected: adds latency and requires a separate orchestration step. (3) Use `workflow_run` trigger — rejected: only fires after the triggering workflow completes, which is too late for the current architecture.
|
|
63
|
+
- **Consequences:** The release workflow retains a PAT with broader scope than ideal. Mitigation: the PAT should be scoped to the minimum permissions (just `contents: write` for the repo). Regular rotation recommended.
|
|
64
|
+
|
|
65
|
+
## D006: Pin third-party actions by commit SHA, not tag
|
|
66
|
+
|
|
67
|
+
- **Date:** 2026-09-05
|
|
68
|
+
- **PR:** #199
|
|
69
|
+
- **Context:** Audit finding B71 flagged `peaceiris/actions-gh-pages@v4` as a floating tag. The action is handed a write-capable token. A compromised `v4` tag could push malicious content to `gh-pages`.
|
|
70
|
+
- **Decision:** Pin `peaceiris/actions-gh-pages` to commit SHA `329bcc8f12caed2cefe5a5b80781499a6f3b361b` (the `v4` tag at time of pinning). First-party `actions/*` actions (checkout, setup-node, setup-bun) remain on major-version tags — these are GitHub-maintained with strong supply-chain controls and the SHA would need updating on every minor/patch bump.
|
|
71
|
+
- **Alternatives considered:** (1) Pin all actions by SHA — rejected: first-party actions update frequently and pinning creates maintenance burden with no meaningful security gain (GitHub controls both the actions and the runner). (2) Use `actions/checkout` pinned — not done, same reason.
|
|
72
|
+
- **Consequences:** Third-party action pinned; any tag mutation is blocked. First-party actions on tags will auto-update within major versions. Record the SHA in the comment for traceability.
|
|
73
|
+
|
|
74
|
+
## D007: Pin agent-browser to exact version in CI
|
|
75
|
+
|
|
76
|
+
- **Date:** 2026-09-05
|
|
77
|
+
- **PR:** #199
|
|
78
|
+
- **Context:** Audit finding B69 flagged `npm install -g agent-browser` with no version pin. The job holds `contents: write`. A compromised `agent-browser` package would execute with write access to `gh-pages`.
|
|
79
|
+
- **Decision:** Pin to `agent-browser@0.36.0` (current latest). Add comment documenting the pin rationale.
|
|
80
|
+
- **Alternatives considered:** (1) Remove agent-browser entirely — rejected: it provides real deploy verification. (2) Add npm integrity check — rejected: npm's `--ignore-scripts` would break agent-browser's `install` step; checksum verification requires custom tooling. Version pin + review on updates is the practical baseline.
|
|
81
|
+
- **Consequences:** Supply-chain attack window reduced from "any future version" to "only 0.36.0". Version bumps must be deliberate and reviewed.
|
|
82
|
+
|
|
83
|
+
## D008: Ship bun.lock in npm package for frozen-lockfile installs
|
|
84
|
+
|
|
85
|
+
- **Date:** 2026-09-05
|
|
86
|
+
- **PR:** #199
|
|
87
|
+
- **Context:** Audit finding B79 noted that npm-sourced installs resolve dependencies fresh (`bun install --production`) instead of using `--frozen-lockfile`, since the npm tarball didn't include `bun.lock`. This means transitive deps could differ from what CI tested.
|
|
88
|
+
- **Decision:** Add `bun.lock` to `package.json`'s `files` array so it ships in the npm tarball. The existing `install.sh` logic already uses `--frozen-lockfile` when `bun.lock` is present.
|
|
89
|
+
- **Alternatives considered:** (1) Generate a lockfile during install — rejected: defeats the purpose of pinning. (2) Keep `bun.lock` out and accept fresh resolution — rejected: supply-chain pinning gap.
|
|
90
|
+
- **Consequences:** npm-installed packages now include `bun.lock` and install with `--frozen-lockfile`. The npm package size increases slightly. The `else` branch in `install.sh` (lines 423-432) becomes unreachable for current npm installs but is kept as a safe fallback.
|
|
91
|
+
|
|
92
|
+
## D010: npm-sourced installs with a shipped bun.lock use --frozen-lockfile --production
|
|
93
|
+
|
|
94
|
+
- **Date:** 2026-09-06
|
|
95
|
+
- **PR:** hotfix (after v4.8.2)
|
|
96
|
+
- **Context:** v4.8.2 shipped broken for the **default npm install path**. D007 (#199) added `bun.lock` to the npm package's `files`; the dependency-mode guard from #194 treated `NPM_INSTALLED=true && bun.lock present` as a fatal ("refusing to guess which dependency mode is correct"). D007 made that guard's fire-branch the *normal* case, so every fresh npm install of v4.8.2 aborted before installing dependencies. The bug passed CI because smoke installs from `@latest` npm — main's run predated the semantic-release publish and tested 4.8.1 (no lockfile); the breakage only surfaced once v4.8.2 reached the registry.
|
|
97
|
+
- **Decision:** The dependency-mode decision now keys off `$NPM_INSTALLED`, not a bare lockfile-presence check. npm source + shipped lock → `bun install --frozen-lockfile --production` (pinned, devDeps skipped). npm source, no lock → `--production` (legacy). git/local + lock → `--frozen-lockfile` (dev wants devDeps). git/local, no lock → hard error (unchanged).
|
|
98
|
+
- **Alternatives considered:** (1) Revert D007 (don't ship bun.lock) — rejected: pinning transitive deps is the correct supply-chain posture; the packaging was not the flaw, the mode-selector was. (2) Remove the #194 guard entirely and let the old `[ -f bun.lock ]` branch run plain `--frozen-lockfile` — rejected: that would pull devDependencies (semantic-release) into npm installs, breaking the smoke's devDep-exclusion assertion and bloating user installs.
|
|
99
|
+
- **Consequences:** npm-installed packages are pinned to the shipped lockfile while still skipping devDeps. **Coverage hole identified:** smoke's npm-path test installs `@latest` (published version), so an unpublished PR branch is never validated against its own packed tarball — add a version-consistency guard so "testing the wrong release" is loud, not silent.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bigknoxy/hashpilot",
|
|
3
|
-
"version": "4.8.
|
|
3
|
+
"version": "4.8.3",
|
|
4
4
|
"description": "HashPilot — Global Tool-Agnostic Structured Editing Core for Coding Agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
"docs/",
|
|
28
28
|
"LICENSE",
|
|
29
29
|
"package.json",
|
|
30
|
-
"tsconfig.json"
|
|
30
|
+
"tsconfig.json",
|
|
31
|
+
"bun.lock"
|
|
31
32
|
],
|
|
32
33
|
"repository": {
|
|
33
34
|
"type": "git",
|
package/scripts/install.sh
CHANGED
|
@@ -405,31 +405,45 @@ log "Installing dependencies..."
|
|
|
405
405
|
# (e.g. an npm extraction that somehow shipped a lockfile, or a git/local
|
|
406
406
|
# source that's missing one) fails loudly here instead of silently
|
|
407
407
|
# guessing.
|
|
408
|
-
if [ "$NPM_INSTALLED" = "true" ] && [ -f "$SOURCE_DIR/bun.lock" ]; then
|
|
409
|
-
err "npm-sourced install unexpectedly has a bun.lock — refusing to guess which dependency mode is correct"
|
|
410
|
-
exit 1
|
|
411
|
-
fi
|
|
412
408
|
if [ "$NPM_INSTALLED" = "false" ] && [ ! -f "$SOURCE_DIR/bun.lock" ]; then
|
|
413
409
|
err "Source is missing bun.lock and wasn't installed from npm — refusing to guess which dependency mode is correct"
|
|
414
410
|
err "(local-clone and --source installs are expected to have bun.lock, same as the git repo does)"
|
|
415
411
|
exit 1
|
|
416
412
|
fi
|
|
417
413
|
|
|
418
|
-
|
|
414
|
+
# Dependency mode decided here, not by a bare [ -f bun.lock ] presence check:
|
|
415
|
+
# - git/local source with bun.lock -> --frozen-lockfile (dev wants devDeps)
|
|
416
|
+
# - npm source with bun.lock (D007) -> --frozen-lockfile --production (pinned,
|
|
417
|
+
# but skip devDeps — the npm package lists them in package.json even though
|
|
418
|
+
# `files` excludes them; a plain --frozen-lockfile would pull semantic-release)
|
|
419
|
+
# - npm source without bun.lock -> --production (legacy, pre-D007)
|
|
420
|
+
if [ "$NPM_INSTALLED" = "true" ]; then
|
|
421
|
+
# npm always skips devDependencies. When the shipped lockfile is present
|
|
422
|
+
# (D007), pin to it too; otherwise resolve production deps fresh.
|
|
423
|
+
if [ -f "$SOURCE_DIR/bun.lock" ]; then
|
|
424
|
+
detail "bun.lock shipped (npm package) — installing pinned production dependencies"
|
|
425
|
+
cd "$TARGET_DIR/structured-editing"
|
|
426
|
+
bun install --frozen-lockfile --production 2>&1 | while IFS= read -r line; do detail "$line"; done
|
|
427
|
+
cd "$OLDPWD"
|
|
428
|
+
else
|
|
429
|
+
# The npm-published package.json still lists devDependencies (npm's
|
|
430
|
+
# `files` field controls which FILES ship, not which package.json fields
|
|
431
|
+
# do) — a plain `bun install` would resolve and install semantic-release,
|
|
432
|
+
# fast-check, and the rest of the dev toolchain for no reason on an end
|
|
433
|
+
# user's machine. --production skips them; the CLI never needs them.
|
|
434
|
+
detail "No bun.lock shipped (npm package install) — resolving production dependencies fresh"
|
|
435
|
+
rm -f "$TARGET_DIR/structured-editing/bun.lock"
|
|
436
|
+
cd "$TARGET_DIR/structured-editing"
|
|
437
|
+
bun install --production 2>&1 | while IFS= read -r line; do detail "$line"; done
|
|
438
|
+
cd "$OLDPWD"
|
|
439
|
+
fi
|
|
440
|
+
elif [ -f "$SOURCE_DIR/bun.lock" ]; then
|
|
419
441
|
cd "$TARGET_DIR/structured-editing"
|
|
420
442
|
bun install --frozen-lockfile 2>&1 | while IFS= read -r line; do detail "$line"; done
|
|
421
443
|
cd "$OLDPWD"
|
|
422
444
|
else
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
# do) — a plain `bun install` would resolve and install semantic-release,
|
|
426
|
-
# fast-check, and the rest of the dev toolchain for no reason on an end
|
|
427
|
-
# user's machine. --production skips them; the CLI never needs them.
|
|
428
|
-
detail "No bun.lock shipped (npm package install) — resolving production dependencies fresh"
|
|
429
|
-
rm -f "$TARGET_DIR/structured-editing/bun.lock"
|
|
430
|
-
cd "$TARGET_DIR/structured-editing"
|
|
431
|
-
bun install --production 2>&1 | while IFS= read -r line; do detail "$line"; done
|
|
432
|
-
cd "$OLDPWD"
|
|
445
|
+
err "Source has no bun.lock and was not installed from npm — nothing to pin against"
|
|
446
|
+
exit 1
|
|
433
447
|
fi
|
|
434
448
|
detail "Dependencies installed"
|
|
435
449
|
|