Welcome-back messages work on stock macOS now.
Install in about five minutes.
+``` + +with: + +```html +Install in 30 seconds.
+``` + +README says "30 seconds" at lines 15 and 95 and describes the same command the page displays. The page's separate "New to Claude Code?" paragraph already accounts for installing Claude Code itself, which is where the extra time went. + +- [ ] **Step 2: Make the eleven-skills count add up (finding 9)** + +Replace the `.lede` paragraph under ``: + +```html +
Eight of them run end-to-end as the standard sequence; two utilities (course-import and learn) sit outside it. Use one command for the full pipeline, or invoke any skill on its own — none of them require an existing manifest.
+``` + +with: + +```html +Eight run end-to-end as the standard sequence, /idstack:pipeline orchestrates them, and two utilities (course-import and learn) sit outside the chain. Invoke any skill on its own — none of them require an existing manifest.
Patched in v3.4.0.1 (August 7): three evidence cards on this page overstated their domain's evidence tier. They are derived from evidence/references.md now, and the test suite fails if they ever disagree again.
Patched in v3.4.0.1 (August 7): three evidence cards on this page overstated their domain's evidence tier. They are derived from evidence/references.md now, and the test suite fails if they ever disagree again. The same patch added the outbound Canvas API upload in /idstack:course-export and the git fetch in bin/idstack-update-check to the privacy policy, and named WSL or Git Bash in the Windows install instructions.
./setup registers idstack with Claude Code and installs all 11 skills. Re-run it after a git pull to update.
New to Claude Code? Download it first (free), then paste the command above. When Claude Code starts, run /idstack:pipeline.
Requires a bash shell — Terminal on macOS or Linux, WSL or Git Bash on Windows. ./setup is a bash script, so PowerShell and cmd can't run it. python3 is recommended but not required; without it, quality-score trends and search filtering are unavailable.
If something looks wrong afterwards, bin/idstack-doctor diagnoses the plugin registration, and bin/idstack-status reports course health from inside a project directory.
` lede (L1013) | the lede accounts for 8 pipeline skills + 2 asides = 10; revise so `/idstack:pipeline` is counted as the eleventh rather than only appearing in the track label, so a reader who counts reaches eleven | 9 |
+| `Install in about five minutes.
` (L1127) | → `Install in 30 seconds.` | 1 |
+| after `.install-prose` (L1136) | new `.install-prose` paragraph: bash shell required (WSL or Git Bash on Windows), python3 recommended; `bin/idstack-doctor` diagnoses a broken install, `bin/idstack-status` shows course health. **This is the primary fix for 5** — a Windows visitor is stopped by prose they can read, not by a JSON-LD string they never see | **5**, 7, 8 |
+| v3.4.0.1 patch paragraph (L1153) | add the two other shipped items per ROADMAP — `PRIVACY.md` disclosures for Canvas API uploads and `bin/idstack-update-check` git fetches, and the Windows/WSL install instructions | 4 |
+| `.footer-links` block (L1177) | add `` to `PRIVACY.md` on `main`, beside MIT License / Contribute / Roadmap | 6 |
+
+### `docs/sitemap.xml`
+
+Delete `2026-05-13 ` (L5). Closes 3.
+
+### `README.md`
+
+No change. It is already internally consistent at "30 seconds" (L15, L95); `docs/index.html`
+reconciles to README, not the reverse, because README's number describes the exact command the page
+displays. The page's separate "New to Claude Code? Download it first" line already carries the
+Claude Code install time.
+
+### `.github/workflows/static.yml`
+
+Add the staging step from D1; repoint `upload-pages-artifact` at `_site`. Closes 10 and 11.
+
+### `superpowers/specs/`, `superpowers/plans/`
+
+`git mv docs/superpowers/specs/2026-08-12-documentation-accuracy-design.md` and
+`git mv docs/superpowers/plans/2026-08-12-documentation-accuracy.md` to the repo-root
+`superpowers/` tree. `superpowers/specs/` already exists (this document); `superpowers/plans/` must
+be created first — `git mv` will not create it. Remove the now-empty `docs/superpowers/`. Closes 10.
+
+### `test/check-doc-accuracy.py`, `test/mutation-test.sh`
+
+Add the D3 guard and its mutation.
+
+## Verification
+
+Success criteria, each independently checkable:
+
+1. `python3 test/check-doc-accuracy.py .` → exit 0 with the new check present.
+2. `./test/smoke-test.sh` → green (it runs the validator and the `og-template.html` assertions).
+3. `python3 test/check-evidence-cards.py .` → green, unchanged.
+4. `./test/mutation-test.sh` → mutation 22 reports `GUARDED`; every prior mutation still `GUARDED`.
+5. Reintroducing `dateModified` by hand makes check 1 fail — confirms the guard bites outside the
+ mutation harness.
+6. Staging step simulated locally (`rm -rf _site && cp -R docs _site && rm -rf _site/superpowers &&
+ rm -f _site/og-template.html`) → `_site` contains `index.html`, `sitemap.xml`, `robots.txt`,
+ `CNAME`, both favicons, `og-image.png`, and `why-ai-native.md` (raw Markdown, intended public
+ content — see Non-goals); contains neither `superpowers/` nor `og-template.html`.
+7. Post-merge: `curl -o /dev/null -w "%{http_code}"` on
+ `https://idstack.org/superpowers/specs/2026-08-12-documentation-accuracy-design.md` and on
+ `https://idstack.org/og-template.html` → both 404. `https://idstack.org/` → 200.
+8. Re-run the outbound link sweep over `docs/index.html` — all links 200, including the new
+ `PRIVACY.md` link.
+
+## Non-goals
+
+- **Repo About blurb, topics, homepage URL.** Checked via `gh repo view`; current and accurate.
+- **Any visual redesign.** D4 constrains this to existing classes.
+- **`docs/why-ai-native.md`.** Served as raw Markdown at idstack.org, but it is intended public
+ content, linked from README, and reachable only by direct URL. Out of scope.
+- **Rewriting the What's-new section beyond finding 4.** Only the incomplete v3.4.0.1 note changes.
+- **A general link-checker in CI.** All 11 links currently resolve; adding network-dependent checks
+ to the suite is a separate decision with its own flakiness tradeoff.
+
+## Note on this document's location
+
+Written to `superpowers/specs/` at the repo root, deviating from the brainstorming skill's
+`docs/superpowers/specs/` default. That default is finding 10 — following it would publish this
+design document at idstack.org, which is the defect being fixed.
diff --git a/test/check-doc-accuracy.py b/test/check-doc-accuracy.py
index 023f54e..56d4527 100755
--- a/test/check-doc-accuracy.py
+++ b/test/check-doc-accuracy.py
@@ -74,6 +74,37 @@ def check_binaries_and_flags(root, problems):
problems.append("README.md references non-executable binary: %s" % ref)
+def check_no_stale_dates(root, problems):
+ """Assert two deleted date fields have not come back.
+
+ docs/index.html carried a JSON-LD "dateModified" and docs/sitemap.xml a
+ . Both were deleted rather than corrected: no CI check can assert
+ such a date is current without failing on commits that did not introduce
+ the defect (a PR left open a week, a merge dated after the docs edit), and
+ a check that cries wolf is one people learn to bypass. Absence is the only
+ assertion here that cannot false-positive.
+
+ See superpowers/specs/2026-08-14-github-page-accuracy-design.md, D2 and D3.
+ """
+ index_html = os.path.join(root, "docs", "index.html")
+ if os.path.isfile(index_html):
+ with open(index_html, "r", encoding="utf-8") as f:
+ if "dateModified" in f.read():
+ problems.append(
+ "docs/index.html reintroduced dateModified; it was removed "
+ "because it cannot be kept accurate (spec D2)"
+ )
+
+ sitemap = os.path.join(root, "docs", "sitemap.xml")
+ if os.path.isfile(sitemap):
+ with open(sitemap, "r", encoding="utf-8") as f:
+ if "lastmod" in f.read():
+ problems.append(
+ "docs/sitemap.xml reintroduced lastmod; it was removed "
+ "because it cannot be kept accurate (spec D2)"
+ )
+
+
def check_public_surfaces(root, problems):
v_file = os.path.join(root, "VERSION")
if not os.path.isfile(v_file):
@@ -187,6 +218,7 @@ def main():
check_manifest_schema_version(root, problems)
check_binaries_and_flags(root, problems)
check_public_surfaces(root, problems)
+ check_no_stale_dates(root, problems)
check_developer_surfaces(root, problems)
for p in problems:
diff --git a/test/mutation-test.sh b/test/mutation-test.sh
index 84d1716..bd11cf3 100755
--- a/test/mutation-test.sh
+++ b/test/mutation-test.sh
@@ -303,8 +303,10 @@ fresh
python3 - "$WORK/r/docs/index.html" <<'PY'
import sys
p = sys.argv[1]; s = open(p).read()
-s = s.replace("Install in about five minutes.
",
- "Install in about five minutes.
\n"
+old = "Install in 30 seconds.
"
+assert s.count(old) == 1, 'anchor not unique: %d' % s.count(old)
+s = s.replace(old,
+ "Install in 30 seconds.
\n"
" Also runs in OpenAI Codex CLI.
", 1) # IDSTACK_CLI_LEAK_ALLOW
open(p,'w').write(s)
PY
@@ -320,8 +322,10 @@ fresh
python3 - "$WORK/r/docs/index.html" <<'PY'
import sys
p = sys.argv[1]; s = open(p).read()
-s = s.replace("Install in about five minutes.
",
- "Install in about five minutes.
\n"
+old = "Install in 30 seconds.
"
+assert s.count(old) == 1, 'anchor not unique: %d' % s.count(old)
+s = s.replace(old,
+ "Install in 30 seconds.
\n"
" Reviewed by Gemini Code Assist. Also runs in Codex CLI.
", 1) # IDSTACK_CLI_LEAK_ALLOW
open(p,'w').write(s)
PY
@@ -383,6 +387,19 @@ open(p,'w').write(s)
PY
expect_fail "non-existent binary reference in README" "$WORK/r/test/smoke-test.sh" "$WORK/r"
+# 22. dateModified reintroduced into the landing page -> smoke-test must fail.
+# The field was deleted rather than corrected (spec D2); this proves the
+# absence assertion in check-doc-accuracy.py actually guards that decision.
+fresh
+python3 - "$WORK/r/docs/index.html" <<'PY'
+import sys
+p = sys.argv[1]; s = open(p).read()
+s = s.replace('"datePublished": "2026-04-20",',
+ '"datePublished": "2026-04-20",\n "dateModified": "2026-08-06",', 1)
+open(p, 'w').write(s)
+PY
+expect_fail "dateModified reintroduced into docs/index.html" "$WORK/r/test/smoke-test.sh" "$WORK/r"
+
echo ""
echo "guarded: $pass NOT guarded: $fail skipped: $skip"
[ "$fail" -eq 0 ]
diff --git a/test/smoke-test.sh b/test/smoke-test.sh
index 143e0a6..15ab2b8 100755
--- a/test/smoke-test.sh
+++ b/test/smoke-test.sh
@@ -390,11 +390,15 @@ check "generator takes no --target flag" "! grep -q -- '--target' '$IDSTACK_DIR/
check "resolve chain drops the ~/.agents fallbacks" "! grep -q '\.agents/' '$IDSTACK_DIR/templates/snippets/idstack-resolve.sh'"
check "preamble embeds no ~/.agents fallbacks" "! grep -q '\.agents/' '$IDSTACK_DIR/templates/preamble.md'"
-# Repo-wide sweep for the retired CLI's name. Two exemptions:
+# Repo-wide sweep for the retired CLI's name. Three exemptions:
#
# 1. CHANGELOG.md — the release record, which has to keep describing what was
# removed and how to clean up after it.
-# 2. Lines tagged IDSTACK_CLI_LEAK_ALLOW. Three kinds of line carry the tag:
+# 2. .superpowers/, .gstack/, .idstack/, .claude/ — git-ignored tool scratch
+# directories. Implementation reports and review notes written during
+# development are not shipped and CI never sees them (fresh checkout), but
+# they can discuss the sweep and trip it unreliably.
+# 3. Lines tagged IDSTACK_CLI_LEAK_ALLOW. Three kinds of line carry the tag:
# this block's own patterns, the dated release note on the landing page,
# and the comments crediting "Gemini Code Assist" — a PR-review bot # IDSTACK_CLI_LEAK_ALLOW
# that flagged the version classifier four times, unrelated to the CLI and
@@ -408,7 +412,7 @@ check "preamble embeds no ~/.agents fallbacks" "! grep -q '\.agents/' '$IDSTACK_
CLI_LEAK_RE='codex|gemini' # IDSTACK_CLI_LEAK_ALLOW
CLI_LEAK="$(grep -rIiE "$CLI_LEAK_RE" "$IDSTACK_DIR" \
--exclude-dir=.git --exclude-dir=.gstack --exclude-dir=.idstack \
- --exclude-dir=.claude --exclude=CHANGELOG.md 2>/dev/null || true)"
+ --exclude-dir=.claude --exclude-dir=.superpowers --exclude=CHANGELOG.md 2>/dev/null || true)"
CLI_LEAK="$(printf '%s' "$CLI_LEAK" | grep -vF 'IDSTACK_CLI_LEAK_ALLOW' || true)"
# Printed through the command itself, not tested with -z, so a failure names
# the offending lines instead of just saying the string was non-empty.
Install in about five minutes.
", - "Install in about five minutes.
\n" +old = "Install in 30 seconds.
" +assert s.count(old) == 1, 'anchor not unique: %d' % s.count(old) +s = s.replace(old, + "Install in 30 seconds.
\n" "Also runs in OpenAI Codex CLI.
", 1) # IDSTACK_CLI_LEAK_ALLOW open(p,'w').write(s) PY @@ -320,8 +322,10 @@ fresh python3 - "$WORK/r/docs/index.html" <<'PY' import sys p = sys.argv[1]; s = open(p).read() -s = s.replace("Install in about five minutes.
", - "Install in about five minutes.
\n" +old = "Install in 30 seconds.
" +assert s.count(old) == 1, 'anchor not unique: %d' % s.count(old) +s = s.replace(old, + "Install in 30 seconds.
\n" "Reviewed by Gemini Code Assist. Also runs in Codex CLI.
", 1) # IDSTACK_CLI_LEAK_ALLOW open(p,'w').write(s) PY @@ -383,6 +387,19 @@ open(p,'w').write(s) PY expect_fail "non-existent binary reference in README" "$WORK/r/test/smoke-test.sh" "$WORK/r" +# 22. dateModified reintroduced into the landing page -> smoke-test must fail. +# The field was deleted rather than corrected (spec D2); this proves the +# absence assertion in check-doc-accuracy.py actually guards that decision. +fresh +python3 - "$WORK/r/docs/index.html" <<'PY' +import sys +p = sys.argv[1]; s = open(p).read() +s = s.replace('"datePublished": "2026-04-20",', + '"datePublished": "2026-04-20",\n "dateModified": "2026-08-06",', 1) +open(p, 'w').write(s) +PY +expect_fail "dateModified reintroduced into docs/index.html" "$WORK/r/test/smoke-test.sh" "$WORK/r" + echo "" echo "guarded: $pass NOT guarded: $fail skipped: $skip" [ "$fail" -eq 0 ] diff --git a/test/smoke-test.sh b/test/smoke-test.sh index 143e0a6..15ab2b8 100755 --- a/test/smoke-test.sh +++ b/test/smoke-test.sh @@ -390,11 +390,15 @@ check "generator takes no --target flag" "! grep -q -- '--target' '$IDSTACK_DIR/ check "resolve chain drops the ~/.agents fallbacks" "! grep -q '\.agents/' '$IDSTACK_DIR/templates/snippets/idstack-resolve.sh'" check "preamble embeds no ~/.agents fallbacks" "! grep -q '\.agents/' '$IDSTACK_DIR/templates/preamble.md'" -# Repo-wide sweep for the retired CLI's name. Two exemptions: +# Repo-wide sweep for the retired CLI's name. Three exemptions: # # 1. CHANGELOG.md — the release record, which has to keep describing what was # removed and how to clean up after it. -# 2. Lines tagged IDSTACK_CLI_LEAK_ALLOW. Three kinds of line carry the tag: +# 2. .superpowers/, .gstack/, .idstack/, .claude/ — git-ignored tool scratch +# directories. Implementation reports and review notes written during +# development are not shipped and CI never sees them (fresh checkout), but +# they can discuss the sweep and trip it unreliably. +# 3. Lines tagged IDSTACK_CLI_LEAK_ALLOW. Three kinds of line carry the tag: # this block's own patterns, the dated release note on the landing page, # and the comments crediting "Gemini Code Assist" — a PR-review bot # IDSTACK_CLI_LEAK_ALLOW # that flagged the version classifier four times, unrelated to the CLI and @@ -408,7 +412,7 @@ check "preamble embeds no ~/.agents fallbacks" "! grep -q '\.agents/' '$IDSTACK_ CLI_LEAK_RE='codex|gemini' # IDSTACK_CLI_LEAK_ALLOW CLI_LEAK="$(grep -rIiE "$CLI_LEAK_RE" "$IDSTACK_DIR" \ --exclude-dir=.git --exclude-dir=.gstack --exclude-dir=.idstack \ - --exclude-dir=.claude --exclude=CHANGELOG.md 2>/dev/null || true)" + --exclude-dir=.claude --exclude-dir=.superpowers --exclude=CHANGELOG.md 2>/dev/null || true)" CLI_LEAK="$(printf '%s' "$CLI_LEAK" | grep -vF 'IDSTACK_CLI_LEAK_ALLOW' || true)" # Printed through the command itself, not tested with -z, so a failure names # the offending lines instead of just saying the string was non-empty.