Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
47b8f35
Add a no-build TypeScript setup
breferrari Sep 1, 2026
7336dc3
Add the library the hooks and scripts share
breferrari Sep 1, 2026
a4e4153
Port the three hooks to TypeScript behind bash shims
breferrari Sep 1, 2026
9ba6850
Port the configure and doctor scripts to TypeScript, with no shim
breferrari Sep 1, 2026
bfd1263
Point the manifest at the TypeScript runtime
breferrari Sep 1, 2026
921e89e
Add the test suite and the recorded behaviour it is checked against
breferrari Sep 1, 2026
5a627f0
Add CI
breferrari Sep 1, 2026
e3ecffb
Update the README for the TypeScript runtime
breferrari Sep 1, 2026
52c89ac
Report success on a first install instead of exiting 2
breferrari Sep 1, 2026
3df0d62
Refuse an unset MCS_PROJECT_PATH instead of resolving against the fil…
breferrari Sep 1, 2026
662d2ce
Revamp the README: mermaid diagrams, navigation, and stale wording
breferrari Sep 1, 2026
110c8b4
Make the loop diagram vertical and scope the README to the pack as it is
breferrari Sep 1, 2026
72f9497
Drop the bash shims: register the TypeScript hooks directly
breferrari Sep 2, 2026
2b55c61
Drop the bash shims: register the TypeScript hooks directly
breferrari Sep 2, 2026
8560aa9
Show the installed hooks in the on-disk layout
breferrari Sep 2, 2026
77a3a77
Add section emoji to the README
breferrari Sep 2, 2026
57bb819
Ship the runtime as .mts so module type never depends on the consumer
breferrari Sep 2, 2026
2adfad8
Tell a git exit status apart from a git that never ran
breferrari Sep 2, 2026
f74e10c
Check the git results configure-memories was discarding
breferrari Sep 2, 2026
36f55e6
Restore the review nudge and stop swallowing a failed stage
breferrari Sep 2, 2026
50e025d
Make the suite reproducible off the machine that recorded it
breferrari Sep 2, 2026
ddee16e
Let the state snapshot see the remote
breferrari Sep 2, 2026
d7261e9
Close the smaller findings from review
breferrari Sep 2, 2026
a1b78f5
Declare the interpreter and gate on the release that honours it
breferrari Sep 2, 2026
0770a6b
Flush stdout rather than exiting out from under it
breferrari Sep 2, 2026
bc66a4f
Put the entry points under tsc instead of a parse-only --check
breferrari Sep 7, 2026
14f542b
Keep the review report when the dedupe state cannot be read
breferrari Sep 7, 2026
1a617e0
Stop a closed reader or an oversized git output from aborting a hook
breferrari Sep 7, 2026
9a90ab7
Pin the harness locale and uncap what it captures
breferrari Sep 7, 2026
1a9f96a
Say what actually picks a hook's interpreter, and name the files that…
breferrari Sep 7, 2026
b83f04e
Fix a fixture that contradicts its golden, and cover the non-rejectio…
breferrari Sep 7, 2026
565767a
Correct three README claims the interpreter change left behind
breferrari Sep 8, 2026
1f49868
Pin typecheck coverage by resolving the globs, and cover the EPIPE crash
breferrari Sep 8, 2026
7f86a98
Close the three loose ends from the last round
breferrari Sep 8, 2026
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
77 changes: 77 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
name: ci

# macOS only, deliberately: mcs is a Swift/Homebrew tool that installs on macOS,
# so it is the only platform that can actually install this pack. The suite runs
# the hooks exactly as mcs does, by executing them and letting the shebang pick
# the interpreter.
on:
push:
pull_request:

permissions:
contents: read

concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true

jobs:
test:
strategy:
fail-fast: false
matrix:
# 22.6 is the floor: `--experimental-strip-types` does not exist below it,
# and a bare '22' resolves to current 22.x, which cannot reach that range.
node: ['22.6.0', '22', '24']
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}

- name: node is new enough to strip types
run: |
command -v git >/dev/null || { echo "::error::git is required"; exit 1; }
node --experimental-strip-types -e 'const [maj, min] = process.versions.node.split(".").map(Number);
if (maj < 22 || (maj === 22 && min < 6)) { console.error("::error::node " + process.versions.node + " cannot strip types"); process.exit(1); }
console.log("node " + process.versions.node + " strips types");'

- name: install typecheck deps (CI-only, never shipped)
run: npm install --no-save --silent typescript@5.9.2 @types/node@22.9.0

- name: typecheck
run: npm run typecheck

- name: unit, contract and behaviour tests
run: npm test

# A migration artifact: it pinned the premise that commit subjects were
# unchanged by the port. Cheap to keep, not load-bearing going forward.
- name: the hostname equivalence holds on this runner
run: |
from_shell=$(hostname -s)
from_node=$(node -e 'process.stdout.write(require("node:os").hostname().split(".")[0])')
echo "shell='$from_shell' node='$from_node'"
[ "$from_shell" = "$from_node" ] || { echo "::error::hostname -s and os.hostname() disagree"; exit 1; }

# The pack contains no shell at all. Hooks and pack scripts are TypeScript
# executed through their shebang.
- name: no shell crept back in
run: |
stray=$(find . -name '*.sh' -not -path './node_modules/*' -not -path './.git/*' || true)
if [ -n "$stray" ]; then
echo "::error::this pack contains no shell scripts"
echo "$stray"
exit 1
fi

# A test that writes outside its temp dir is a bug wherever it lands.
- name: the test run left the working tree clean
run: |
residue=$(git status --porcelain --untracked-files=all)
if [ -n "$residue" ]; then
echo "::error::the test run left files behind"
echo "$residue"
exit 1
fi
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@
*.swo
.idea/
.vscode/

# Node typecheck deps (CI + local only; runtime is zero-deps)
node_modules/
164 changes: 110 additions & 54 deletions README.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion commands/approve-memories.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Run `git -C .claude/.memories-repo status --porcelain -- memories/` and `git -C

## 2. Filename guardrail

Every dirty file under `memories/` must match `^memories/(learning|decision)_[a-zA-Z0-9_-]+\.md$` — the same pattern the Stop hook enforces (keep in sync with `hooks/memories_autopush.sh` `allowed_pattern`, `hooks/memories_announce.sh` regex, and `scripts/configure-memories.sh` `allowed_pattern`). If any file fails, list the offenders, instruct the user to rename them to `memories/learning_<topic>_<specific>.md` or `memories/decision_<domain>_<topic>.md`, and stop without committing.
Every dirty file under `memories/` must match `^memories/(learning|decision)_[a-zA-Z0-9_-]+\.md$` — the same pattern the Stop hook enforces, defined once in `runtime/lib/naming.mts`. If any file fails, list the offenders, instruct the user to rename them to `memories/learning_<topic>_<specific>.md` or `memories/decision_<domain>_<topic>.md`, and stop without committing.

## 3. Stage, commit, push

Expand Down
37 changes: 0 additions & 37 deletions hooks/memories_announce.sh

This file was deleted.

Loading