aboutsummaryrefslogtreecommitdiff
path: root/scripts/tests/sync-language-bundle.bats
Commit message (Collapse)AuthorAgeFilesLines
* fix(language-bundle): don't re-drop the coverage fragment once adoptedCraig Jennings11 days1-0/+24
| | | | | | The startup bundle sync re-dropped from-rulesets-coverage-makefile.txt into a project's inbox on every run, even after the project had adopted the targets. inbox_drop only treated the fragment as adopted if coverage-makefile.txt still sat at the project root or waited in the inbox. But install-lang tells users the opposite: copy the targets into your Makefile, then delete the fragment. So a project that followed the documented path got the drop re-suggested forever (deleted three sessions running in one case). I guarded the drop so a project Makefile that already defines the distinctive coverage-summary target counts as adopted. The check lives at the call site, keeping inbox_drop generic. Added two bats cases: targets-in-Makefile suppresses the drop, an unrelated Makefile still gets it.
* feat(elisp): add coverage-summary to the Elisp bundle with missing-file ↵Craig Jennings14 days1-0/+62
| | | | | | | | | | | | | | detection A line-weighted coverage total has a blind spot: a module no test loads never shows up in the SimpleCov report, so it can't drag the number down. The suite looks healthier than it is. This adds a summary that counts every source file on disk against the report and treats an absent file as 0%, weighting the project number by file instead of by line so untested modules stay visible. The script ships at languages/elisp/claude/scripts/coverage-summary.el, self-contained on stock Emacs (just the built-in json). It parses the undercover SimpleCov shape directly rather than depending on the editor's coverage engine, so it runs anywhere the bundle lands. I proved it against a real 103-file report: 93 tracked, 27 untested modules surfaced, project number 66.4%. Delivery follows the bundle convention. The script lives under the gitignored .claude/ footprint and gets auto-fixed on drift by sync-language-bundle.sh, which I made generic for any claude/scripts/* rather than coverage-specific. The Makefile targets ship as a project-owned fragment (languages/elisp/coverage-makefile.txt) that install-lang.sh seeds at the project root and sync drops into .ai/inbox/ when that convention exists. The bundle never edits the project's own Makefile. Tests: 12 ERT for the kernel (Normal/Boundary/Error per function), wired into make test via a new languages/*/tests/ discovery path, plus bats for the sync auto-fix and the inbox-drop guards. This is the Elisp pilot. The pattern is proven, so fanning out to Python, Go, and TypeScript is now a follow-up. Each one needs only its own parser and fragment. The plumbing is already generic.
* feat: split team publishing rules into an installable overlayCraig Jennings2026-05-221-0/+39
| | | | | | | | | | | | The global commits.md carried DeepSat-specific publishing steps — Linear ticket-state moves, the Slack notification protocol with its channel ID and engineer names, the deepsat.ghe.com host, the team merge norm. Those are symlinked into every project on the machine, so they sat as dead weight in personal repos and risked misfiring where there's no Linear ticket to move or Slack mpdm to ping. I split them out. commits.md keeps the universal skeleton (identity, attribution, commit format, the review-and-publish gate, verification) and replaces the team steps with seams: "run the project's publishing overlay here if it defines one," the same pattern startup.org uses for startup-extras. A project with no overlay runs the complete flow, just without ticket and chat integration. The DeepSat specifics move to teams/deepsat/claude/rules/publishing.md. That file is not a global rule — install-team.sh copies it into one project's .claude/rules/ (make install-team TEAM=deepsat PROJECT=...), keyed on the PROJECT argument, so only the named project gets it. Location decides distribution: claude-rules/ is the global-symlink set, teams/ is targeted-copy, so the overlay reaches DeepSat and nowhere else. The startup freshness check (sync-language-bundle.sh) now covers team overlays alongside language bundles: a process_bundle function handles both, with a team syncing only its own rule (no generic rules, hooks, or settings — those belong to a language bundle). A drifted overlay rule auto-fixes from canonical at the project's next startup, the same mechanism language bundles already ride. Tested: 3 new bats cases (team overlay clean / drifted-and-fixed / does-not-pull-generic-rules) on top of the 11 existing; install-team + sync verified end-to-end against a temp project. make test green, shellcheck clean.
* feat(startup): sync language bundles per project on session launchCraig Jennings2026-05-221-0/+153
Startup synced the .ai/ templates into the current project every session but never checked the language bundle (elisp, python) installed in .claude/. Bundle drift went unnoticed until someone re-ran make install-lang by hand: a generic rule added to claude-rules/ after the last install, or a changed validator hook. scripts/sync-language-bundle.sh closes that gap. It fingerprints which bundle a project has by the presence of the language's own rule files (elisp.md, python-testing.md), then reconciles against the canonical source: auto-fix for rulesets-owned files (.claude/rules/*.md, .claude/hooks/*, githooks/*), surface-only for settings.json, which a project may have customized. CLAUDE.md is left alone. It's seed-only in install-lang and project-owned afterward, the same reason diff-lang skips it. Startup Phase A step 12 calls it for the current project, guarded so older checkouts that lack the script still boot. It writes only under .claude/ and githooks/, disjoint from the .ai/ rsync paths, so the parallel batch stays safe. A script rather than a make target keeps the Makefile-parse layer off the boot path. The absolute rulesets path it depends on is the same one the rsyncs already carry. Tested: 11 bats cases (no-bundle, clean, drifted rule/hook auto-fixed, surfaced settings.json asserted unmodified, absent CLAUDE.md not flagged, python detection, $PWD default, bad path). A smoke run against a copy of a real elisp project's .claude/ caught a perpetual "CLAUDE.md missing" alarm, which is what drove dropping CLAUDE.md from the surface set.