Skip to content

fix(ci): repair pre-existing main failures (source-tests + MegaLinter)#110

Merged
ChipWolf merged 15 commits into
mainfrom
fix/source-tests-bootstrap-private
Jun 15, 2026
Merged

fix(ci): repair pre-existing main failures (source-tests + MegaLinter)#110
ChipWolf merged 15 commits into
mainfrom
fix/source-tests-bootstrap-private

Conversation

@ChipWolf

@ChipWolf ChipWolf commented Jun 15, 2026

Copy link
Copy Markdown
Owner

Two checks have been red on main independently of any feature work. This PR repairs both so main (and PRs branched from it) go green. None of these failures relate to a feature change; they're linter/test-harness issues on recently-merged code.

1. source-tests (ubuntu) — brewfile.bats 8 & 9

run_onchange_after_bootstrap.sh.tmpl:47 reads .private, but the test renders via chezmoi execute-template --init, which doesn't promote the config template's [data] to top-level vars. The helper supplied codespaces but not private, so a fresh checkout (CI) died with map has no entry for key "private" while dev machines passed (key present in on-disk config data). The production template is correct (real apply always sets .private); only the isolated test render under-specified its data.

Fix: add "private":false to the bootstrap render's --override-data. Verified in an ubuntu:24.04 container w/ chezmoi 2.70.4: both bats tests ok.

2. MegaLinter — luacheck, stylua, shellcheck, devskim

