From 7a6976d6e2e3b9b160e9aeaee3b171db87f3b882 Mon Sep 17 00:00:00 2001 From: Philippos Savvides Date: Wed, 5 Aug 2026 07:43:23 -0700 Subject: [PATCH 1/4] docs: update project documentation for v3.3.0.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The release shipped new public surface, shared libraries, and eight test suites; the docs described none of it. Corrections against the diff: - CONTRIBUTING said a skill is "one directory, one file: SKILL.md" and named only smoke-test.sh. A new contributor following it would hand-edit a generated file and run 1 of 8 suites. Now documents the .tmpl source, the regen gate, every suite and what it covers, the Python 3.9 floor for embedded scripts, and the bin/lib rule (test the shipped file, not a copy). - CLAUDE.md / AGENTS.md: added idstack-migrate (incl. --init), manifest-merge and slugify to Commands; added the eight test suites and the CI matrix; documented the {{IDSTACK_RESOLVE}} placeholder and why it repeats per bash block; added the bin/lib section. - README: the contributing pointer repeated CONTRIBUTING's wrong instruction; the architecture block omitted idstack-doctor, which README's own troubleshooting section tells users to run. - ROADMAP was three releases behind, still showing v3.0.0 as newest. Added v3.1-v3.3 and dropped the passed "(v2.6)" labels from pending items, which made them read as overdue rather than unscheduled. Same labels fixed in TODOS.md and CLAUDE.md. - CHANGELOG: contributor-only work moved out of the user-facing "Changed" section into "For contributors"; added the git pull && ./setup line so the entry says how to actually receive the fixes. No entry reworded or removed. Corrected "16 behavioral tests" to 17 — f956177 split an assertion after the count was last audited; ./test/test-setup.sh reports 17/17. Verified: gen-skills --dry-run clean (22 templates, 0 stale); all eight suites pass (371 smoke, 25 integration, 17 setup, 21 manifest-merge, 27 version-classifier, 9 plugin-status, 6 preamble-python, 13/13 mutations guarded). Co-Authored-By: Claude Opus 5 (1M context) --- AGENTS.md | 49 ++++++++++++++++++++++++-- CHANGELOG.md | 8 +++-- CLAUDE.md | 37 ++++++++++++++++++-- CONTRIBUTING.md | 71 ++++++++++++++++++++++++++++++-------- README.md | 4 ++- ROADMAP.md | 28 ++++++++++++--- TODOS.md | 15 ++++---- templates/agent-context.md | 49 ++++++++++++++++++++++++-- 8 files changed, 225 insertions(+), 36 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 6c80a2a..38dc932 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -99,12 +99,34 @@ Every skill template follows this pattern: 2. **`{{PREAMBLE}}`** placeholder (replaced by `templates/preamble.md` during generation) 3. **Workflow** (Markdown defining the conversational flow, decision trees, outputs) 4. **`{{MANIFEST_SCHEMA}}`** placeholder (replaced by `templates/manifest-schema.md`) -5. **Timeline logging** (logs session data to `.idstack/timeline.jsonl` on completion) +5. **`{{IDSTACK_RESOLVE}}`** placeholder (replaced by `templates/snippets/idstack-resolve.sh`). + Unlike the other two it appears many times per template — once at the top of every + bash block that calls `$_IDSTACK/bin/...`. Bash blocks run in separate shells, so + `_IDSTACK` must be re-derived in each. The snippet is the single definition of that + resolution order: `CLAUDE_PLUGIN_ROOT`, `IDSTACK_HOME`, the Codex symlinks, then the + Claude Code marketplace cache. `templates/manifest-schema.md` is spliced verbatim and + writes the resolution out longhand; smoke-test keeps the two in lockstep. +6. **Timeline logging** (logs session data to `.idstack/timeline.jsonl` on completion) The shared preamble includes: update check, manifest check, preferences check, designer profile check, and context recovery (reads timeline + learnings for welcome-back messages and pipeline guidance). +Python embedded in the preamble must parse on Python 3.9 — the version macOS ships. +`test/test-preamble-python.sh` runs every embedded block on 3.9 and 3.12; a syntax error +there dies silently at runtime, which is how context recovery stayed broken for several +releases. + +### Shared shell libraries + +Logic used by more than one script — or that deserves a unit test — lives in `bin/lib/` +and is sourced by its callers rather than inlined: + +- `bin/lib/version-classify.sh` — version comparison, shared by `setup` and `bin/idstack-doctor` +- `bin/lib/plugin-status.sh` — parses `claude plugin list` output into idstack's own entry + +Test the shipped file, never a copy. + ### Course memory Skills log session data to `.idstack/timeline.jsonl` (what skills ran, scores, @@ -139,15 +161,38 @@ takes precedence when tiers conflict. ```bash ./setup # Install for the detected CLI(s) -./test/smoke-test.sh # Verify installation and generated artifacts +./setup --local # Install at project scope instead of user scope +./setup --codex / --no-codex # Force or skip the Codex bundle bin/idstack-gen-skills # Regenerate skill files for all targets bin/idstack-gen-skills --target codex # Regenerate Codex flavor only bin/idstack-gen-skills --dry-run # Check if generated files are up to date bin/idstack-doctor # Diagnose installs across CLIs bin/idstack-status # Course health dashboard (run in a project dir) bin/idstack-status --readiness # Pre-export readiness check only +bin/idstack-migrate # Migrate .idstack/project.json to the latest schema +bin/idstack-migrate --init # Also create a canonical manifest when none exists +bin/idstack-manifest-merge --section --payload # Canonical manifest write path +bin/idstack-slugify "" # Derive the for .idstack/exports/ ``` +Tests — all eight run in CI on every push and PR (`.github/workflows/test.yml`, +ubuntu on Python 3.9 + 3.12, macOS on 3.12): + +```bash +./test/smoke-test.sh # Install, SKILL.md freshness, frontmatter, version agreement, + # canonical section names, namespacing, resolve-snippet lockstep +./test/integration-test.sh # End-to-end; proves the suite leaves the working tree untouched +./test/test-setup.sh # ./setup behavior: flags, scope, legacy cleanup, failure handling +./test/test-manifest-merge.sh # bin/idstack-manifest-merge unit tests +./test/test-version-classifier.sh # bin/lib/version-classify.sh unit tests +./test/test-plugin-status.sh # bin/lib/plugin-status.sh unit tests +./test/test-preamble-python.sh # Runs the preamble's embedded python on 3.9 and 3.12 +./test/mutation-test.sh # Reintroduces each fixed defect, asserts its guarding test fails +``` + +Python 3.9 is the oldest interpreter in the field (macOS system python3) and the +leg that catches modern-only syntax reaching the preamble's embedded scripts. + No build step for users. No dependencies beyond bash (python3 recommended for full features). Skills are plain Markdown files. diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b1acde..12c57be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## v3.3.0.0 (2026-08-04) +To get these fixes: `cd` into your idstack clone, then `git pull && ./setup`. Restart Claude Code afterward — plugins load at session start. + ### Fixed — course memory, pipeline orchestration, re-run detection A full audit of the toolchain surfaced a set of bugs that broke user-visible behavior, some since their features shipped: @@ -19,14 +21,14 @@ A full audit of the toolchain surfaced a set of bugs that broke user-visible beh - course-quality-review, course-export, and learning-objectives now write their manifest sections through `bin/idstack-manifest-merge` (atomic, section-scoped, preserves every other section). needs-analysis and course-import keep the Read-modify-Write path — both write several co-owned sections in one pass, which whole-section merge cannot express — and each now documents why. - `bin/idstack-migrate --init` creates a canonical manifest with every section at its default. Three skills told the user to run `idstack-migrate` to create one when running standalone; it was a no-op on a missing file, so the merge that followed died with exit 4 and standalone results were silently never persisted. The skeleton comes from running the existing migration chain over a minimal seed, so there is no second definition of "canonical". - learning-objectives reports gained the required "Top recommendations" section; `[Alignment-1]` is now correctly cited as T5. -- Logic that was duplicated or inlined and therefore untestable now lives in `bin/lib/` and is sourced by its callers: `version-classify.sh` (shared by `setup` and `bin/idstack-doctor`) and `plugin-status.sh` (the `claude plugin list` parser). Their unit tests exercise the shipped code rather than a copy — the version classifier had drifted across three PRs while a mirrored test passed green. -### Infrastructure +### For contributors The audit found the test suite had never run automatically, and that some of it was not testing what it appeared to test. Both are fixed: +- Logic that was duplicated or inlined and therefore untestable now lives in `bin/lib/` and is sourced by its callers: `version-classify.sh` (shared by `setup` and `bin/idstack-doctor`) and `plugin-status.sh` (the `claude plugin list` parser). Their unit tests exercise the shipped code rather than a copy — the version classifier had drifted across three PRs while a mirrored test passed green. - **CI.** New GitHub Actions `test.yml` runs all seven suites on push and PR (ubuntu + macos, Python 3.9 + 3.12 — 3.9 is the leg that catches the context-recovery class of bug). `release.yml` refuses to publish unless the tag, `VERSION`, `plugin.json`, and `CHANGELOG.md` agree and the smoke test passes. -- **`./setup` is now tested** — 16 behavioral tests covering flag parsing, scope selection, all three legacy-cleanup shapes, and failure handling, run against a repo copy with a fake `$HOME` and a stub `claude`. It previously had no coverage at all while the smoke test spent 14 assertions on landing-page CSS. +- **`./setup` is now tested** — 17 behavioral tests covering flag parsing, scope selection, all three legacy-cleanup shapes, and failure handling, run against a repo copy with a fake `$HOME` and a stub `claude`. It previously had no coverage at all while the smoke test spent 14 assertions on landing-page CSS. - **A mutation suite proves the guards work.** `test/mutation-test.sh` reintroduces each of the 13 defects fixed here into a throwaway copy and asserts the guarding test fails. This is what was missing: the version-classifier suite passed green while testing a local copy of the classifier rather than the shipped code, and `gen-skills` counted a placeholder-less template as neither generated nor failed. - smoke-test grew from 272 to 371 assertions (version agreement, canonical section names, `/idstack:` namespacing, resolve-snippet lockstep, v1.1 migration, `bash -n` on every script) and prints failure diagnostics instead of a bare FAIL; integration-test proves it leaves the working tree untouched. diff --git a/CLAUDE.md b/CLAUDE.md index acbe061..36f8eba 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## What is idstack -An open source set of skills for evidence-based instructional design. Runs in Claude Code and OpenAI Codex CLI (Gemini CLI on the v2.6 roadmap). Each skill is a SKILL.md file that defines a conversational workflow backed by evidence from peer-reviewed research across 11 domains. +An open source set of skills for evidence-based instructional design. Runs in Claude Code and OpenAI Codex CLI (Gemini CLI is on the roadmap, not yet scheduled). Each skill is a SKILL.md file that defines a conversational workflow backed by evidence from peer-reviewed research across 11 domains. ## Commands @@ -13,7 +13,6 @@ An open source set of skills for evidence-based instructional design. Runs in Cl ./setup --local # Install at project scope (./.claude/) instead of user scope ./setup --codex # Force-install the Codex bundle even if codex isn't on PATH ./setup --no-codex # Skip the Codex install -./test/smoke-test.sh # Verify installation, SKILL.md files, YAML frontmatter, migrations bin/idstack-gen-skills # Regenerate skill files for all targets (claude + codex) bin/idstack-gen-skills --target claude # Regenerate Claude flavor only (skills//SKILL.md) bin/idstack-gen-skills --target codex # Regenerate Codex flavor only (dist/codex/skills/idstack-/) @@ -21,8 +20,28 @@ bin/idstack-gen-skills --dry-run # Check if generated files are up to bin/idstack-doctor # Diagnose plugin install (presence, manifest version, legacy-install conflicts) bin/idstack-status # Course health dashboard (run in a project dir) bin/idstack-status --readiness # Pre-export readiness check only +bin/idstack-migrate # Migrate an existing .idstack/project.json to the latest schema +bin/idstack-migrate --init # Also create a canonical manifest when none exists (standalone skill runs) +bin/idstack-manifest-merge --section --payload # Canonical manifest write path (atomic, section-scoped) +bin/idstack-slugify "" # Derive the used for .idstack/exports/ ``` +Tests (all eight run in CI on every push and PR — see `.github/workflows/test.yml`): + +```bash +./test/smoke-test.sh # 371 assertions: install, SKILL.md freshness, frontmatter, version agreement, + # canonical section names, /idstack: namespacing, resolve-snippet lockstep, bash -n +./test/integration-test.sh # End-to-end run; proves the suite leaves the working tree untouched +./test/test-setup.sh # 17 behavioral tests for ./setup (flags, scope, legacy cleanup, failure handling) +./test/test-manifest-merge.sh # bin/idstack-manifest-merge unit tests +./test/test-version-classifier.sh # bin/lib/version-classify.sh unit tests +./test/test-plugin-status.sh # bin/lib/plugin-status.sh unit tests +./test/test-preamble-python.sh # Runs the preamble's embedded python on 3.9 and 3.12 +./test/mutation-test.sh # Reintroduces each fixed defect and asserts its guarding test fails +``` + +CI matrix: ubuntu (Python 3.9 + 3.12) and macOS (3.12). 3.9 is the leg that catches modern-only Python syntax reaching the preamble's embedded scripts — it is what macOS ships. `mutation-test.sh` runs once, pinned to 3.9. + No build step for users. No dependencies beyond bash (python3 recommended for full features). Skills are plain Markdown files. ## Architecture @@ -86,10 +105,22 @@ Every skill template follows this pattern: 2. **`{{PREAMBLE}}`** placeholder (replaced by `templates/preamble.md` during generation) 3. **Workflow** (Markdown defining the conversational flow, decision trees, outputs) 4. **`{{MANIFEST_SCHEMA}}`** placeholder (replaced by `templates/manifest-schema.md`) -5. **Timeline logging** (logs session data to `.idstack/timeline.jsonl` on completion) +5. **`{{IDSTACK_RESOLVE}}`** placeholder (replaced by `templates/snippets/idstack-resolve.sh`). Unlike the other two, this one appears many times per template — once at the top of every bash block that calls `$_IDSTACK/bin/...`. Bash blocks run in separate shells, so `_IDSTACK` must be re-derived in each; the snippet is the single definition of that resolution order (`CLAUDE_PLUGIN_ROOT`, `IDSTACK_HOME`, the Codex symlinks, then the Claude Code marketplace cache). `templates/manifest-schema.md` is spliced verbatim and so writes the resolution out longhand — smoke-test keeps the two in lockstep. +6. **Timeline logging** (logs session data to `.idstack/timeline.jsonl` on completion) The shared preamble includes: interaction conventions (defines `AskUserQuestion` / `Agent` / `Skill` as portable concept names so the same body runs in both CLIs), update check, manifest check, preferences check, designer profile check, and context recovery (reads timeline + learnings for welcome-back messages and pipeline guidance). +Python embedded in the preamble must parse on Python 3.9 — the version macOS ships. `test/test-preamble-python.sh` runs every embedded block on 3.9 and 3.12; a syntax error there dies silently at runtime, which is how context recovery stayed broken for several releases. + +### Shared shell libraries + +Logic used by more than one script — or that deserves a unit test — lives in `bin/lib/` and is sourced by its callers rather than inlined: + +- `bin/lib/version-classify.sh` — version comparison, shared by `setup` and `bin/idstack-doctor` +- `bin/lib/plugin-status.sh` — parses `claude plugin list` output into idstack's own entry + +Test the shipped file, never a copy. The version classifier drifted across three PRs while a mirrored copy in its test passed green. + ### Course memory Skills log session data to `.idstack/timeline.jsonl` (what skills ran, scores, dimensions) and `.idstack/learnings.jsonl` (project-specific discoveries). The context recovery preamble reads these on session start to provide continuity across conversations. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 31c9a53..f2c0323 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,20 +5,24 @@ 1. Fork the repo and clone your fork 2. Create a branch: `git checkout -b my-skill` 3. Add your skill (see below) -4. Run `./setup` to register it -5. Run `./test/smoke-test.sh` to verify -6. Submit a PR +4. Run `bin/idstack-gen-skills` to generate the skill files from your template +5. Run `./setup` to register it +6. Run the test suite (see [Testing](#testing)) to verify +7. Submit a PR ## How skills work -One directory, one file: +One directory, one source file, one generated file per target: ``` -your-skill/ -└── SKILL.md +skills/your-skill/ +├── SKILL.md.tmpl # Source — this is the file you edit +└── SKILL.md # Generated by bin/idstack-gen-skills (Claude flavor; do not edit) ``` -That's the entire skill. No backend, no config files, no registration step beyond `./setup`. +Plus a Codex flavor at `dist/codex/skills/idstack-your-skill/SKILL.md`, also generated. + +That's the entire skill. No backend, no config files, no registration step beyond `./setup`. Edit the `.tmpl` and regenerate — a hand-edit to `SKILL.md` is overwritten on the next `bin/idstack-gen-skills` run, and the smoke test fails on the drift in the meantime. ### SKILL.md structure @@ -46,19 +50,37 @@ The bare `name` field becomes the slash-command suffix: `name: course-import` is **3. Skill implementation** — the rest of the file is Markdown that defines the skill's workflow, decision trees, and outputs. -**4. Timeline logging** — at the end, a section that logs the session to `.idstack/timeline.jsonl` with skill-specific fields. +**4. `{{MANIFEST_SCHEMA}}` placeholder** — replaced with `templates/manifest-schema.md`. + +**5. `{{IDSTACK_RESOLVE}}` placeholder** — replaced with `templates/snippets/idstack-resolve.sh`. Put this at the top of **every** bash block that calls `$_IDSTACK/bin/...`, not just the first. Bash blocks run in separate shells, so a value derived in an earlier block isn't there in a later one. Skipping it is how `learn` and `course-export` ended up pointing `bin/` calls at a nonexistent directory for marketplace installs. + +**6. Timeline logging** — at the end, a section that logs the session to `.idstack/timeline.jsonl` with skill-specific fields. ### Template system Skills use a template system to share common preamble code. Edit `{skill}/SKILL.md.tmpl`, not `SKILL.md` directly. The generated `SKILL.md` files have an `` header. -After editing a `.tmpl` file or `templates/preamble.md`, regenerate: +After editing a `.tmpl` file, `templates/preamble.md`, `templates/manifest-schema.md`, or `templates/snippets/idstack-resolve.sh`, regenerate: ```bash -bin/idstack-gen-skills +bin/idstack-gen-skills # write the regenerated files +bin/idstack-gen-skills --dry-run # check only — exits non-zero if anything is stale ``` -The smoke test includes a freshness check that fails if any `SKILL.md` is stale. +Commit the regenerated files in the same commit as the template change. The smoke test includes a freshness check that fails if any `SKILL.md` is stale. + +### Embedded Python must run on 3.9 + +Any Python embedded in `templates/preamble.md` or a skill body has to parse on Python 3.9 — that is what macOS ships, and it is the interpreter most designers will hit. An f-string reusing a quote inside its replacement field is legal from 3.12 (PEP 701) and a SyntaxError before it, which is exactly how context recovery stayed silently broken for several releases. `test/test-preamble-python.sh` runs every embedded block on both 3.9 and 3.12. + +### Shared shell libraries + +Logic used by more than one script — or worth a unit test — belongs in `bin/lib/`, sourced by its callers rather than copy-pasted: + +- `bin/lib/version-classify.sh` — version comparison, shared by `setup` and `bin/idstack-doctor` +- `bin/lib/plugin-status.sh` — parses `claude plugin list` down to idstack's own entry + +Point the test at the shipped file, never at a copy of the logic. The version classifier drifted across three PRs while a mirrored copy inside its own test kept passing green. ## The dual-output contract @@ -100,10 +122,26 @@ Use domain codes from `evidence/references.md` (e.g., `[Alignment-14] [T1]`). St ## Testing ```bash -./setup # Register your new skill (auto-detects Claude Code and codex on PATH) -./test/smoke-test.sh # Verify installation across all targets +bin/idstack-gen-skills --dry-run # Generated files up to date? Run this first. +./setup # Register your new skill (auto-detects Claude Code and codex on PATH) +./test/smoke-test.sh # Verify installation across all targets ``` +Eight suites run in CI (`.github/workflows/test.yml`) on every push and pull request. Run whichever ones your change touches locally; CI runs them all: + +| Suite | Covers | +|-------|--------| +| `test/smoke-test.sh` | Install, `SKILL.md` freshness, YAML frontmatter, version agreement across `VERSION` / `plugin.json` / `CHANGELOG.md`, canonical manifest section names, `/idstack:` namespacing, resolve-snippet lockstep, schema migrations, `bash -n` on every script | +| `test/integration-test.sh` | End-to-end run; asserts the suite leaves your working tree untouched | +| `test/test-setup.sh` | `./setup` behavior — flag parsing, scope selection, all three legacy-cleanup shapes, failure handling. Runs against a repo copy with a fake `$HOME` and a stub `claude` | +| `test/test-manifest-merge.sh` | `bin/idstack-manifest-merge` | +| `test/test-version-classifier.sh` | `bin/lib/version-classify.sh` | +| `test/test-plugin-status.sh` | `bin/lib/plugin-status.sh` | +| `test/test-preamble-python.sh` | The preamble's embedded Python, on 3.9 and 3.12 | +| `test/mutation-test.sh` | Reintroduces each known defect into a throwaway copy and asserts the guarding test fails. Add a mutation here whenever you fix a bug — it is what proves your new test would have caught it | + +The CI matrix is ubuntu on Python 3.9 and 3.12, plus macOS on 3.12 for BSD `grep`/`sed`/`awk` differences. `mutation-test.sh` runs once, pinned to 3.9. Do not skip hooks or push with a red suite. + Then test manually: - Claude Code: `/idstack:your-skill` - Codex CLI: `$your-skill` @@ -112,10 +150,15 @@ Then test manually: - **Focused scope** — one skill per PR - **Evidence-backed** — recommendations cite research, not opinions -- **Tested** — smoke test passes, manual test in Claude Code works +- **Tested** — the suite passes, manual test in Claude Code works, and a bug fix ships with both the test that catches it and a mutation in `test/mutation-test.sh` that proves the test works +- **Regenerated** — `bin/idstack-gen-skills --dry-run` is clean, with generated files committed alongside the template change - **Standalone** — skill works without a manifest (ask questions as fallback) - **Pipeline-aware** — if upstream data exists in the manifest, use it to enrich recommendations +## Looking for something to work on? + +[TODOS.md](TODOS.md) is the backlog — deferred work with the reasoning and dependencies attached. [ROADMAP.md](ROADMAP.md) is the user-facing view of the same thing. Read [DESIGN.md](DESIGN.md) before changing anything visual; it is the source of truth for the report stylesheet and the landing page. + ## Questions or feedback? [Fill out this form](https://forms.gle/6LDgDD1M6WWyYvME8) — no GitHub account needed. You can also [open an issue](https://github.com/savvides/idstack/issues). diff --git a/README.md b/README.md index d9a6576..50be625 100644 --- a/README.md +++ b/README.md @@ -270,6 +270,8 @@ Any skill works independently. Run `/idstack:pipeline` to chain them all, or inv | bin/idstack-migrate bin/idstack-timeline-log | | bin/idstack-learnings-log bin/idstack-status | | bin/idstack-slugify bin/idstack-update-check | +| bin/idstack-doctor bin/lib/version-classify.sh | +| bin/lib/plugin-status.sh | +-------------------------------------------------------+ ``` @@ -396,7 +398,7 @@ Have feedback or a feature request? [Fill out this form](https://forms.gle/6LDgD Found a bug? You can also [open an issue on GitHub](https://github.com/savvides/idstack/issues). -Want to add a new skill? See [CONTRIBUTING.md](CONTRIBUTING.md) for the full guide. The architecture is simple: create a directory with a SKILL.md file and run `./setup`. +Want to add a new skill? See [CONTRIBUTING.md](CONTRIBUTING.md) for the full guide. The architecture is simple: create a directory with a `SKILL.md.tmpl` template, run `bin/idstack-gen-skills` to generate the per-CLI skill files, then `./setup`. ## More diff --git a/ROADMAP.md b/ROADMAP.md index 4305a39..c418dcf 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -4,6 +4,26 @@ What's coming next for idstack. Priorities are shaped by user feedback. [Tell us ## Just shipped +### Course memory, pipeline orchestration, and re-run detection fixed (v3.3.0.0) +- **Welcome-back messages work on stock macOS.** The session-memory code embedded in every skill contained an f-string that is a SyntaxError on any Python below 3.12 — including the 3.9 macOS ships. It failed silently, so context recovery, quality-score trends, and next-step suggestions produced nothing. Fixed, and now exercised on 3.9 in CI so the class of bug can't ship again. +- **`/idstack:pipeline` invokes its child skills correctly.** It was calling them by an unnamespaced name that never resolved in Claude Code. +- **Skills notice previous runs again.** Re-run detection ("update the results or start fresh?") was dead in five skills, which looked up manifest sections that don't exist. +- **Marketplace installs resolve `bin/` correctly.** `learn` and `course-export` missed the marketplace cache — the way most users are installed — so their tool calls pointed at a nonexistent directory. +- **Apostrophes no longer blank the dashboard**, imported courses get a proper next-step suggestion, and `bin/idstack-doctor` can no longer report a disabled install as healthy. +- **Standalone runs persist.** `bin/idstack-migrate --init` creates a canonical manifest, so a skill run outside the pipeline has something to write into instead of silently discarding its results. + +### Test infrastructure and CI (v3.3.0.0, for contributors) +- The suite had never run automatically. GitHub Actions now runs all eight suites on every push and pull request, across ubuntu (Python 3.9 + 3.12) and macOS. +- `./setup` — the primary deliverable — went from zero coverage to 17 behavioral tests. +- `test/mutation-test.sh` reintroduces each fixed defect and asserts its guarding test fails, which is how a test that only appeared to test something gets caught. + +### Install through the Claude Code plugin marketplace (v3.2.0.0) +- `./setup` registers idstack as a Claude Code plugin marketplace and installs from there. Recent Claude Code versions stopped discovering plugins from the bare symlink older setups created, so `/idstack:` commands silently never appeared in the slash picker. If that happened to you, pull the latest and re-run `./setup`. + +### `DESIGN.md` and design-system reconciliation (v3.1.0.0) +- The visual system behind the report stylesheet and the landing page is documented at the repo root in `DESIGN.md` — fonts, colors, spacing, radii, motion, plus anti-patterns and a dated decisions log. Skills, contributors, and reviewers read it before touching anything visual. +- Publication-grade type (Source Serif 4, Public Sans, JetBrains Mono), an ivory palette in place of parchment, sharper card corners, and a second annotation color mirroring the two-pen academic-editor convention. Reports written by older versions still render correctly. + ### Branded HTML reports + per-course export folder (v3.0.0) - **HTML replaces Markdown for the human view.** Every skill that produces findings now writes a branded, self-contained HTML report at `.idstack/exports//.html`. Visual contract: `templates/report.html.tmpl` + `templates/assets/idstack.css` (scholarly serif body, severity-colored finding cards, evidence-tier badges, print-friendly, auto light/dark via `prefers-color-scheme`). Content contract is unchanged — observation → evidence → why-it-matters → suggestion, severity + tier on every finding. - **One folder per course, by name.** All per-course artifacts — every per-skill HTML report, the pipeline `index.html` dashboard, the bundled CSS, and LMS packages (`course-export.imscc`, `scorm-export.zip`) — live under `.idstack/exports//`. The slug is derived from `project_name` via `bin/idstack-slugify` (NFKD-fold, kebab-case, ASCII-safe). Zip the folder to hand the whole deliverable to a stakeholder. @@ -75,11 +95,11 @@ What's coming next for idstack. Priorities are shaped by user feedback. [Tell us ## Coming soon -### Gemini CLI support (v2.6) -Add native Gemini CLI as a third target. `.tmpl` → `.toml` transform plus a `gemini-extension.json` manifest. Gemini's built-in `ask_user` tool maps cleanly to the AskUserQuestion concept (drop-in), and inline `!{cmd}` shell interpolation will speed up the manifest-merge call paths. Codex shipped first because its SKILL.md format is a 1:1 match; Gemini needs the file-format transform. +### Gemini CLI support +Add native Gemini CLI as a third target. `.tmpl` → `.toml` transform plus a `gemini-extension.json` manifest. Gemini's built-in `ask_user` tool maps cleanly to the AskUserQuestion concept (drop-in), and inline `!{cmd}` shell interpolation will speed up the manifest-merge call paths. Codex shipped first because its SKILL.md format is a 1:1 match; Gemini needs the file-format transform. Not yet scheduled to a release. -### Marketplace publishing (v2.6) -Publish idstack via `codex plugin marketplace add savvides/idstack` so users don't need to clone the repo. Requires building the proper two-tier marketplace.json + .codex-plugin/plugin.json schema. v2.5 ships with simpler per-skill auto-discovery at `$CODEX_HOME/skills/`, which works without a marketplace. +### Codex marketplace publishing +Publish idstack via `codex plugin marketplace add savvides/idstack` so Codex users don't need to clone the repo. Requires building the proper two-tier marketplace.json + .codex-plugin/plugin.json schema. Codex currently installs through simpler per-skill auto-discovery at `$CODEX_HOME/skills/`, which works without a marketplace. (Claude Code already installs through its marketplace as of v3.2.0.0.) Not yet scheduled to a release. ### More skills Four more skills based on the research synthesis: diff --git a/TODOS.md b/TODOS.md index 526a49d..c5e2804 100644 --- a/TODOS.md +++ b/TODOS.md @@ -62,13 +62,14 @@ plus a whole-repo symlink at `~/.agents/plugins/idstack/` for in-skill `bin/` re generator (`--target {claude|codex|all}`) emits the Codex flavor under `dist/codex/skills/` with `allowed-tools:` stripped. Concept-name preamble lets the same skill body run in both CLIs. -**Gemini CLI: still pending (v2.6).** `.tmpl` → `.toml` transform, `gemini-extension.json` -manifest, `ask_user` tool mapping. Gemini's built-in structured-question tool is a clean -drop-in for the AskUserQuestion concept. - -**Marketplace publishing: still pending (v2.6).** v2.5 uses simpler per-skill auto-discovery; -proper Codex marketplace.json + .codex-plugin/plugin.json packaging would let users do -`codex plugin marketplace add savvides/idstack` without cloning. +**Gemini CLI: still pending, not yet scheduled to a release.** `.tmpl` → `.toml` transform, +`gemini-extension.json` manifest, `ask_user` tool mapping. Gemini's built-in +structured-question tool is a clean drop-in for the AskUserQuestion concept. + +**Codex marketplace publishing: still pending, not yet scheduled to a release.** Codex installs +through simpler per-skill auto-discovery; proper Codex marketplace.json + .codex-plugin/plugin.json +packaging would let users do `codex plugin marketplace add savvides/idstack` without cloning. +(Claude Code has installed through its own marketplace since v3.2.0.0.) **Why:** Expands addressable market beyond Claude Code. **Priority:** P2 (Codex done; Gemini next) diff --git a/templates/agent-context.md b/templates/agent-context.md index 6c80a2a..38dc932 100644 --- a/templates/agent-context.md +++ b/templates/agent-context.md @@ -99,12 +99,34 @@ Every skill template follows this pattern: 2. **`{{PREAMBLE}}`** placeholder (replaced by `templates/preamble.md` during generation) 3. **Workflow** (Markdown defining the conversational flow, decision trees, outputs) 4. **`{{MANIFEST_SCHEMA}}`** placeholder (replaced by `templates/manifest-schema.md`) -5. **Timeline logging** (logs session data to `.idstack/timeline.jsonl` on completion) +5. **`{{IDSTACK_RESOLVE}}`** placeholder (replaced by `templates/snippets/idstack-resolve.sh`). + Unlike the other two it appears many times per template — once at the top of every + bash block that calls `$_IDSTACK/bin/...`. Bash blocks run in separate shells, so + `_IDSTACK` must be re-derived in each. The snippet is the single definition of that + resolution order: `CLAUDE_PLUGIN_ROOT`, `IDSTACK_HOME`, the Codex symlinks, then the + Claude Code marketplace cache. `templates/manifest-schema.md` is spliced verbatim and + writes the resolution out longhand; smoke-test keeps the two in lockstep. +6. **Timeline logging** (logs session data to `.idstack/timeline.jsonl` on completion) The shared preamble includes: update check, manifest check, preferences check, designer profile check, and context recovery (reads timeline + learnings for welcome-back messages and pipeline guidance). +Python embedded in the preamble must parse on Python 3.9 — the version macOS ships. +`test/test-preamble-python.sh` runs every embedded block on 3.9 and 3.12; a syntax error +there dies silently at runtime, which is how context recovery stayed broken for several +releases. + +### Shared shell libraries + +Logic used by more than one script — or that deserves a unit test — lives in `bin/lib/` +and is sourced by its callers rather than inlined: + +- `bin/lib/version-classify.sh` — version comparison, shared by `setup` and `bin/idstack-doctor` +- `bin/lib/plugin-status.sh` — parses `claude plugin list` output into idstack's own entry + +Test the shipped file, never a copy. + ### Course memory Skills log session data to `.idstack/timeline.jsonl` (what skills ran, scores, @@ -139,15 +161,38 @@ takes precedence when tiers conflict. ```bash ./setup # Install for the detected CLI(s) -./test/smoke-test.sh # Verify installation and generated artifacts +./setup --local # Install at project scope instead of user scope +./setup --codex / --no-codex # Force or skip the Codex bundle bin/idstack-gen-skills # Regenerate skill files for all targets bin/idstack-gen-skills --target codex # Regenerate Codex flavor only bin/idstack-gen-skills --dry-run # Check if generated files are up to date bin/idstack-doctor # Diagnose installs across CLIs bin/idstack-status # Course health dashboard (run in a project dir) bin/idstack-status --readiness # Pre-export readiness check only +bin/idstack-migrate # Migrate .idstack/project.json to the latest schema +bin/idstack-migrate --init # Also create a canonical manifest when none exists +bin/idstack-manifest-merge --section --payload # Canonical manifest write path +bin/idstack-slugify "" # Derive the for .idstack/exports/ ``` +Tests — all eight run in CI on every push and PR (`.github/workflows/test.yml`, +ubuntu on Python 3.9 + 3.12, macOS on 3.12): + +```bash +./test/smoke-test.sh # Install, SKILL.md freshness, frontmatter, version agreement, + # canonical section names, namespacing, resolve-snippet lockstep +./test/integration-test.sh # End-to-end; proves the suite leaves the working tree untouched +./test/test-setup.sh # ./setup behavior: flags, scope, legacy cleanup, failure handling +./test/test-manifest-merge.sh # bin/idstack-manifest-merge unit tests +./test/test-version-classifier.sh # bin/lib/version-classify.sh unit tests +./test/test-plugin-status.sh # bin/lib/plugin-status.sh unit tests +./test/test-preamble-python.sh # Runs the preamble's embedded python on 3.9 and 3.12 +./test/mutation-test.sh # Reintroduces each fixed defect, asserts its guarding test fails +``` + +Python 3.9 is the oldest interpreter in the field (macOS system python3) and the +leg that catches modern-only syntax reaching the preamble's embedded scripts. + No build step for users. No dependencies beyond bash (python3 recommended for full features). Skills are plain Markdown files. From d81788a51ede58d9388c7cd222fd35ce96116f14 Mon Sep 17 00:00:00 2001 From: Philippos Savvides Date: Wed, 5 Aug 2026 08:17:24 -0700 Subject: [PATCH 2/4] docs: close the gaps the cross-model doc review found Eight findings from the Codex documentation review, each verified against the shipped source before applying. User-facing (README): - Bare /course-quality-review and /learning-objectives in prose and in the sample transcript. This release banned exactly that form from skill text for not being a valid command; the README still handed it to users. Now /idstack:, with a note above the workflow diagram explaining that its unprefixed labels are for column width, not for typing. - The sample install output was from an install path that no longer exists ("linked: ...", "installed successfully"). setup:176 prints "idstack installed (Claude Code) - scope: ..." and a skills list. Replaced with what it actually prints. - "Requirement: Claude Code" contradicted line 7's Codex support claim. Codex is now named, with every setup flag documented. Contributor guidance: - --keep-legacy is a public flag with its own usage line (setup:32), fixed by this very release, and was documented nowhere. Added to both command lists. - CLAUDE.md / AGENTS.md / CONTRIBUTING called inline manifest writes a deprecated fallback, but needs-analysis and course-import use them deliberately for multi-section writes. Undocumented, that reads as two skills violating the rule. Now stated as the one exception, with the standalone idstack-migrate --init requirement alongside it. Counts: - CHANGELOG said CI runs "all seven suites"; test.yml runs eight (seven in the matrix job, mutation in its own). - TODOS said "All 7 skill preambles"; there are 11. - ROADMAP: pre-v2 entries used /idstack and bare /red-team forms. Normalized to the colon namespace so nothing on the page is copy-pasteable and broken. Verified: gen-skills --dry-run clean; smoke 371/371, integration 25/25, setup 17/17. Co-Authored-By: Claude Opus 5 (1M context) --- AGENTS.md | 8 ++++++++ CHANGELOG.md | 2 +- CLAUDE.md | 3 +++ CONTRIBUTING.md | 2 ++ README.md | 37 ++++++++++++++++++++++++++++++------- ROADMAP.md | 30 +++++++++++++++--------------- TODOS.md | 2 +- templates/agent-context.md | 8 ++++++++ 8 files changed, 68 insertions(+), 24 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 38dc932..b325f69 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -74,6 +74,13 @@ Manifest write rules: - Use `bin/idstack-manifest-merge` for the write path: section-scoped, atomic (tempfile + rename), preserves foreign sections, validates against the canonical schema in `templates/manifest-schema.md`. Inline full-manifest edit is the deprecated fallback. +- **The one documented exception:** `needs-analysis` and `course-import` keep the + Read-modify-Write path because each writes several co-owned sections in one pass, which + whole-section merge cannot express. Both state why inline. Don't "fix" them to use the + merge tool, and don't copy their pattern into a single-section writer. +- Running standalone, call `bin/idstack-migrate --init` before merging. On a missing + manifest plain `idstack-migrate` is a no-op, so the merge that follows exits 4 and the + results are silently never persisted. Report write rules: @@ -163,6 +170,7 @@ takes precedence when tiers conflict. ./setup # Install for the detected CLI(s) ./setup --local # Install at project scope instead of user scope ./setup --codex / --no-codex # Force or skip the Codex bundle +./setup --keep-legacy # Leave pre-v2.0.1.0 installs in place bin/idstack-gen-skills # Regenerate skill files for all targets bin/idstack-gen-skills --target codex # Regenerate Codex flavor only bin/idstack-gen-skills --dry-run # Check if generated files are up to date diff --git a/CHANGELOG.md b/CHANGELOG.md index 12c57be..18de502 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,7 +27,7 @@ A full audit of the toolchain surfaced a set of bugs that broke user-visible beh The audit found the test suite had never run automatically, and that some of it was not testing what it appeared to test. Both are fixed: - Logic that was duplicated or inlined and therefore untestable now lives in `bin/lib/` and is sourced by its callers: `version-classify.sh` (shared by `setup` and `bin/idstack-doctor`) and `plugin-status.sh` (the `claude plugin list` parser). Their unit tests exercise the shipped code rather than a copy — the version classifier had drifted across three PRs while a mirrored test passed green. -- **CI.** New GitHub Actions `test.yml` runs all seven suites on push and PR (ubuntu + macos, Python 3.9 + 3.12 — 3.9 is the leg that catches the context-recovery class of bug). `release.yml` refuses to publish unless the tag, `VERSION`, `plugin.json`, and `CHANGELOG.md` agree and the smoke test passes. +- **CI.** New GitHub Actions `test.yml` runs all eight suites on push and PR — seven in a matrix job (ubuntu + macos, Python 3.9 + 3.12 — 3.9 is the leg that catches the context-recovery class of bug), plus the mutation suite in its own job. `release.yml` refuses to publish unless the tag, `VERSION`, `plugin.json`, and `CHANGELOG.md` agree and the smoke test passes. - **`./setup` is now tested** — 17 behavioral tests covering flag parsing, scope selection, all three legacy-cleanup shapes, and failure handling, run against a repo copy with a fake `$HOME` and a stub `claude`. It previously had no coverage at all while the smoke test spent 14 assertions on landing-page CSS. - **A mutation suite proves the guards work.** `test/mutation-test.sh` reintroduces each of the 13 defects fixed here into a throwaway copy and asserts the guarding test fails. This is what was missing: the version-classifier suite passed green while testing a local copy of the classifier rather than the shipped code, and `gen-skills` counted a placeholder-less template as neither generated nor failed. - smoke-test grew from 272 to 371 assertions (version agreement, canonical section names, `/idstack:` namespacing, resolve-snippet lockstep, v1.1 migration, `bash -n` on every script) and prints failure diagnostics instead of a bare FAIL; integration-test proves it leaves the working tree untouched. diff --git a/CLAUDE.md b/CLAUDE.md index 36f8eba..5e5f34a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -13,6 +13,7 @@ An open source set of skills for evidence-based instructional design. Runs in Cl ./setup --local # Install at project scope (./.claude/) instead of user scope ./setup --codex # Force-install the Codex bundle even if codex isn't on PATH ./setup --no-codex # Skip the Codex install +./setup --keep-legacy # Leave pre-v2.0.1.0 installs in place instead of removing them bin/idstack-gen-skills # Regenerate skill files for all targets (claude + codex) bin/idstack-gen-skills --target claude # Regenerate Claude flavor only (skills//SKILL.md) bin/idstack-gen-skills --target codex # Regenerate Codex flavor only (dist/codex/skills/idstack-/) @@ -89,6 +90,8 @@ Rules for writing the manifest: - Own your section only. Read full manifest, modify only your skill's section, preserve everything else. - Update the `updated` timestamp on every write. - Use `bin/idstack-manifest-merge` for the write path: it's section-scoped, atomic (tempfile + rename), preserves foreign sections, and validates against the canonical schema in `templates/manifest-schema.md`. Inline full-manifest `Edit` is the deprecated fallback only. +- **The one documented exception:** `needs-analysis` and `course-import` keep the Read-modify-Write path because each writes several co-owned sections in one pass, which whole-section merge cannot express. Both state why inline. Don't "fix" them to use the merge tool, and don't copy their pattern into a single-section writer. +- Running standalone, call `bin/idstack-migrate --init` before merging. On a missing manifest plain `idstack-migrate` is a no-op, so the merge that follows exits 4 and the results are silently never persisted. Rules for writing the report: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f2c0323..1d66c92 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -97,6 +97,8 @@ Phrase recommendations as suggestions ("consider…"), not directives. Cite ever - **Own your section only.** Read the full manifest, modify only the section your skill owns, preserve everything else. - **Update the `updated` timestamp** on every write. - **Use `bin/idstack-manifest-merge`** for the write path. It's section-scoped, atomic (tempfile + rename), preserves foreign sections, and validates against the canonical schema in `templates/manifest-schema.md`. Inline full-manifest `Edit` is the deprecated fallback. +- **One documented exception.** `needs-analysis` and `course-import` keep the Read-modify-Write path because each writes several co-owned sections in one pass, which whole-section merge cannot express. Both say so inline. Don't convert them, and don't copy the pattern into a skill that owns a single section. +- **Standalone runs need `bin/idstack-migrate --init` first.** On a missing manifest, plain `idstack-migrate` is a no-op, so the merge that follows exits 4 and the skill's results are silently never persisted. `--init` creates a canonical manifest with every section at its default. ## Evidence standards diff --git a/README.md b/README.md index 50be625..9bde161 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,7 @@ idstack: Reading your manifest... I have 12 modules, 6 objectives, ### Top 3 Recommendations 1. Add rubrics to all assessments with elaborated feedback - [Assessment-8] [T1] — Run /learning-objectives to align + [Assessment-8] [T1] — Run /idstack:learning-objectives 2. Design collaborative activities for at least 4 modules [Online-15] [T2] 3. Add learner support section with office hours, tutoring, @@ -94,7 +94,7 @@ You had a course in Canvas. Now you have an evidence-based audit with specific r ## Install — 30 seconds -**Requirement:** [Claude Code](https://claude.ai/code) (desktop app, web app, or CLI). +**Requirement:** [Claude Code](https://claude.ai/code) (desktop app, web app, or CLI) or [OpenAI Codex CLI](https://developers.openai.com/codex/cli). `./setup` detects whichever you have and installs for both if both are present. Paste this into your terminal: @@ -136,25 +136,46 @@ Claude clones the repo, runs setup, and confirms the skills are registered. ``` +
+All setup flags + +```bash +./setup # Auto-detect Claude Code and codex on PATH, install for both +./setup --local # Install at project scope (./.claude/) instead of user scope +./setup --codex # Force-install the Codex bundle even if codex isn't on PATH +./setup --no-codex # Skip the Codex install +./setup --keep-legacy # Leave pre-v2.0.1.0 installs in place instead of removing them +``` + +Setup is idempotent — re-run it any time. +
+ You should see: ``` -Installing idstack... - linked: /idstack → /path/to/idstack +idstack installed (Claude Code) — scope: user. -idstack installed successfully. + If Claude Code is already running, restart it (plugins load at session start). Usage: /idstack: Have an existing course? - /idstack:course-import → /idstack:course-quality-review + /idstack:course-import -> /idstack:course-quality-review Starting fresh? /idstack:needs-analysis Run the full pipeline: /idstack:pipeline + + All skills: needs-analysis, learning-objectives, assessment-design, + course-builder, course-quality-review, accessibility-review, + red-team, course-export, course-import, pipeline, learn + + More info: https://idstack.org ``` +If you also have Codex CLI on your `PATH`, you'll see an `idstack installed (Codex CLI).` block too, with `$` usage. + ## Your design team idstack turns Claude Code into an evidence-based instructional design team. Each skill is a specialist. All invoked via `/idstack:`. @@ -177,6 +198,8 @@ idstack turns Claude Code into an evidence-based instructional design team. Each Each skill feeds into the next. The project manifest is the thread. +Skill names in the diagram below are shown unprefixed to keep the columns readable. To actually run one, use `/idstack:` in Claude Code or `$` in Codex CLI. + ``` EXISTING COURSE NEW COURSE @@ -313,7 +336,7 @@ Every recommendation includes an evidence tier so you know how strong the backin When the skill says "add elaborated feedback to your quizzes," it tells you that's T1 evidence from multiple meta-analyses, not someone's blog post. ### Using skills independently -Any skill works on its own. `/course-quality-review` works without a manifest by asking you questions directly. `/learning-objectives` works without a needs analysis. The pipeline adds context and makes recommendations sharper, but every skill is self-contained. +Any skill works on its own. `/idstack:course-quality-review` works without a manifest by asking you questions directly. `/idstack:learning-objectives` works without a needs analysis. The pipeline adds context and makes recommendations sharper, but every skill is self-contained. ## The evidence base diff --git a/ROADMAP.md b/ROADMAP.md index c418dcf..5b41793 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -55,23 +55,23 @@ What's coming next for idstack. Priorities are shaped by user feedback. [Tell us - Schema migration v1.4 fixes drifted field names (`red_team_audit.summary.*_count` → `findings_summary.*`, `_import_quality_flags` → `import_metadata.quality_flag_details`). ### idstack v2 — Pipeline orchestrator, intelligence, sub-agents -- **`/idstack pipeline`** — chains all 8 skills automatically. Auto-skips completed skills, shows pipeline status, pause and resume anytime. -- **Namespace refactor** — all skills now invoked via `/idstack ` (e.g., `/idstack needs-analysis`). No more name collisions with other skill packages. +- **`/idstack:pipeline`** — chains all 8 skills automatically. Auto-skips completed skills, shows pipeline status, pause and resume anytime. +- **Namespace refactor** — all skills now invoked via `/idstack:` (e.g., `/idstack:needs-analysis`). No more name collisions with other skill packages. - **Cross-course intelligence** — learnings from one course appear in another. Global store at `~/.idstack/global/learnings.jsonl` with keyword search. -- **`/idstack learn`** — search, delete, promote, and export learnings. -- **Course readiness dashboard** — pre-export gate showing quality/red-team/accessibility status. Integrated into `/idstack course-export`. +- **`/idstack:learn`** — search, delete, promote, and export learnings. +- **Course readiness dashboard** — pre-export gate showing quality/red-team/accessibility status. Integrated into `/idstack:course-export`. - **Designer profile** — `~/.idstack/profile.yaml` with experience level. Skills adapt explanation depth (novice/intermediate/expert). - **Manifest preferences** — schema v1.3 adds verbosity, export format, preferred LMS settings. -- **Sub-agent architecture** — `/idstack red-team` (5 parallel agents), `/idstack accessibility-review` (2 parallel), `/idstack course-quality-review` (3 parallel). Claude Code only, graceful degradation elsewhere. -- **Spec review loop** — `/idstack course-builder` validates alignment via adversarial subagent after generating content. +- **Sub-agent architecture** — `/idstack:red-team` (5 parallel agents), `/idstack:accessibility-review` (2 parallel), `/idstack:course-quality-review` (3 parallel). Claude Code only, graceful degradation elsewhere. +- **Spec review loop** — `/idstack:course-builder` validates alignment via adversarial subagent after generating content. - **IDSTACK_HOME** — all paths portable via env var. Foundation for multi-platform support. ### Bidirectional pipeline + evidence depth (v1.5.1) - All 9 skills now write back to the manifest. Downstream skills get richer input from upstream analysis. -- Score trending: run `/idstack course-quality-review` multiple times and see your score improve over sessions. -- `/idstack accessibility-review` expanded to full WCAG 2.1 AA coverage with course-specific guidance for videos, quizzes, forums, PDFs, and simulations. -- `/idstack red-team` all 5 adversarial dimensions now cite their research evidence. -- `/idstack course-export` shows readiness info (quality, accessibility, red-team scores) before export. +- Score trending: run `/idstack:course-quality-review` multiple times and see your score improve over sessions. +- `/idstack:accessibility-review` expanded to full WCAG 2.1 AA coverage with course-specific guidance for videos, quizzes, forums, PDFs, and simulations. +- `/idstack:red-team` all 5 adversarial dimensions now cite their research evidence. +- `/idstack:course-export` shows readiness info (quality, accessibility, red-team scores) before export. - Schema migration v1.2 with chained upgrades (any version → latest in one pass). ### Course memory (v1.5.0) @@ -85,13 +85,13 @@ What's coming next for idstack. Priorities are shaped by user feedback. [Tell us - Skills check for updates and notify when a new version is available. ### SCORM import and export (v1.4.0) -- `/course-import` now accepts SCORM 1.2/2004 packages from Articulate Rise, Storyline, Adobe Captivate, Lectora, iSpring, and any SCORM-compliant authoring tool -- `/course-export` now generates SCORM 1.2 packages for any LMS or corporate training platform +- `/idstack:course-import` now accepts SCORM 1.2/2004 packages from Articulate Rise, Storyline, Adobe Captivate, Lectora, iSpring, and any SCORM-compliant authoring tool +- `/idstack:course-export` now generates SCORM 1.2 packages for any LMS or corporate training platform - PDF and document file import also added for Rise course exports and syllabi ### Accessibility review + Red team audit (v1.3.0) -- `/accessibility-review` — WCAG 2.1 AA compliance plus Universal Design for Learning (UDL 3.0). Two-tier output: "Must Fix" for legal compliance, "Should Improve" for inclusive design. -- `/red-team` — Adversarial course audit. Assumes the course is broken and tries to prove it. Five dimensions: alignment stress test, evidence verification, cognitive load analysis, learner persona simulation, prerequisite chain integrity. Produces a confidence score. +- `/idstack:accessibility-review` — WCAG 2.1 AA compliance plus Universal Design for Learning (UDL 3.0). Two-tier output: "Must Fix" for legal compliance, "Should Improve" for inclusive design. +- `/idstack:red-team` — Adversarial course audit. Assumes the course is broken and tries to prove it. Five dimensions: alignment stress test, evidence verification, cognitive load analysis, learner persona simulation, prerequisite chain integrity. Produces a confidence score. ## Coming soon @@ -119,7 +119,7 @@ Direct API connections to Blackboard, Moodle, and D2L (beyond the IMS Common Car ## The big vision ### Push changes back to your LMS -After `/course-quality-review` identifies issues and `/learning-objectives` generates better objectives, push the improvements directly back to Canvas (and eventually other LMS platforms). No more copy-pasting between a design document and your LMS. The output IS the course. +After `/idstack:course-quality-review` identifies issues and `/idstack:learning-objectives` generates better objectives, push the improvements directly back to Canvas (and eventually other LMS platforms). No more copy-pasting between a design document and your LMS. The output IS the course. This is the 10x goal. It depends on stable import/export, Canvas API write support, conflict handling, and institutional partnerships. It's a ways out, but it's where we're headed. diff --git a/TODOS.md b/TODOS.md index c5e2804..9e1bbe3 100644 --- a/TODOS.md +++ b/TODOS.md @@ -14,7 +14,7 @@ smoke-test catches the regression, new `bin/idstack-doctor` for diagnostics. ## ~~v1.1: Manifest Versioning~~ SHIPPED (v1.2.0) Shipped in v1.2.0. `bin/idstack-migrate` handles schema migrations. -All 7 skill preambles call it automatically. +Every skill preamble calls it automatically (7 skills at the time; 11 now). ## ~~v2: Cross-Domain Quality Checks~~ SHIPPED (v1.2.0) Shipped in v1.2.0. Four checks added to /course-quality-review: diff --git a/templates/agent-context.md b/templates/agent-context.md index 38dc932..b325f69 100644 --- a/templates/agent-context.md +++ b/templates/agent-context.md @@ -74,6 +74,13 @@ Manifest write rules: - Use `bin/idstack-manifest-merge` for the write path: section-scoped, atomic (tempfile + rename), preserves foreign sections, validates against the canonical schema in `templates/manifest-schema.md`. Inline full-manifest edit is the deprecated fallback. +- **The one documented exception:** `needs-analysis` and `course-import` keep the + Read-modify-Write path because each writes several co-owned sections in one pass, which + whole-section merge cannot express. Both state why inline. Don't "fix" them to use the + merge tool, and don't copy their pattern into a single-section writer. +- Running standalone, call `bin/idstack-migrate --init` before merging. On a missing + manifest plain `idstack-migrate` is a no-op, so the merge that follows exits 4 and the + results are silently never persisted. Report write rules: @@ -163,6 +170,7 @@ takes precedence when tiers conflict. ./setup # Install for the detected CLI(s) ./setup --local # Install at project scope instead of user scope ./setup --codex / --no-codex # Force or skip the Codex bundle +./setup --keep-legacy # Leave pre-v2.0.1.0 installs in place bin/idstack-gen-skills # Regenerate skill files for all targets bin/idstack-gen-skills --target codex # Regenerate Codex flavor only bin/idstack-gen-skills --dry-run # Check if generated files are up to date From 399b563bd7c84c24cbe7dac7d773ca38fb4d2e8e Mon Sep 17 00:00:00 2001 From: Philippos Savvides Date: Wed, 5 Aug 2026 08:20:53 -0700 Subject: [PATCH 3/4] docs: complete the README install-output sample The previous commit rebuilt this block from setup:176 onward and claimed it was what setup prints. It skipped the three lines setup emits before that: the regeneration notice (setup:49) and the "Installing idstack (scope)" / "source:" header (setup:51-52), all unconditional. Co-Authored-By: Claude Opus 5 (1M context) --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 9bde161..bb429ec 100644 --- a/README.md +++ b/README.md @@ -152,6 +152,10 @@ Setup is idempotent — re-run it any time. You should see: ``` + regenerated skill files for all targets +Installing idstack (user)... + source: /path/to/idstack + idstack installed (Claude Code) — scope: user. If Claude Code is already running, restart it (plugins load at session start). From 0b4ba5187800f4faeb553ce8039755602d3b61a7 Mon Sep 17 00:00:00 2001 From: Philippos Savvides Date: Wed, 5 Aug 2026 15:45:58 -0700 Subject: [PATCH 4/4] fix: skills no longer suggest commands that don't exist (v3.3.0.1) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v3.3.0.0 banned bare /skill references because they resolve in neither CLI, and fixed them in bin/idstack-status. The guard enforcing it matched only backticked refs: BARE_SLASH_RE='`/(needs-analysis|...)`' Three plain-prose examples in templates/preamble.md survived it (lines 236, 241, 244) — and the preamble is spliced into all 22 skill files. They are the model's instructions for phrasing welcome-back and next-step messages, so the model copied their shape and told users things like "Based on your progress, /assessment-design is the natural next step." Typing that does nothing. It landed inside the context-recovery message v3.3.0.0 had just repaired, so it was the first thing a user saw once welcome-back messages started working again. - Namespaced all three. On Codex the existing translation rule renders them as $. - Widened the guard to match a bare /skill in any command position (line start, whitespace, quote, paren, backtick), not only inside backticks. It will not match a slash preceded by a path character, so .idstack/exports//red-team.html stays legal, and it cannot match /idstack: because the skill name does not follow the slash. - Kept frontmatter exempt, as before: description: is picker prose, not a command. The check now strips through the closing --- and scans the body. Six frontmatter matches confirmed exempt rather than "fixed". - Added a mutation case reintroducing an unbackticked bare reference. Found by the doc sweep in /document-release, not by the suite — the guard that was supposed to catch it is the thing that had the hole. Verified: smoke 371/371, integration 25/25, setup 17/17, manifest-merge 21/21, version-classifier 27/27, plugin-status 9/9, preamble-python 6/6, mutations 14/14 guarded. gen-skills --dry-run clean. Co-Authored-By: Claude Opus 5 (1M context) --- .claude-plugin/plugin.json | 2 +- CHANGELOG.md | 13 ++++++++++ VERSION | 2 +- .../idstack-accessibility-review/SKILL.md | 6 ++--- .../skills/idstack-assessment-design/SKILL.md | 6 ++--- .../skills/idstack-course-builder/SKILL.md | 6 ++--- .../skills/idstack-course-export/SKILL.md | 6 ++--- .../skills/idstack-course-import/SKILL.md | 6 ++--- .../idstack-course-quality-review/SKILL.md | 6 ++--- dist/codex/skills/idstack-learn/SKILL.md | 6 ++--- .../idstack-learning-objectives/SKILL.md | 6 ++--- .../skills/idstack-needs-analysis/SKILL.md | 6 ++--- dist/codex/skills/idstack-pipeline/SKILL.md | 6 ++--- dist/codex/skills/idstack-red-team/SKILL.md | 6 ++--- docs/index.html | 7 +++--- skills/accessibility-review/SKILL.md | 6 ++--- skills/assessment-design/SKILL.md | 6 ++--- skills/course-builder/SKILL.md | 6 ++--- skills/course-export/SKILL.md | 6 ++--- skills/course-import/SKILL.md | 6 ++--- skills/course-quality-review/SKILL.md | 6 ++--- skills/learn/SKILL.md | 6 ++--- skills/learning-objectives/SKILL.md | 6 ++--- skills/needs-analysis/SKILL.md | 6 ++--- skills/pipeline/SKILL.md | 6 ++--- skills/red-team/SKILL.md | 6 ++--- templates/preamble.md | 6 ++--- test/mutation-test.sh | 11 +++++++++ test/smoke-test.sh | 24 +++++++++++++++---- 29 files changed, 118 insertions(+), 79 deletions(-) diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index ffd0b4d..beff54f 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "idstack", - "version": "3.3.0.0", + "version": "3.3.0.1", "description": "Evidence-based instructional design pipeline. 11 skills backed by peer-reviewed research across 11 domains. Analyze, design, build, review, and export courses with every recommendation citing its evidence tier.", "author": { "name": "Philippos Savvides", diff --git a/CHANGELOG.md b/CHANGELOG.md index 18de502..43973ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,18 @@ # Changelog +## v3.3.0.1 (2026-08-05) + +To get this fix: `cd` into your idstack clone, then `git pull && ./setup`. Restart Claude Code afterward — plugins load at session start. + +### Fixed — skills no longer suggest commands that don't exist + +- **Welcome-back and next-step messages named unrunnable commands.** v3.3.0.0 banned bare `/skill` references because they resolve in neither CLI, and fixed them in `bin/idstack-status`. The guard enforcing it matched only backticked refs, so three plain-prose examples in the preamble's context-recovery section survived — and the preamble is spliced into all 22 skill files. The model copied their shape and told users things like "Based on your progress, /assessment-design is the natural next step." Typing that does nothing. Landing inside the context-recovery message v3.3.0.0 had just repaired made it the first thing a user saw once welcome-back messages started working again. Now namespaced; on Codex the existing translation rule renders them as `$`. + +### For contributors + +- The smoke-test guard now matches a bare `/skill` in any command position, not only inside backticks, and scans skill bodies with frontmatter still exempt (`description:` is picker prose, not a command). Suite count unchanged at 371. +- `test/mutation-test.sh` gained a case that reintroduces an unbackticked bare reference into the preamble and asserts smoke-test fails: 14 mutations, 14 guarded. + ## v3.3.0.0 (2026-08-04) To get these fixes: `cd` into your idstack clone, then `git pull && ./setup`. Restart Claude Code afterward — plugins load at session start. diff --git a/VERSION b/VERSION index ec285fb..bb32e79 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.3.0.0 +3.3.0.1 diff --git a/dist/codex/skills/idstack-accessibility-review/SKILL.md b/dist/codex/skills/idstack-accessibility-review/SKILL.md index d8159f4..aaef3b7 100644 --- a/dist/codex/skills/idstack-accessibility-review/SKILL.md +++ b/dist/codex/skills/idstack-accessibility-review/SKILL.md @@ -245,15 +245,15 @@ fi ``` **If QUALITY_TREND is shown:** Synthesize a welcome-back message. Example: "Welcome back. -Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /learning-objectives." +Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /idstack:learning-objectives." Keep it to 2-3 sentences. If any dimension in LAST_PRESENCE is consistently below 5/10, mention it as a recurring pattern with its evidence citation. **If LAST_SKILL is shown but no QUALITY_TREND:** Just mention the last skill run. -Example: "Welcome back. Last session you ran /course-import." +Example: "Welcome back. Last session you ran /idstack:course-import." **If SUGGESTED_NEXT is shown:** Mention the suggested next skill naturally. -Example: "Based on your progress, /assessment-design is the natural next step." +Example: "Based on your progress, /idstack:assessment-design is the natural next step." **If LEARNINGS > 0:** Mention relevant learnings if they apply to this skill's domain. Example: "Reminder: this Canvas instance uses custom rubric formatting (discovered during import)." diff --git a/dist/codex/skills/idstack-assessment-design/SKILL.md b/dist/codex/skills/idstack-assessment-design/SKILL.md index 7d3a224..e56ff9b 100644 --- a/dist/codex/skills/idstack-assessment-design/SKILL.md +++ b/dist/codex/skills/idstack-assessment-design/SKILL.md @@ -245,15 +245,15 @@ fi ``` **If QUALITY_TREND is shown:** Synthesize a welcome-back message. Example: "Welcome back. -Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /learning-objectives." +Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /idstack:learning-objectives." Keep it to 2-3 sentences. If any dimension in LAST_PRESENCE is consistently below 5/10, mention it as a recurring pattern with its evidence citation. **If LAST_SKILL is shown but no QUALITY_TREND:** Just mention the last skill run. -Example: "Welcome back. Last session you ran /course-import." +Example: "Welcome back. Last session you ran /idstack:course-import." **If SUGGESTED_NEXT is shown:** Mention the suggested next skill naturally. -Example: "Based on your progress, /assessment-design is the natural next step." +Example: "Based on your progress, /idstack:assessment-design is the natural next step." **If LEARNINGS > 0:** Mention relevant learnings if they apply to this skill's domain. Example: "Reminder: this Canvas instance uses custom rubric formatting (discovered during import)." diff --git a/dist/codex/skills/idstack-course-builder/SKILL.md b/dist/codex/skills/idstack-course-builder/SKILL.md index 6720128..f3c3b36 100644 --- a/dist/codex/skills/idstack-course-builder/SKILL.md +++ b/dist/codex/skills/idstack-course-builder/SKILL.md @@ -245,15 +245,15 @@ fi ``` **If QUALITY_TREND is shown:** Synthesize a welcome-back message. Example: "Welcome back. -Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /learning-objectives." +Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /idstack:learning-objectives." Keep it to 2-3 sentences. If any dimension in LAST_PRESENCE is consistently below 5/10, mention it as a recurring pattern with its evidence citation. **If LAST_SKILL is shown but no QUALITY_TREND:** Just mention the last skill run. -Example: "Welcome back. Last session you ran /course-import." +Example: "Welcome back. Last session you ran /idstack:course-import." **If SUGGESTED_NEXT is shown:** Mention the suggested next skill naturally. -Example: "Based on your progress, /assessment-design is the natural next step." +Example: "Based on your progress, /idstack:assessment-design is the natural next step." **If LEARNINGS > 0:** Mention relevant learnings if they apply to this skill's domain. Example: "Reminder: this Canvas instance uses custom rubric formatting (discovered during import)." diff --git a/dist/codex/skills/idstack-course-export/SKILL.md b/dist/codex/skills/idstack-course-export/SKILL.md index 6944f24..ced2592 100644 --- a/dist/codex/skills/idstack-course-export/SKILL.md +++ b/dist/codex/skills/idstack-course-export/SKILL.md @@ -245,15 +245,15 @@ fi ``` **If QUALITY_TREND is shown:** Synthesize a welcome-back message. Example: "Welcome back. -Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /learning-objectives." +Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /idstack:learning-objectives." Keep it to 2-3 sentences. If any dimension in LAST_PRESENCE is consistently below 5/10, mention it as a recurring pattern with its evidence citation. **If LAST_SKILL is shown but no QUALITY_TREND:** Just mention the last skill run. -Example: "Welcome back. Last session you ran /course-import." +Example: "Welcome back. Last session you ran /idstack:course-import." **If SUGGESTED_NEXT is shown:** Mention the suggested next skill naturally. -Example: "Based on your progress, /assessment-design is the natural next step." +Example: "Based on your progress, /idstack:assessment-design is the natural next step." **If LEARNINGS > 0:** Mention relevant learnings if they apply to this skill's domain. Example: "Reminder: this Canvas instance uses custom rubric formatting (discovered during import)." diff --git a/dist/codex/skills/idstack-course-import/SKILL.md b/dist/codex/skills/idstack-course-import/SKILL.md index e2d21f9..cc0c7c4 100644 --- a/dist/codex/skills/idstack-course-import/SKILL.md +++ b/dist/codex/skills/idstack-course-import/SKILL.md @@ -245,15 +245,15 @@ fi ``` **If QUALITY_TREND is shown:** Synthesize a welcome-back message. Example: "Welcome back. -Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /learning-objectives." +Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /idstack:learning-objectives." Keep it to 2-3 sentences. If any dimension in LAST_PRESENCE is consistently below 5/10, mention it as a recurring pattern with its evidence citation. **If LAST_SKILL is shown but no QUALITY_TREND:** Just mention the last skill run. -Example: "Welcome back. Last session you ran /course-import." +Example: "Welcome back. Last session you ran /idstack:course-import." **If SUGGESTED_NEXT is shown:** Mention the suggested next skill naturally. -Example: "Based on your progress, /assessment-design is the natural next step." +Example: "Based on your progress, /idstack:assessment-design is the natural next step." **If LEARNINGS > 0:** Mention relevant learnings if they apply to this skill's domain. Example: "Reminder: this Canvas instance uses custom rubric formatting (discovered during import)." diff --git a/dist/codex/skills/idstack-course-quality-review/SKILL.md b/dist/codex/skills/idstack-course-quality-review/SKILL.md index 2e1f37f..a85bb1d 100644 --- a/dist/codex/skills/idstack-course-quality-review/SKILL.md +++ b/dist/codex/skills/idstack-course-quality-review/SKILL.md @@ -245,15 +245,15 @@ fi ``` **If QUALITY_TREND is shown:** Synthesize a welcome-back message. Example: "Welcome back. -Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /learning-objectives." +Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /idstack:learning-objectives." Keep it to 2-3 sentences. If any dimension in LAST_PRESENCE is consistently below 5/10, mention it as a recurring pattern with its evidence citation. **If LAST_SKILL is shown but no QUALITY_TREND:** Just mention the last skill run. -Example: "Welcome back. Last session you ran /course-import." +Example: "Welcome back. Last session you ran /idstack:course-import." **If SUGGESTED_NEXT is shown:** Mention the suggested next skill naturally. -Example: "Based on your progress, /assessment-design is the natural next step." +Example: "Based on your progress, /idstack:assessment-design is the natural next step." **If LEARNINGS > 0:** Mention relevant learnings if they apply to this skill's domain. Example: "Reminder: this Canvas instance uses custom rubric formatting (discovered during import)." diff --git a/dist/codex/skills/idstack-learn/SKILL.md b/dist/codex/skills/idstack-learn/SKILL.md index 3b6d61f..9d6b7a9 100644 --- a/dist/codex/skills/idstack-learn/SKILL.md +++ b/dist/codex/skills/idstack-learn/SKILL.md @@ -244,15 +244,15 @@ fi ``` **If QUALITY_TREND is shown:** Synthesize a welcome-back message. Example: "Welcome back. -Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /learning-objectives." +Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /idstack:learning-objectives." Keep it to 2-3 sentences. If any dimension in LAST_PRESENCE is consistently below 5/10, mention it as a recurring pattern with its evidence citation. **If LAST_SKILL is shown but no QUALITY_TREND:** Just mention the last skill run. -Example: "Welcome back. Last session you ran /course-import." +Example: "Welcome back. Last session you ran /idstack:course-import." **If SUGGESTED_NEXT is shown:** Mention the suggested next skill naturally. -Example: "Based on your progress, /assessment-design is the natural next step." +Example: "Based on your progress, /idstack:assessment-design is the natural next step." **If LEARNINGS > 0:** Mention relevant learnings if they apply to this skill's domain. Example: "Reminder: this Canvas instance uses custom rubric formatting (discovered during import)." diff --git a/dist/codex/skills/idstack-learning-objectives/SKILL.md b/dist/codex/skills/idstack-learning-objectives/SKILL.md index 215c0c6..2107b8f 100644 --- a/dist/codex/skills/idstack-learning-objectives/SKILL.md +++ b/dist/codex/skills/idstack-learning-objectives/SKILL.md @@ -245,15 +245,15 @@ fi ``` **If QUALITY_TREND is shown:** Synthesize a welcome-back message. Example: "Welcome back. -Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /learning-objectives." +Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /idstack:learning-objectives." Keep it to 2-3 sentences. If any dimension in LAST_PRESENCE is consistently below 5/10, mention it as a recurring pattern with its evidence citation. **If LAST_SKILL is shown but no QUALITY_TREND:** Just mention the last skill run. -Example: "Welcome back. Last session you ran /course-import." +Example: "Welcome back. Last session you ran /idstack:course-import." **If SUGGESTED_NEXT is shown:** Mention the suggested next skill naturally. -Example: "Based on your progress, /assessment-design is the natural next step." +Example: "Based on your progress, /idstack:assessment-design is the natural next step." **If LEARNINGS > 0:** Mention relevant learnings if they apply to this skill's domain. Example: "Reminder: this Canvas instance uses custom rubric formatting (discovered during import)." diff --git a/dist/codex/skills/idstack-needs-analysis/SKILL.md b/dist/codex/skills/idstack-needs-analysis/SKILL.md index ed7ef86..539b96f 100644 --- a/dist/codex/skills/idstack-needs-analysis/SKILL.md +++ b/dist/codex/skills/idstack-needs-analysis/SKILL.md @@ -245,15 +245,15 @@ fi ``` **If QUALITY_TREND is shown:** Synthesize a welcome-back message. Example: "Welcome back. -Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /learning-objectives." +Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /idstack:learning-objectives." Keep it to 2-3 sentences. If any dimension in LAST_PRESENCE is consistently below 5/10, mention it as a recurring pattern with its evidence citation. **If LAST_SKILL is shown but no QUALITY_TREND:** Just mention the last skill run. -Example: "Welcome back. Last session you ran /course-import." +Example: "Welcome back. Last session you ran /idstack:course-import." **If SUGGESTED_NEXT is shown:** Mention the suggested next skill naturally. -Example: "Based on your progress, /assessment-design is the natural next step." +Example: "Based on your progress, /idstack:assessment-design is the natural next step." **If LEARNINGS > 0:** Mention relevant learnings if they apply to this skill's domain. Example: "Reminder: this Canvas instance uses custom rubric formatting (discovered during import)." diff --git a/dist/codex/skills/idstack-pipeline/SKILL.md b/dist/codex/skills/idstack-pipeline/SKILL.md index 86ed5ef..321801b 100644 --- a/dist/codex/skills/idstack-pipeline/SKILL.md +++ b/dist/codex/skills/idstack-pipeline/SKILL.md @@ -244,15 +244,15 @@ fi ``` **If QUALITY_TREND is shown:** Synthesize a welcome-back message. Example: "Welcome back. -Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /learning-objectives." +Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /idstack:learning-objectives." Keep it to 2-3 sentences. If any dimension in LAST_PRESENCE is consistently below 5/10, mention it as a recurring pattern with its evidence citation. **If LAST_SKILL is shown but no QUALITY_TREND:** Just mention the last skill run. -Example: "Welcome back. Last session you ran /course-import." +Example: "Welcome back. Last session you ran /idstack:course-import." **If SUGGESTED_NEXT is shown:** Mention the suggested next skill naturally. -Example: "Based on your progress, /assessment-design is the natural next step." +Example: "Based on your progress, /idstack:assessment-design is the natural next step." **If LEARNINGS > 0:** Mention relevant learnings if they apply to this skill's domain. Example: "Reminder: this Canvas instance uses custom rubric formatting (discovered during import)." diff --git a/dist/codex/skills/idstack-red-team/SKILL.md b/dist/codex/skills/idstack-red-team/SKILL.md index bc0067f..185daa8 100644 --- a/dist/codex/skills/idstack-red-team/SKILL.md +++ b/dist/codex/skills/idstack-red-team/SKILL.md @@ -246,15 +246,15 @@ fi ``` **If QUALITY_TREND is shown:** Synthesize a welcome-back message. Example: "Welcome back. -Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /learning-objectives." +Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /idstack:learning-objectives." Keep it to 2-3 sentences. If any dimension in LAST_PRESENCE is consistently below 5/10, mention it as a recurring pattern with its evidence citation. **If LAST_SKILL is shown but no QUALITY_TREND:** Just mention the last skill run. -Example: "Welcome back. Last session you ran /course-import." +Example: "Welcome back. Last session you ran /idstack:course-import." **If SUGGESTED_NEXT is shown:** Mention the suggested next skill naturally. -Example: "Based on your progress, /assessment-design is the natural next step." +Example: "Based on your progress, /idstack:assessment-design is the natural next step." **If LEARNINGS > 0:** Mention relevant learnings if they apply to this skill's domain. Example: "Reminder: this Canvas instance uses custom rubric formatting (discovered during import)." diff --git a/docs/index.html b/docs/index.html index 6cb7106..8407af8 100644 --- a/docs/index.html +++ b/docs/index.html @@ -44,7 +44,7 @@ "operatingSystem": "macOS, Linux, Windows", "softwareVersion": "3.3.0", "datePublished": "2026-04-20", - "dateModified": "2026-08-04", + "dateModified": "2026-08-05", "offers": { "@type": "Offer", "price": "0", @@ -926,7 +926,7 @@ MIT - v3.3.0.0 — Course memory fixed + v3.3.0.1 — Course memory fixed

Evidence-based instructional design, transparently cited.

108 peer-reviewed studies across 11 research domains. Every recommendation tagged with its evidence tier — T1 meta-analyses and RCTs through T5 expert opinion. Runs in Claude Code, OpenAI Codex CLI, and (soon) Gemini.

@@ -1176,10 +1176,11 @@

v3.3.0.0 — Course memory that actually remembers.

-

August 4, 2026 · v3.3.0.0 · latest

+

August 4, 2026 · v3.3.0.0 · patched by v3.3.0.1

Welcome-back messages work on stock macOS now.

On any Python older than 3.12 — including the 3.9 that macOS ships — the session-memory code inside every skill hit a silent syntax error. No welcome-back summary, no quality-score trend, no suggested next step. Fixed, and now exercised on Python 3.9 in CI so it stays fixed.

Also in this release: /idstack:pipeline invokes its child skills correctly in Claude Code, skills notice previous runs again ("update the results or start fresh?"), imported courses get a proper next-step suggestion, and a course name with an apostrophe no longer blanks the status dashboard. To update: cd into your idstack clone, then git pull && ./setup.

+

Patched in v3.3.0.1 (August 5): skills no longer point you at commands that don't exist. Welcome-back and next-step messages now name the runnable /idstack:<skill> form.

→ All releases on GitHub

diff --git a/skills/accessibility-review/SKILL.md b/skills/accessibility-review/SKILL.md index e639706..bd91c37 100644 --- a/skills/accessibility-review/SKILL.md +++ b/skills/accessibility-review/SKILL.md @@ -254,15 +254,15 @@ fi ``` **If QUALITY_TREND is shown:** Synthesize a welcome-back message. Example: "Welcome back. -Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /learning-objectives." +Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /idstack:learning-objectives." Keep it to 2-3 sentences. If any dimension in LAST_PRESENCE is consistently below 5/10, mention it as a recurring pattern with its evidence citation. **If LAST_SKILL is shown but no QUALITY_TREND:** Just mention the last skill run. -Example: "Welcome back. Last session you ran /course-import." +Example: "Welcome back. Last session you ran /idstack:course-import." **If SUGGESTED_NEXT is shown:** Mention the suggested next skill naturally. -Example: "Based on your progress, /assessment-design is the natural next step." +Example: "Based on your progress, /idstack:assessment-design is the natural next step." **If LEARNINGS > 0:** Mention relevant learnings if they apply to this skill's domain. Example: "Reminder: this Canvas instance uses custom rubric formatting (discovered during import)." diff --git a/skills/assessment-design/SKILL.md b/skills/assessment-design/SKILL.md index 909465a..6a3495a 100644 --- a/skills/assessment-design/SKILL.md +++ b/skills/assessment-design/SKILL.md @@ -253,15 +253,15 @@ fi ``` **If QUALITY_TREND is shown:** Synthesize a welcome-back message. Example: "Welcome back. -Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /learning-objectives." +Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /idstack:learning-objectives." Keep it to 2-3 sentences. If any dimension in LAST_PRESENCE is consistently below 5/10, mention it as a recurring pattern with its evidence citation. **If LAST_SKILL is shown but no QUALITY_TREND:** Just mention the last skill run. -Example: "Welcome back. Last session you ran /course-import." +Example: "Welcome back. Last session you ran /idstack:course-import." **If SUGGESTED_NEXT is shown:** Mention the suggested next skill naturally. -Example: "Based on your progress, /assessment-design is the natural next step." +Example: "Based on your progress, /idstack:assessment-design is the natural next step." **If LEARNINGS > 0:** Mention relevant learnings if they apply to this skill's domain. Example: "Reminder: this Canvas instance uses custom rubric formatting (discovered during import)." diff --git a/skills/course-builder/SKILL.md b/skills/course-builder/SKILL.md index 1aa4f6b..93755bc 100644 --- a/skills/course-builder/SKILL.md +++ b/skills/course-builder/SKILL.md @@ -254,15 +254,15 @@ fi ``` **If QUALITY_TREND is shown:** Synthesize a welcome-back message. Example: "Welcome back. -Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /learning-objectives." +Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /idstack:learning-objectives." Keep it to 2-3 sentences. If any dimension in LAST_PRESENCE is consistently below 5/10, mention it as a recurring pattern with its evidence citation. **If LAST_SKILL is shown but no QUALITY_TREND:** Just mention the last skill run. -Example: "Welcome back. Last session you ran /course-import." +Example: "Welcome back. Last session you ran /idstack:course-import." **If SUGGESTED_NEXT is shown:** Mention the suggested next skill naturally. -Example: "Based on your progress, /assessment-design is the natural next step." +Example: "Based on your progress, /idstack:assessment-design is the natural next step." **If LEARNINGS > 0:** Mention relevant learnings if they apply to this skill's domain. Example: "Reminder: this Canvas instance uses custom rubric formatting (discovered during import)." diff --git a/skills/course-export/SKILL.md b/skills/course-export/SKILL.md index f45f1e5..5579704 100644 --- a/skills/course-export/SKILL.md +++ b/skills/course-export/SKILL.md @@ -254,15 +254,15 @@ fi ``` **If QUALITY_TREND is shown:** Synthesize a welcome-back message. Example: "Welcome back. -Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /learning-objectives." +Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /idstack:learning-objectives." Keep it to 2-3 sentences. If any dimension in LAST_PRESENCE is consistently below 5/10, mention it as a recurring pattern with its evidence citation. **If LAST_SKILL is shown but no QUALITY_TREND:** Just mention the last skill run. -Example: "Welcome back. Last session you ran /course-import." +Example: "Welcome back. Last session you ran /idstack:course-import." **If SUGGESTED_NEXT is shown:** Mention the suggested next skill naturally. -Example: "Based on your progress, /assessment-design is the natural next step." +Example: "Based on your progress, /idstack:assessment-design is the natural next step." **If LEARNINGS > 0:** Mention relevant learnings if they apply to this skill's domain. Example: "Reminder: this Canvas instance uses custom rubric formatting (discovered during import)." diff --git a/skills/course-import/SKILL.md b/skills/course-import/SKILL.md index b25b799..ec58a74 100644 --- a/skills/course-import/SKILL.md +++ b/skills/course-import/SKILL.md @@ -254,15 +254,15 @@ fi ``` **If QUALITY_TREND is shown:** Synthesize a welcome-back message. Example: "Welcome back. -Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /learning-objectives." +Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /idstack:learning-objectives." Keep it to 2-3 sentences. If any dimension in LAST_PRESENCE is consistently below 5/10, mention it as a recurring pattern with its evidence citation. **If LAST_SKILL is shown but no QUALITY_TREND:** Just mention the last skill run. -Example: "Welcome back. Last session you ran /course-import." +Example: "Welcome back. Last session you ran /idstack:course-import." **If SUGGESTED_NEXT is shown:** Mention the suggested next skill naturally. -Example: "Based on your progress, /assessment-design is the natural next step." +Example: "Based on your progress, /idstack:assessment-design is the natural next step." **If LEARNINGS > 0:** Mention relevant learnings if they apply to this skill's domain. Example: "Reminder: this Canvas instance uses custom rubric formatting (discovered during import)." diff --git a/skills/course-quality-review/SKILL.md b/skills/course-quality-review/SKILL.md index b35db8f..f0132dc 100644 --- a/skills/course-quality-review/SKILL.md +++ b/skills/course-quality-review/SKILL.md @@ -254,15 +254,15 @@ fi ``` **If QUALITY_TREND is shown:** Synthesize a welcome-back message. Example: "Welcome back. -Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /learning-objectives." +Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /idstack:learning-objectives." Keep it to 2-3 sentences. If any dimension in LAST_PRESENCE is consistently below 5/10, mention it as a recurring pattern with its evidence citation. **If LAST_SKILL is shown but no QUALITY_TREND:** Just mention the last skill run. -Example: "Welcome back. Last session you ran /course-import." +Example: "Welcome back. Last session you ran /idstack:course-import." **If SUGGESTED_NEXT is shown:** Mention the suggested next skill naturally. -Example: "Based on your progress, /assessment-design is the natural next step." +Example: "Based on your progress, /idstack:assessment-design is the natural next step." **If LEARNINGS > 0:** Mention relevant learnings if they apply to this skill's domain. Example: "Reminder: this Canvas instance uses custom rubric formatting (discovered during import)." diff --git a/skills/learn/SKILL.md b/skills/learn/SKILL.md index 324bd54..c700277 100644 --- a/skills/learn/SKILL.md +++ b/skills/learn/SKILL.md @@ -249,15 +249,15 @@ fi ``` **If QUALITY_TREND is shown:** Synthesize a welcome-back message. Example: "Welcome back. -Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /learning-objectives." +Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /idstack:learning-objectives." Keep it to 2-3 sentences. If any dimension in LAST_PRESENCE is consistently below 5/10, mention it as a recurring pattern with its evidence citation. **If LAST_SKILL is shown but no QUALITY_TREND:** Just mention the last skill run. -Example: "Welcome back. Last session you ran /course-import." +Example: "Welcome back. Last session you ran /idstack:course-import." **If SUGGESTED_NEXT is shown:** Mention the suggested next skill naturally. -Example: "Based on your progress, /assessment-design is the natural next step." +Example: "Based on your progress, /idstack:assessment-design is the natural next step." **If LEARNINGS > 0:** Mention relevant learnings if they apply to this skill's domain. Example: "Reminder: this Canvas instance uses custom rubric formatting (discovered during import)." diff --git a/skills/learning-objectives/SKILL.md b/skills/learning-objectives/SKILL.md index 146393e..9ae7f1f 100644 --- a/skills/learning-objectives/SKILL.md +++ b/skills/learning-objectives/SKILL.md @@ -253,15 +253,15 @@ fi ``` **If QUALITY_TREND is shown:** Synthesize a welcome-back message. Example: "Welcome back. -Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /learning-objectives." +Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /idstack:learning-objectives." Keep it to 2-3 sentences. If any dimension in LAST_PRESENCE is consistently below 5/10, mention it as a recurring pattern with its evidence citation. **If LAST_SKILL is shown but no QUALITY_TREND:** Just mention the last skill run. -Example: "Welcome back. Last session you ran /course-import." +Example: "Welcome back. Last session you ran /idstack:course-import." **If SUGGESTED_NEXT is shown:** Mention the suggested next skill naturally. -Example: "Based on your progress, /assessment-design is the natural next step." +Example: "Based on your progress, /idstack:assessment-design is the natural next step." **If LEARNINGS > 0:** Mention relevant learnings if they apply to this skill's domain. Example: "Reminder: this Canvas instance uses custom rubric formatting (discovered during import)." diff --git a/skills/needs-analysis/SKILL.md b/skills/needs-analysis/SKILL.md index 74d402c..1624405 100644 --- a/skills/needs-analysis/SKILL.md +++ b/skills/needs-analysis/SKILL.md @@ -253,15 +253,15 @@ fi ``` **If QUALITY_TREND is shown:** Synthesize a welcome-back message. Example: "Welcome back. -Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /learning-objectives." +Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /idstack:learning-objectives." Keep it to 2-3 sentences. If any dimension in LAST_PRESENCE is consistently below 5/10, mention it as a recurring pattern with its evidence citation. **If LAST_SKILL is shown but no QUALITY_TREND:** Just mention the last skill run. -Example: "Welcome back. Last session you ran /course-import." +Example: "Welcome back. Last session you ran /idstack:course-import." **If SUGGESTED_NEXT is shown:** Mention the suggested next skill naturally. -Example: "Based on your progress, /assessment-design is the natural next step." +Example: "Based on your progress, /idstack:assessment-design is the natural next step." **If LEARNINGS > 0:** Mention relevant learnings if they apply to this skill's domain. Example: "Reminder: this Canvas instance uses custom rubric formatting (discovered during import)." diff --git a/skills/pipeline/SKILL.md b/skills/pipeline/SKILL.md index 6cc6362..bdb145b 100644 --- a/skills/pipeline/SKILL.md +++ b/skills/pipeline/SKILL.md @@ -253,15 +253,15 @@ fi ``` **If QUALITY_TREND is shown:** Synthesize a welcome-back message. Example: "Welcome back. -Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /learning-objectives." +Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /idstack:learning-objectives." Keep it to 2-3 sentences. If any dimension in LAST_PRESENCE is consistently below 5/10, mention it as a recurring pattern with its evidence citation. **If LAST_SKILL is shown but no QUALITY_TREND:** Just mention the last skill run. -Example: "Welcome back. Last session you ran /course-import." +Example: "Welcome back. Last session you ran /idstack:course-import." **If SUGGESTED_NEXT is shown:** Mention the suggested next skill naturally. -Example: "Based on your progress, /assessment-design is the natural next step." +Example: "Based on your progress, /idstack:assessment-design is the natural next step." **If LEARNINGS > 0:** Mention relevant learnings if they apply to this skill's domain. Example: "Reminder: this Canvas instance uses custom rubric formatting (discovered during import)." diff --git a/skills/red-team/SKILL.md b/skills/red-team/SKILL.md index f8fa417..6c7adef 100644 --- a/skills/red-team/SKILL.md +++ b/skills/red-team/SKILL.md @@ -256,15 +256,15 @@ fi ``` **If QUALITY_TREND is shown:** Synthesize a welcome-back message. Example: "Welcome back. -Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /learning-objectives." +Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /idstack:learning-objectives." Keep it to 2-3 sentences. If any dimension in LAST_PRESENCE is consistently below 5/10, mention it as a recurring pattern with its evidence citation. **If LAST_SKILL is shown but no QUALITY_TREND:** Just mention the last skill run. -Example: "Welcome back. Last session you ran /course-import." +Example: "Welcome back. Last session you ran /idstack:course-import." **If SUGGESTED_NEXT is shown:** Mention the suggested next skill naturally. -Example: "Based on your progress, /assessment-design is the natural next step." +Example: "Based on your progress, /idstack:assessment-design is the natural next step." **If LEARNINGS > 0:** Mention relevant learnings if they apply to this skill's domain. Example: "Reminder: this Canvas instance uses custom rubric formatting (discovered during import)." diff --git a/templates/preamble.md b/templates/preamble.md index 213ddf4..9b45c37 100644 --- a/templates/preamble.md +++ b/templates/preamble.md @@ -233,15 +233,15 @@ fi ``` **If QUALITY_TREND is shown:** Synthesize a welcome-back message. Example: "Welcome back. -Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /learning-objectives." +Quality score trend: 62 -> 68 -> 72 over 3 reviews. Last skill: /idstack:learning-objectives." Keep it to 2-3 sentences. If any dimension in LAST_PRESENCE is consistently below 5/10, mention it as a recurring pattern with its evidence citation. **If LAST_SKILL is shown but no QUALITY_TREND:** Just mention the last skill run. -Example: "Welcome back. Last session you ran /course-import." +Example: "Welcome back. Last session you ran /idstack:course-import." **If SUGGESTED_NEXT is shown:** Mention the suggested next skill naturally. -Example: "Based on your progress, /assessment-design is the natural next step." +Example: "Based on your progress, /idstack:assessment-design is the natural next step." **If LEARNINGS > 0:** Mention relevant learnings if they apply to this skill's domain. Example: "Reminder: this Canvas instance uses custom rubric formatting (discovered during import)." diff --git a/test/mutation-test.sh b/test/mutation-test.sh index 665d217..5ef7228 100755 --- a/test/mutation-test.sh +++ b/test/mutation-test.sh @@ -100,6 +100,17 @@ sed -i.bak 's|`/idstack:learning-objectives`|`/learning-objectives`|' \ regen expect_fail "bare /skill reference regression" "$WORK/r/test/smoke-test.sh" "$WORK/r" +# 4b. UNBACKTICKED bare /skill in the preamble returns -> smoke-test must fail. +# The guard above matched only backticked refs until v3.3.0.1, so three plain-prose +# examples sat in the preamble's context-recovery section telling the model to say +# "/assessment-design is the natural next step" — a command that does nothing. The +# preamble is spliced into all 22 skill files, so this reached every user. +fresh +sed -i.bak 's|/idstack:assessment-design is the natural next step|/assessment-design is the natural next step|' \ + "$WORK/r/templates/preamble.md" +regen +expect_fail "unbackticked bare /skill in preamble regression" "$WORK/r/test/smoke-test.sh" "$WORK/r" + # 5. pipeline unnamespaced Skill invocation returns -> smoke-test must fail fresh sed -i.bak 's|skill: "idstack:needs-analysis"|skill: "needs-analysis"|' \ diff --git a/test/smoke-test.sh b/test/smoke-test.sh index 7d3dab5..d6f8d8f 100755 --- a/test/smoke-test.sh +++ b/test/smoke-test.sh @@ -165,13 +165,27 @@ done # User-facing skill references must be namespaced /idstack: — the Codex # translation rule strips that prefix; a bare /skill renders as an invalid -# command in both CLIs. (Frontmatter descriptions are exempt; this bans the -# backticked in-body form.) -BARE_SLASH_RE='`/(needs-analysis|learning-objectives|assessment-design|course-builder|course-quality-review|accessibility-review|red-team|course-export|course-import|pipeline|learn)`' +# command in both CLIs. (Frontmatter descriptions are exempt.) +# +# This matched only the backticked form until v3.3.0.1, which let three +# unbackticked examples sit in the preamble's context-recovery section — the +# model copied them and told users to run "/assessment-design", which does +# nothing. The leading class covers a command position: line start, whitespace, +# an opening quote/paren, or a backtick. It deliberately does NOT match a `/` +# preceded by a path character, so `.idstack/exports//red-team.html` +# stays legal, and it can't match `/idstack:` because the skill name +# there does not follow the slash. +BARE_SLASH_RE='(^|[[:space:]"(`])/(needs-analysis|learning-objectives|assessment-design|course-builder|course-quality-review|accessibility-review|red-team|course-export|course-import|pipeline|learn)\b' +# Frontmatter stays exempt: `description:` is prose the CLI shows in a skill +# picker, not a command anyone types. STRIP_FM drops everything through the +# closing `---` so only the body is scanned. Later `---` horizontal rules in +# the body keep incrementing c, which is harmless once c>=2. +STRIP_FM='awk "/^---\$/{c++; next} c>=2"' for skill in $SKILLS; do - check "$skill SKILL.md.tmpl free of bare backticked /skill refs" "! grep -E '$BARE_SLASH_RE' '$IDSTACK_DIR/skills/$skill/SKILL.md.tmpl'" + check "$skill SKILL.md.tmpl body free of bare /skill refs" "! $STRIP_FM '$IDSTACK_DIR/skills/$skill/SKILL.md.tmpl' | grep -qE '$BARE_SLASH_RE'" done -check "preamble free of bare backticked /skill refs" "! grep -E '$BARE_SLASH_RE' '$IDSTACK_DIR/templates/preamble.md'" +# The preamble has no frontmatter — scan the whole file. +check "preamble free of bare /skill refs" "! grep -qE '$BARE_SLASH_RE' '$IDSTACK_DIR/templates/preamble.md'" check "no '/idstack ' space typos in templates" "! grep -rE '/idstack [a-z]' $IDSTACK_DIR/skills/*/SKILL.md.tmpl '$IDSTACK_DIR/templates/preamble.md'" check "pipeline status table uses /idstack: prefixes" "grep -qF '[done] /idstack:needs-analysis' '$IDSTACK_DIR/skills/pipeline/SKILL.md.tmpl'" check "pipeline invokes children with the idstack: namespace" "grep -qF 'skill: \"idstack:needs-analysis\"' '$IDSTACK_DIR/skills/pipeline/SKILL.md.tmpl'"