From 4a80aba951a47401caf88b4e1fcd0284b437ff0f Mon Sep 17 00:00:00 2001 From: Iko Date: Tue, 6 Oct 2026 08:54:40 +0700 Subject: [PATCH 1/2] fix(ci): use the real labeler input id so stale labels are actually removed labeler.yml passed 'syncLabels', but the action's input id is 'sync-labels'. The runner logs "Unexpected input(s) 'syncLabels'" and the action falls back to its declared default (off), so labels were never removed on synchronize despite the step comment promising it. Audit of every with: key against each action's declared inputs (fetched per-pin from the action repos) found this as the only mismatch in the repo. Evidence: run 37394726141's log records the ignored input. Both v5 and the v7 landed in #69 declare the kebab-case id. --- .github/labeler.yml | 2 +- .github/workflows/labeler.yml | 6 +++++- CHANGELOG.md | 2 ++ CONTRIBUTING.md | 4 +++- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/.github/labeler.yml b/.github/labeler.yml index eec4e45..059dd6d 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -1,4 +1,4 @@ -# Path-based PR labels (actions/labeler v5). +# Path-based PR labels (actions/labeler v7). # Labels must exist in the repo before this matches — run # .github/workflows/labels-bootstrap.yml once after publishing to create them. # diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index 18e6761..c813aa8 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -23,4 +23,8 @@ jobs: configuration-path: .github/labeler.yml # Keep labels accurate as the PR evolves: stale labels are removed # on synchronize, not just added. - syncLabels: true + # NOTE: the input id is kebab-case. `syncLabels` is silently ignored - + # the runner logs "Unexpected input(s) 'syncLabels'" and the action + # falls back to its default (off), which is why stale labels were + # never actually removed until this was corrected. + sync-labels: true diff --git a/CHANGELOG.md b/CHANGELOG.md index f678367..734379a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,8 @@ All notable changes to the pstack-hermes port tooling will be documented in this - Docs / agent policy (Phase A, no package rebuild): `AGENTS.md` and `docs/USING.md` codify the stock-skills write surface — Hermes self-improvement (`skill_manage` / learning) targets local skills, skill taps, or a dist fork, not stock plugin skills. Stack forge freeze: **Graphite (`gt`) default**, **GitHub (`gh`) fallback**, **GitLab (`glab`) halted**. README Known limitations aligned (was incorrectly describing Graphite as optional-only). ### Fixed +- Label sync never ran (found while auditing every `with:` key against each action's declared inputs - the only such mismatch in the repo). `labeler.yml` passed `syncLabels: true`, but the input id is `sync-labels`: the runner logs `Unexpected input(s) 'syncLabels'` and the action falls back to its declared default (off), so stale labels were never removed on `synchronize` despite the step comment promising exactly that. Corrected to `sync-labels` (kebab-case; both v5 and the v7 that #69 landed declare it). Evidence: run 37394726141's log records the ignored input verbatim. +- `.github/actions/build-package` was outside dependabot's scan. The root `github-actions` entry covers `.github/workflows` plus a repo-root `action.yml`, not `.github/actions/*/action.yml` - observed when #69's setup-uv bump updated every workflow and skipped the shared action, leaving its pin behind and on a path to silent rot, the exact failure mode `dependabot.yml` exists to prevent (AGENTS.md: pins are "bumped by dependabot, not by hand"). Added a directory-scoped entry (the `actions/github-script` pattern) and caught the pin up to the SHA the workflows now use. - CI concurrency, from the manual Macroscope review of PR #67: `cancel-in-progress: false` alone did not make the "main runs stay whole" claim true. By default only one run may be *pending* per concurrency group and a newer pending run cancels the older one, so two merges in quick succession could cancel a queued main run before it ever started and the intermediate commit would skip `verify-determinism`. Non-PR runs now take a per-run group (`github.run_id`); semantics verified against GitHub's concurrency documentation. - Drift watchers (High), from the same review: moving the issue upsert into its own composite step silently dropped its guard. The check step's no-drift `exit 0`s end only that step, so the upsert still ran with `$RUNNER_TEMP/drift-body.md` absent and `gh issue comment/create --body-file` failed - the workflow would fail on the common no-drift path (latent today, because upstream drift keeps the body-writing path active; it would start failing the week after a re-pin). Both watchers now emit `drift=true` from the check step only on the path that also writes the body, and the upsert step is conditioned on it; pinned for both watchers by `tools/tests/test_workflow_review_guards.py`. - Drift watchers: the "not creating a possible duplicate" guard could never fire. `existing="$(gh ... || lookup_status=$?)"` set the variable inside the subshell, so the parent always saw the initial 0; when `gh issue list` failed, the workflow proceeded with an empty result and CREATED a duplicate tracking issue - the exact failure the guard's message claims to prevent. Reproduced in bash before fixing; shellcheck SC2030/SC2031 flagged it once the shellcheck gate existed. The upsert now lives in the shared `drift-issue-upsert` action with the status captured outside the substitution, and one jq form for both callers. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2bc980c..a224af8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -104,7 +104,9 @@ one has already caught (or would have caught) a real defect here. - **Every action is pinned to a full commit SHA** with a trailing `# vN` comment. `dependabot.yml` keeps them current: the weekly `github-actions` group PR updates both the SHA and the comment. Review SHA bumps like any - dependency change - the usual CI gates run on the PR. + dependency change - the usual CI gates run on the PR. The root entry does + **not** cover `.github/actions/*/action.yml`, so each composite action with + its own `uses:` needs a directory-scoped entry there. - **`UPSTREAM_PIN` moves in lock-step.** It is declared in `ci.yml`, `release.yml`, `publish-plugin.yml` and `upstream-drift-watch.yml`; `tools/check_pins.py` fails CI when any of the four is missing, duplicated, From 79968b7868bc476b90ddf911ff75bc44c2ea59f2 Mon Sep 17 00:00:00 2001 From: Iko Date: Tue, 6 Oct 2026 08:54:46 +0700 Subject: [PATCH 2/2] fix(ci): give composite actions a dependabot entry; catch the shared action's pin up The root github-actions entry covers .github/workflows plus a repo-root action.yml, not .github/actions/*/action.yml. Observed live: #69's setup-uv bump updated every workflow and skipped .github/actions/build-package, leaving its pin behind and on a path to silent rot - the failure mode dependabot.yml exists to prevent. Adds a directory-scoped entry (actions/github-script pattern) and aligns the pin to the SHA the workflows now use. --- .github/actions/build-package/action.yml | 2 +- .github/dependabot.yml | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/.github/actions/build-package/action.yml b/.github/actions/build-package/action.yml index 59e1fd1..5e38aea 100644 --- a/.github/actions/build-package/action.yml +++ b/.github/actions/build-package/action.yml @@ -49,7 +49,7 @@ runs: run: echo "SOURCE_DATE_EPOCH=$(git log -1 --format=%ct)" >> "$GITHUB_ENV" - name: Set up uv - uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10 + uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10 with: enable-cache: true diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 0ad9f69..fb51530 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -22,6 +22,18 @@ updates: actions: patterns: ["*"] + # Composite actions need their own entry. The root entry above covers + # .github/workflows plus a repo-root action.yml, but NOT + # .github/actions/*/action.yml - observed live: the setup-uv bump landed in + # every workflow and skipped .github/actions/build-package, leaving that pin + # to rot silently. Directory-scoped entries are the documented pattern + # (cf. actions/github-script). + - package-ecosystem: "github-actions" + directory: "/.github/actions/build-package" + schedule: + interval: "weekly" + day: "monday" + # pyproject.toml + uv.lock (the tooling venv: pyyaml, pytest, ruff, # actionlint-py, shellcheck-py). - package-ecosystem: "uv"