All on recently-merged code (hammerspoon, agent-audit, consensus), not feature work:

  • luacheck (home/dot_hammerspoon/*.lua): "accessing undefined variable hs" — hs is the Hammerspoon runtime global; the watcher/tap/menubar are intentional non-local globals (kept to avoid GC). Fix: allow hs via LUA_LUACHECK_ARGUMENTS, declare the per-file globals with inline luacheck: globals directives.
  • stylua (same files): 2-space vs stylua's default (the repo has no stylua.toml). Fix: format with stylua defaults.
  • shellcheck (skills/agent-audit/audit.sh): SC2016 (literal $schema JSON key) and SC2012 (ls on controlled Cellar dirs) — both intentional. Fix: scoped shellcheck disable directives with reasons.
  • devskim (skills/consensus/resources/*.schema.json): DS137138 flags http://json-schema.org/draft-07/schema# as insecure, but that's the canonical draft-07 $schema identifier (must stay http://) — a genuine false positive. Fix: add DS137138 to .devskim.json IgnoreRuleIds.

Verified locally: luacheck 0/0, stylua --check clean, shellcheck --external-sources clean across all affected files. devskim is a config-only ignore (its SARIF showed only the four DS137138 false positives, no real findings); CI confirms.

Relationship to #109

PR #109 (AGENTS.md → skills refactor) is clean on its own merits; its red CI is inherited from these two pre-existing main failures. Once this merges and #109 picks up main, #109 goes green.

🤖 Generated with Claude Code

ChipWolf and others added 15 commits June 12, 2026 19:26
…tension

Replace the local-render approach (pi-request-dump.mjs) with a real wire
capture using the same Anthropic /v1/messages loopback as Claude Code.

How it works:
- audit_pi() writes a throwaway PI_CODING_AGENT_DIR containing:
  - lib/pi-loopback-ext.mjs  an ES module extension that overrides the
    built-in 'anthropic' provider baseUrl to http://127.0.0.1:$PORT
  - settings.json             loads the extension; dummy Anthropic model
  - auth.json (0600)          dummy API key so pi doesn't bail pre-request
- Starts claude-loopback.mjs (Anthropic messages format)
- Runs: PI_CODING_AGENT_DIR=... PI_AUDIT_LOOPBACK_PORT=... PI_OFFLINE=1
         ANTHROPIC_API_KEY=audit-dummy pi -p 'hi' --approve
- Captures the full /v1/messages body including the live extension stack
  output (<available_skills> block is now present when skills are installed)
- Uses claude_first_turn_chars for FIRST_* columns (Anthropic format)

SYS_* column is unchanged (pi-dump.mjs local render, no network).

Before: pi FIRST_CH ~4,969 (local render, no skills, no extension stack)
After:  pi FIRST_CH ~24,096 (wire capture, skills catalogue included)

Also update categorizePi in both categorize.mjs and breakdown-unified.mjs to
read the Anthropic wire format: system array -> systemText, span breakdown
now includes <available_skills> anchor, tool chars from req.tools array.
Uncommented yubico-authenticator from disabled packages list.
It will now be installed on macOS via brew bundle.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Bind Ctrl+1..Ctrl+5 to jump directly to the Nth Space on the focused
screen, including full-screen-app spaces that the native "Switch to
Desktop N" shortcuts cannot reach. Uses hs.spaces.spacesForScreen plus
hs.spaces.gotoSpace, which drives the Mission Control thumbnail button.

Installs Hammerspoon via the Homebrew cask (macOS only) and gates the
~/.hammerspoon config to darwin in .chezmoiignore. Config auto-reloads
via hs.pathwatcher.

One-time manual step: grant Hammerspoon Accessibility permission in
System Settings -> Privacy & Security -> Accessibility.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
macOS reserves Ctrl+1..Ctrl+N as Carbon hotkeys for "Switch to Desktop"
when N Mission Control user desktops exist, even when the System Settings
shortcut checkboxes are off. RegisterEventHotKey then rejects those combos
(error -9878), so hs.hotkey.bind silently failed for Ctrl+1/Ctrl+2 (two
user desktops here) while Ctrl+3..5 registered fine.

Replace the per-key hs.hotkey binds with a single hs.eventtap that reads
Ctrl+number from the event stream before hotkey dispatch, so all five keys
work uniformly and still reach full-screen spaces.

Also enable hs.ipc in init.lua so the running config can be queried from
the `hs` CLI (used to diagnose this).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a Hammerspoon section to the repo guide: use hs.eventtap (not
hs.hotkey.bind) for Ctrl+number Space switches because macOS reserves
Ctrl+1..Ctrl+N for Switch-to-Desktop and RegisterEventHotKey rejects
them (-9878); hs.spaces reaches full-screen spaces; hs.pathwatcher
auto-reload survives chezmoi writes; hs.ipc CLI for debugging;
Accessibility permission is a one-time manual grant.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Show the active Space's position (the same 1-based index Ctrl+1..Ctrl+5
use) as a menu bar badge via hs.menubar, updated on hs.spaces.watcher
events. The dropdown lists every Space (full-screen ones flagged, current
one checked) and clicking jumps to it.

The badge is recomputed from spacesForScreen + activeSpaceOnScreen (not
the watcher's deprecated space-number arg), deferred ~0.25s so it reads
the settled position after macOS finishes the transition and any
most-recent-use reordering.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Document the menu bar Space indicator (space_indicator.lua) and the macOS
mru-spaces default that reorders full-screen spaces, which makes position-
based Ctrl+N and the badge drift; record the defaults write to disable it
and the watcher settle-delay workaround.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add home/.chezmoiscripts/run_onchange_after_macos_defaults.sh.tmpl to set
`com.apple.dock mru-spaces -bool false` so macOS stops reordering Spaces
by most-recent-use. That keeps the Hammerspoon Ctrl+1..Ctrl+5 direct-Space
switches and the menu bar indicator pointing at consistent positions,
including full-screen-app spaces.

Darwin-guarded (renders empty elsewhere); run_onchange so it only re-runs
when the content changes; restarts the Dock only when it is running so it
is a no-op in headless/CI sessions.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the small circled-number badge with one dot per Space on the
focused screen, the active one filled (●) and the rest hollow (○), in
Mission Control order. More legible at a glance and shows position within
the full set of Spaces.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…empty

When Ctrl+N targets a position that does not exist yet (for example Ctrl+3
with only two Spaces), add a new empty desktop with hs.spaces.addSpaceToScreen
and switch to it instead of showing a "No Space N" alert. addSpaceToScreen
does not return the new id, so the new Space is found by diffing the Space
list before and after.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Match Komorebi's alt+number Workspace switches on Windows. On macOS
Option+number normally types ¡™£¢∞, but the event tap returns true to
swallow the keystroke before the input system inserts the character, so
the Space switches and nothing is typed (verified by reading a focused
TextEdit document after a synthetic ⌥1/⌥2: it stayed empty).

Update the spaces.lua and space_indicator.lua comments and the AGENTS.md
Hammerspoon section to reflect ⌥ and why the event tap is still required
(special-char swallowing, plus Ctrl+number being unbindable via hs.hotkey).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
source-tests has been red on main since the bootstrap onchange hash
landed: tests 8 and 9 (brewfile.bats) fail on ubuntu with
`map has no entry for key "private"` at run_onchange_after_bootstrap.sh.tmpl:47.

Cause: the render helper uses `chezmoi execute-template --init`, which does
not promote the config template's [data] to top-level template vars, so each
key the template reads must come via --override-data. The helper passed
`codespaces` but not `private`; the bootstrap script gates a block on
`.private` (derived from ~/.private in .chezmoi.toml.tmpl), so a fresh
checkout (CI) errors while a dev machine passes because the key exists in
on-disk config data. The production template is correct (real apply always
sets .private); only the isolated test render under-specified its data.

Reproduced and verified in an ubuntu container with chezmoi 2.70.4
(both tests pass after the fix).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…check

MegaLinter (luacheck + stylua) has been red on main for the hammerspoon
config: 'accessing undefined variable hs' and 2-space-vs-stylua-default
formatting. hs is the Hammerspoon runtime global, and the watcher/tap/menubar
are intentionally non-local globals (kept to avoid GC, per their comments).

- Allow the hs global repo-wide via LUA_LUACHECK_ARGUMENTS in .mega-linter.yml.
- Declare the intentional per-file globals (configWatcher, spaceSwitchTap,
  spaceIndicator*) with inline 'luacheck: globals' directives + a why comment.
- Format all three files with stylua defaults (the repo has no stylua.toml).

Verified locally: luacheck 0/0 and stylua --check clean on all three.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
audit.sh trips SC2016 (literal $schema JSON key inside single quotes) and
SC2012 (ls on controlled Homebrew Cellar version dirs). Both are intentional;
add scoped 'shellcheck disable' directives with reasons rather than rewriting.
Verified: shellcheck --external-sources clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
devskim flags the JSON-Schema draft-07 $schema identifier
(http://json-schema.org/draft-07/schema#) as an insecure URL in the consensus
skill's *.schema.json. That URI is the canonical spec identifier and must stay
http://, so it is a genuine false positive; add DS137138 to .devskim.json
IgnoreRuleIds (alongside the existing DS162092).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ChipWolf ChipWolf changed the title fix(tests): supply private data key to bootstrap-template render fix(ci): repair pre-existing main failures (source-tests + MegaLinter) Jun 15, 2026
@ChipWolf
ChipWolf merged commit 202d912 into main Jun 15, 2026
17 checks passed
@ChipWolf
ChipWolf deleted the fix/source-tests-bootstrap-private branch June 15, 2026 17:28
@github-actions github-actions Bot mentioned this pull request Jun 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant