Addresses both review findings on #993.
1. skill_plugin_emitter.py's module docstring still described the behaviour this
PR removed. Its tree diagram called plugin.json the "manifest with
./skills/<slug> + attribution", and the rights-gate paragraph said
cleared_for_distribution is recorded "in the manifest" -- both now the
sidecar. A docstring asserting the opposite of its own file's point is worse
than no docstring, and it is what `--help` readers see.
Also corrects a third instance the review did not name but which shares the
root cause: the tree diagram never listed authoring-notes.json at all, even
though this PR's fix is what creates it. Added, with the issue #954 reason
stated inline so the next reader knows why provenance cannot live in the
manifest.
2. CLAUDE.md said the resident core is 2,066 tokens while, twelve lines later,
the same file said 2,101. 2,066 predates the worked invocation block added
for write-a-skill checklist item 5; token_budget_estimator.py reports 2,101
on the current tree, matching CHANGELOG.md and the PR body. CLAUDE.md was
the only stale copy and it contradicted itself.
Docstring-only and prose-only; no behaviour change. Verified the emitter still
emits both plugin.json and authoring-notes.json via --sample after the edit.
Gates: compileall, check_plugin_json --all, check_paths, check_frontmatter,
check_dual_publish, check_model_freshness, smoke_scripts (696/696),
derive_counters --check, book_skill_validator --strict.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UySnyf5upm4y8xhYA3w6yw
Addresses both review findings on #993.
1. The changelog/CLAUDE.md counter line said "commands 147 → 150", which
asserts this plugin adds three commands. It adds exactly one
(commands/cs-spinning-up-deep-rl.md). 147 was this branch's pre-merge
baseline; after merging dev the delta had to be restated against dev's
baseline, and that one figure was carried over unchanged while the others
were updated. Verified empirically rather than by arithmetic: derive_counters
on an origin/dev worktree reports 149 commands, and the raw command-file
count goes 281 → 282 across the merge. Corrected to 149 → 150. The other
three figures on that line (skills 387 → 388, agents 117 → 118, plugins
98 → 99) were already right.
2. README POWERFUL-tier row had a stray space before a comma:
"calculator) , **spinning-up-deep-rl**". Removed.
Neither affected derive_counters --check, which reads the tree rather than the
prose -- which is exactly why a wrong delta in prose can survive a green gate,
and why it was worth fixing in a repo this strict about counters being
trustworthy.
Gates re-run: compileall, check_plugin_json --all, check_paths,
check_frontmatter, check_dual_publish, check_model_freshness, smoke_scripts
(696/696), derive_counters --check.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UySnyf5upm4y8xhYA3w6yw
dev moved: PR #994 landed engineering/deep-learning-book, which collides with
this branch on every headline-counter and registry surface.
Conflicts resolved in four files, keeping both sides' content:
- .claude-plugin/marketplace.json -- both plugin entries kept; the registry now
carries spinning-up-deep-rl and deep-learning-book. 99 plugins.
- CHANGELOG.md -- both Unreleased sections kept.
- CLAUDE.md, README.md -- dev's prose taken as the newer baseline, then this
branch's engineering-row entry restored and every counter re-derived rather
than hand-picked from either side.
Counters re-derived from the merged tree with derive_counters.py, which is the
ground truth, and trued up across all five surfaces: 388 skills, 99 plugins,
727 tools, 842 references, 118 agents, 150 commands.
Both changelog/CLAUDE.md delta lines are restated: each side was written against
its own base and both claimed 386 -> 387, which is no longer true of either now
that they land together. This branch's entry is now stated as the delta on top of
deep-learning-book.
Gates re-run on the resolved merge: no conflict markers left in the tree,
compileall, check_plugin_json --all, check_skill_names, check_paths,
check_frontmatter, check_dual_publish, check_model_freshness, smoke_scripts
(696/696), derive_counters --check, book_skill_validator --strict, and a
JSON/YAML parse of every file touched.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UySnyf5upm4y8xhYA3w6yw
Ninth review on PR #994 found that --underparameterized-max and
--overparameterized-min, added two commits earlier, were never checked against each
other. Reproduced, and the consequence is sharper than a silent misclassification:
with --underparameterized-max 20 --overparameterized-min 5 and a ratio of 10, the
tool reported a model ten times overparameterized as "underparameterized" and exited
0. That verdict ranks "shrink the model" FIRST rather than last, inverting the exact
double-descent correction this tool exists to apply.
Added an argparse guard rejecting under-max >= over-min with a message naming both
values (exit 2, the documented usage-error code). Equal bands are rejected too,
since they leave the near-interpolation regime unreachable.
Verified: inverted and equal bands both exit 2; a valid override still moves the
regime (--overparameterized-min 500 gives near-interpolation); defaults unchanged at
overparameterized / OVERFIT / 240.0 with smaller-model last; the other exit codes
still 1 for an action, 0 for balanced, 4 for a leaky split.
Worth noting for the two flags' own history: they were added to close a consistency
nit, and introduced this defect in doing so. A new option is new surface, and its
interaction with existing options is part of it.
Gates green: compileall, check_paths, check_frontmatter, check_dual_publish,
check_model_freshness, smoke_scripts (696 passed), derive_counters --check,
check_skill_names, check_plugin_json, book_skill_validator, and --help +
--sample --output json on all four tools.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s
Eighth review on PR #994 found that _matches()'s (?:s|es)? suffix reintroduced a
smaller version of the substring bug it was written to fix: "rag" + "es" matches the
standalone word "rages", so --goal "why overfitting still rages in large models"
exited 3, refused as out-of-scope retrieval-augmented-generation work.
Reproduced before fixing, then checked whether the -es branch earns its keep at all.
It does not: every keyword in the table ending in s, x, z, ch or sh is already plural
or non-count (basics, features, foundations, prerequisites, statistics, speech,
mlops, fairness, mathematics, time series), so no token needs -es appended. Narrowed
the auto-plural to plain -s and documented that irregular forms belong in
SURFACE_FORMS, spelled out, the way fine-tuning, prompting and agentic already are.
Verified: "rages" no longer matches while standalone "rag" still does; transformers,
embeddings, autoencoders and agentic still match; the goal above is now correctly
unroutable (exit 4) rather than confidently misrouted. RLHF, LoRA fine-tuning, RAG
pipelines and prompt/agent goals still exit 3; sequence, vision, generative and
practitioner routing unchanged.
That makes two rounds of false out-of-scope refusals from the same root cause —
approximate string matching standing in for a word list. The refusal path is the
part of this tool users are least able to second-guess, so it is the wrong place to
approximate.
Gates green: compileall, check_paths, check_frontmatter, check_dual_publish,
check_model_freshness, smoke_scripts (696 passed), derive_counters --check,
check_skill_names, check_plugin_json, book_skill_validator, and --help +
--sample --output json on all four tools.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s
Seventh review on PR #994 noted that capacity_planner.py exposes --overfit-rel-gap
but hardcodes the two params-per-example regime bands, unlike its sibling scripts
where every threshold is overridable. The reviewer called it fine as shipped; the
inconsistency is small enough to close rather than carry.
The band matters more than a typical default: it decides whether "shrink the model"
is ranked last, which is the double-descent correction this tool exists to apply.
The interpolation point depends on task, architecture and label noise, so a user
whose model sits elsewhere had no way to say so.
Adds --underparameterized-max and --overparameterized-min, threaded through plan()
and classify_regime() as keyword arguments defaulting to the existing constants, and
reports all three thresholds in --output json the way training_diagnostics.py already
does. The help text repeats that these are heuristic bands, not a threshold theorem.
Defaults preserve behaviour exactly: the --sample fixture still reports
overparameterized / OVERFIT / 240.0 params-per-example with smaller-model ranked
last, identical to before the change. An override demonstrably moves the regime
(--overparameterized-min 500 reclassifies the same model as near-interpolation).
Exit codes unchanged: 1 for an action, 0 for balanced, 4 for a leaky split.
Not fixed here: CHANGELOG.md's duplicate [Unreleased] header, also noted in that
review. Verified pre-existing rather than introduced by this branch — the count is
2 at the merge-base with main and 2 at HEAD. Left for a separate changelog cleanup.
Gates green: compileall, check_paths, check_frontmatter, check_dual_publish,
check_model_freshness, smoke_scripts (696 passed), derive_counters --check,
check_skill_names, check_plugin_json, book_skill_validator, and --help +
--sample --output json on all four tools.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s
Sixth review on PR #994 noted that --include-intro appeared to have an observable
effect only on the complete lane. Checked it, and it was worse than reported: the
flag was inert on every lane, complete included.
Two reasons compounded. ch01 is not a prerequisite of any chapter, so it never
arrived through prerequisite closure; and the only lane that targets it, complete,
skipped the ch01 filter entirely. The filter therefore removed a chapter that was
never present, and the flag that controlled it could not change any output.
This also means my own verification of the parameter rename in c75500f was
inconclusive: it compared the complete lane with the flag against the vision lane
without it, and those differ for reasons unrelated to the flag. A test that cannot
fail proves nothing.
Inverted the logic so the flag adds ch01 rather than un-removing it, which gives it
a real effect on every lane while leaving complete unchanged (ch01 is already among
its targets). Help text now states what it does and that no lane pulls ch01 in on
its own.
Verified per lane: complete unchanged; vision, generative and foundations each gain
ch01 with the flag and are untouched without it; ch01 sorts first and never precedes
a chapter it would violate. Routing and both refusal paths are unchanged — sequence,
vision, generative and practitioner all route as before, out-of-scope still exits 3,
unroutable still exits 4.
Gates green: compileall, check_paths, check_frontmatter, check_dual_publish,
check_model_freshness, smoke_scripts (696 passed), derive_counters --check,
check_skill_names, check_plugin_json, book_skill_validator, and --help +
--sample --output json on all four tools.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s
Fifth review on PR #994 found the one numeric spec field I missed when adding typed
validation in the previous commit: embedding's seq_len still went through a bare
int(), so it bypassed the checks every sibling field had just been given.
Both failure modes reproduced before fixing:
seq_len "ten" -> uncaught ValueError, traceback, exit 1 (documented: exit 4)
seq_len 0 -> no error at all; reported a plausible "0x8" layer with zero
activation elements and exited 0, presenting a degenerate model
as a valid one
Routed through _positive_int with the existing default (the incoming sequence
length, or 1), so both now exit 4 naming the layer and field. Verified the default
fallback still resolves to the input shape (16x8) and an explicit valid seq_len is
still honoured (32x8).
Swept the file afterwards rather than fixing only the reported instance: all 13
numeric spec fields now go through _positive_int, and no raw int() on a spec field
remains. The reference specs are unchanged — convnet 545,098 parameters, transformer
asset 7,087,872.
Gates green: compileall, check_paths, check_frontmatter, check_dual_publish,
check_model_freshness, smoke_scripts (696 passed), derive_counters --check,
check_skill_names, check_plugin_json, book_skill_validator, and --help +
--sample --output json on all four tools.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s
Fourth review on PR #994 raised two findings against this plugin's scripts. Both
reproduced before fixing; the review's other findings are against marketing/linkedin,
which this branch carries from main but does not touch (see the PR comment).
1. reading_path_planner.py matched keywords by bare substring, so "rag" matched
inside "storage", "lora" inside "exploratory", "conv" inside "converge" and
"text" inside "context". Confirmed: --goal "train models for image storage and
retrieval" exited 3, confidently refused as out-of-scope RAG work, and
"an exploratory look at optimization" exited 3 citing LoRA. A tool whose stated
design is to refuse rather than guess was guessing, and doing it with certainty.
Matching is now word-boundary anchored with an optional plural, plus an explicit
surface-form table for the few tokens whose inflections a word-boundary match
would otherwise miss (fine-tuning, prompting, agentic). Verified: both goals above
now route correctly (exit 0 / the optimization lane), "converge" reaches the
optimization lane rather than vision, and the real refusals still refuse — RLHF,
LoRA fine-tuning, RAG pipelines and prompt/agent goals all still exit 3.
2. model_arithmetic.py documented exit 4 for a spec it cannot parse but only caught
SpecError and ShapeError, so malformed input escaped as a traceback with exit 1.
Confirmed across five cases: a non-dict top-level JSON, a non-dict layer entry,
stride 0, groups 0, and a non-numeric filters value. Numeric fields now go through
a checked accessor that rejects non-integer and non-positive values, the input
layer's shape is validated, and the top-level spec and every layer entry are
type-checked. All five now exit 4 with a message naming the layer and field.
Regression battery over eight goals routes exactly as before; the convnet sample
still reports 545,098 parameters and the transformer asset 7,087,872.
Gates green: compileall, check_paths, check_frontmatter, check_dual_publish,
check_model_freshness, smoke_scripts (696 passed), derive_counters --check,
check_skill_names, check_plugin_json, book_skill_validator, and --help +
--sample --output json on all four tools.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s
Third review on PR #994 found a real bug in the flagship example asset. Verified
before fixing: assets/example_layer_spec.json reported 1,207,962,624 parameters
for the feedforward up-projection instead of 2,362,368 — off by exactly 512x, the
sequence length — putting the block's total at ~1.21B instead of ~7.09M.
Root cause was in the tool, not only the asset. model_arithmetic.py's mha layer
emits (seq, d_model) but linear refused any 2-D input, so the only way to attach a
feedforward block was to flatten first. Flattening collapses all 512 positions into
one 393,216-element vector, which models a dense layer over the whole sequence — a
different layer, with seq_len times the parameters. A transformer FFN was therefore
not expressible at all, and the shipped example walked straight into it. Clean exit
is not correct numbers, which is why --sample exit-code testing never caught it.
Fixed the cause: linear on a 2-D (seq, features) input is now position-wise — one
weight matrix shared across positions, parameters independent of sequence length,
compute linear in it. Documented in the module docstring; the 3-D path still refuses
with an updated message pointing at flatten. Removed the flatten from the example
asset and recorded in its comment why it must not come back.
Verified: the corrected block reports 7,087,872 parameters, matching a hand-check of
2*(2*768) + (4*768^2+4*768) + (768*3072+3072) + (3072*768+768) exactly, and the size
of a BERT-base encoder layer. The convnet --sample is unchanged at 545,098, and
linear on 3-D input still exits 5.
Also adds the missing CHANGELOG.md [Unreleased] entry, which the same review noted:
CLAUDE.md, README.md and marketplace.json carried the new skill and its counter
deltas but CHANGELOG.md did not.
Gates green: compileall, check_paths, check_frontmatter, check_dual_publish,
check_model_freshness, smoke_scripts (696 passed), derive_counters --check,
check_skill_names, check_plugin_json, book_skill_validator, and --help +
--sample --output json on all four tools.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s
Second independent review on PR #994 observed that reading_path_planner.py's
score_lanes() broke equal-hit ties alphabetically by lane key, so SKILL.md's own
documented example "train a transformer" resolved to the practitioner lane rather
than sequence.
Reproduced: the goal hits practitioner on "train" and sequence on "transformer",
one keyword each, and alphabetical ordering picked practitioner.
Fixed the cause rather than the example. Ties now break on keyword specificity —
the lane whose longest matched keyword is longest wins — because an equal hit
count between a generic term and a discriminating one should not be settled by
luck. Lane key remains the final tie-break so ordering stays deterministic.
Regression battery over eight goals: "train a transformer" now routes to sequence;
vision, generative, foundations, practitioner, complete, representation and
sequence goals all route exactly as before. Refusal paths unchanged (out-of-scope
exit 3, unroutable exit 4, sample exit 0).
Gates green after the change: compileall, check_paths, check_frontmatter,
check_dual_publish, check_model_freshness, smoke_scripts (696 passed),
derive_counters --check, check_skill_names, check_plugin_json, book_skill_validator,
and --help + --sample --output json on all four tools.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s
Two small findings from the automated review on PR #994, both verified against the
source before fixing.
1. reading_path_planner.py: the plan() parameter was named include_optional while
the CLI flag and call site both use include_intro, and it only ever gates ch01.
Renamed the parameter and its use for consistency. Behavior unchanged, confirmed
both ways: --include-intro keeps ch01 first, the default drops it.
2. model_arithmetic.py: conv2d "same" padding computes ceil(H / stride), which is
the TensorFlow/Keras SAME convention, and the tool did not disclose which
framework it matches. Documented it in the module docstring — including that
PyTorch's padding='same' is symmetric-only and rejects a stride other than 1, so
a strided PyTorch layer will not match, with "valid" named as the exact-case
workaround — plus a pointer comment at the computation itself. No arithmetic
change; the sample stack reports identical parameters and FLOPs.
The reviewer's third point was that it could not execute the gates in a sandboxed
environment. No code change: those gates were run locally and are green.
Verified after the change: compileall, check_paths, check_frontmatter,
check_dual_publish, check_model_freshness, smoke_scripts (696 passed),
derive_counters --check, check_skill_names, check_plugin_json, the book-skill
validator, and --sample --output json on all four tools.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s
CI gate G1 (scripts/check_paths.py) failed on the previous commit: the agent and
command files live at engineering/deep-learning-book/{agents,commands}/, so bare
references/*.md and assets/*.md tokens resolved against neither the plugin root,
the file's own directory, nor the repo root — the three bases the linter accepts.
The files they point at live under skills/deep-learning-book/.
Prefix the nine offending links with skills/deep-learning-book/ so they resolve
from the plugin root. Content unchanged otherwise; SKILL.md's own relative links
were already correct and were not touched.
Reproduced the failure locally (9 unresolvable references across 4 files), then
confirmed the same check clean, plus every other blocking gate: compileall,
check_plugin_json, check_skill_names, check_frontmatter, check_dual_publish,
check_model_freshness, smoke_scripts (696 passed), derive_counters --check.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s
Addresses the review observation on #993: the compiled skill's
authoring-notes.json carried only a `source` block (how it was built) even
though its content is derived from an external MIT-licensed work, where the
rest of the repo uses an `attribution` block for that. check_plugin_json.py's
NOTES_ALLOWED permits both keys, so the two coexist.
Adds `attribution` to engineering/spinning-up-deep-rl following the shape used
by book-to-skill and skillopt-sleep: derived_from, upstream_docs, upstream_path,
original_author, original_license, original_copyright, derivation_note.
The emitter is deliberately NOT changed to synthesise this. It knows only
`--source-note` free text and a rights basis -- not an upstream URL, author or
licence -- and a half-filled attribution block is worse than none. Instead
Step 11 of conversion_workflow.md now says attribution is added by hand
whenever `--rights` is anything but internal-docs, names the field shape, and
restates that the actual obligation is the LICENSE notice and README credit --
authoring-notes.json is metadata Claude Code never reads, and a sidecar JSON
file is not a licence notice.
Gates re-run clean: check_plugin_json --all, check_paths, check_frontmatter,
check_dual_publish, check_model_freshness, smoke_scripts (692/692),
derive_counters --check, book_skill_validator --strict.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UySnyf5upm4y8xhYA3w6yw
Requested as "convert deeplearningbook.org into a skill". Built as a companion
rather than a compilation, because the repo's own rights gate forbids the latter
for a public plugin.
Why not book-to-skill: its emitter refuses a shareable package without
public-domain / open-license / internal-docs / author-permission, none of which
applies to an MIT Press title whose site states its HTML-only format exists as a
friction against copying under the authors' contract. Its rights reference lists
publishing a compiled skill of a copyrighted book to a public marketplace under
"Do not", and its hard rule 1 forbids scraping a book from the web, so the
pipeline could not have run against a URL either.
What shipped instead: the compiled-skill shape (master SKILL.md ~2.0k tokens with
chapter and topic indexes, chapters/ch01..ch20, glossary, patterns, cheatsheet)
filled with original synthesis and linking to the official free chapters. No
passages, figures, or per-paragraph paraphrase. Passes book-to-skill's own
book_skill_validator.py clean, with every file inside token_budget_estimator's caps.
The differentiator is the delta layer. A compilation freezes a source at its
publication date; this one dates it. Every chapter carries "What changed after
2016", and references/book_to_2026_delta.md gives five corrections with primary
citations and per-claim confidence levels: double descent qualifying Ch 5's
U-curve, AdamW splitting weight decay from L2, transformers displacing Ch 10's
recurrence, diffusion growing out of Ch 18's score matching, and self-supervised
learning vindicating Ch 15 while replacing its methods. Two claims are marked
contested rather than propagated, two named as folklore.
Four stdlib-only tools, each with a real refusal:
- reading_path_planner.py — prerequisite closure over the book's actual dependency
graph; exit 3 for a goal the book does not cover, exit 4 with forcing questions
- training_diagnostics.py — Ch 11's rules in priority order, so a NaN is never
reported as overfitting; exit 4 rather than diagnosing with no instruments
- capacity_planner.py — regularization ladder in cost order, "shrink the model"
ranked last in the overparameterized regime; exit 4 on a val-below-train split
- model_arithmetic.py — params/FLOPs/activation memory for conv, linear, MHA and
LSTM/GRU stacks; exit 5 naming the layer whose shapes do not connect
Also: 4 references citing 7-8 sources each, 3 assets, cs-deep-learning-tutor
agent, /cs:deep-learning + /cs:dl-reading-path + /cs:dl-diagnose.
Counters: skills 386 to 387, tools 723 to 727, refs 838 to 842, agents 116 to 117,
commands 146 to 149, plugins 97 to 98 (verified by derive_counters.py --check).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s
dev's derive_counters.py gained two additional check targets that main's copy
did not have -- mkdocs.yml's site_description and .codex-plugin/plugin.json's
description / shortDescription / longDescription. Both carried the pre-linkedin,
pre-skill-doctor numbers (380 skills / 706 tools / 823 refs / 114 agents /
138 commands / 96 plugins), so the blocking gate fails on this branch the moment
dev's checker meets main's tree.
Synced all six to the derived values: 387 skills, 723 tools, 838 references,
117 agents, 147 commands, 98 plugins.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UySnyf5upm4y8xhYA3w6yw
Runs engineering/book-to-skill end to end on its first real source: OpenAI's
Spinning Up in Deep RL (MIT, (c) 2018 OpenAI; primarily developed by Joshua
Achiam). Cloned openai/spinningup and compiled its docs/ reStructuredText tree
(38 files, ~37k words, ~49K tokens) through the full pipeline -- extract
--mode technical, analysis, 20 chapter files, glossary/patterns/cheatsheet,
master SKILL.md, validator, plugin emitter.
The compiled skill passes book_skill_validator.py in --strict mode with every
file inside budget: a 2,101-token resident core (cap 4,000) plus 20 on-demand
chapters averaging ~1,256 tokens each.
Chapter structure follows the source's own toctree rather than a heading scan:
user documentation (ch01-06), Introduction to RL Parts 1-3 (ch07-09), the
researcher essay / key papers / exercises / benchmarks (ch10-13), one chapter
per algorithm in lineage order (ch14-19: VPG to TRPO to PPO, DDPG to TD3 and
SAC), and the logger/MPI/ExperimentGrid utilities (ch20).
Rights basis is open-license, not fair use -- the emitter's Step-11 gate
refuses a shareable package without one. Upstream's MIT notice is reproduced
in full in the plugin's LICENSE beside this package's own, and README.md names
the source, the author and the source's frozen version; a sidecar JSON is not
a license notice.
Also fixes a defect the emitter only reveals at its final step:
skill_plugin_emitter.py wrote its whole `source` provenance block into
plugin.json, on a stale inline claim that `source`/`attribution` were approved
extension fields. Claude Code rejects an entire manifest on any unrecognized
key (issue #954) and scripts/check_plugin_json.py hard-fails such a manifest,
so every package the emitter produced failed the blocking CI gate on commit.
_plugin_manifest() now emits spec fields only and a new _authoring_notes()
writes .claude-plugin/authoring-notes.json. Recorded as deviation 26 in
engineering/book-to-skill/README.md; the printed marketplace.json snippet is
unchanged, since `source` is a valid key there.
Counters: skills 386 -> 387, agents 116 -> 117, commands 146 -> 147, plugins
97 -> 98. Tools and references unchanged -- a compiled knowledge base ships
notes, not scripts.
All blocking CI gates verified locally: compileall, check_plugin_json --all,
check_skill_names, check_paths, check_frontmatter, check_dual_publish,
check_model_freshness, smoke_scripts (692/692), derive_counters --check.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UySnyf5upm4y8xhYA3w6yw
Answers discussion #934, which asked for a strategic assistant for growing a
LinkedIn presence organically rather than a post generator.
Six skills under marketing/linkedin/: an orchestrator (context: fork) plus
profile, strategy, content, engagement, and analytics lanes. 17 stdlib-only
tools, 15 references, 2 agents, 8 /cs:* commands.
The design constraint is the differentiator: no LinkedIn credentials, no API
calls, no scraping, nothing auto-sent. Automated posting, connecting, and
commenting are prohibited by LinkedIn's User Agreement 8.2, and a restricted
account ends a compounding asset. linkedin_policy_gate.py runs before any
drafting and refuses seven request classes — automation, scraping, engagement
pods, bulk messaging, fake identity, fabricated proof, named third-party
automation platforms — each carrying the policy anchor and a compliant
substitute, so the gate never just says no.
Refusals are real rather than advisory. A cadence under 90 minutes a week
returns a comment-only plan instead of a schedule that dies in week five. A
newsletter whose six-month cost exceeds the budget is refused before the promise
is made. An experiment needing more posts than a quarter allows is reported
infeasible rather than quietly re-sized. The pattern miner refuses to test
anything below 10 posts and reports NOTHING_SURVIVED as a finding.
Evidence discipline: two widely repeated claims are corrected rather than
propagated. The "personalised note triples acceptance" claim is not supported by
the largest samples (acceptance is near-identical either way, ~26.4%); what a
note moves is the post-accept reply rate (~5.4% to ~9.4%), which is why the
message builder refuses an ask in a first-touch note. The ~19% in-body link
reach reduction has never been confirmed by LinkedIn as a penalty and has a
plausible dwell-time explanation, so it is a warning rather than a block. Every
reference carries per-claim confidence levels.
Accessibility is a blocking lint finding: Unicode pseudo-bold is announced by
screen readers as mathematical symbols and is not indexed by search.
All six SKILL.md files are 6/6 PASS on the write-a-skill checklist. Every tool
supports --help, --sample, and --output json with typed exit codes.
Counters: skills 380 -> 386; plugins 96 -> 97; tools 706 -> 723; refs 823 -> 838;
agents 114 -> 116; commands 138 -> 146 (derive_counters.py --check).
Also syncs three previously-merged skills (agent-memory, hivemind, skill-doctor)
into the .hermes/ and .vibe/ mirror trees, which had drifted behind .codex/.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JSPxUHU6utqme7qC6EwHEh
Two reviewer nits batched: derive_counters.py's module docstring and --check
help still described the pre-#989 three-source coverage (flagged on #989);
check_model_freshness.py's EXCLUDED_DIRS did double duty as a directory AND
filename exclusion set, which the name hid (flagged on #985 and #988's
reviews) — renamed with a comment stating both roles. No behavior change;
both gates re-verified passing.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qgc6RYXWJPr5oW9DHU7zR4
Review follow-up on #989: shortDescription/longDescription carry their own
counts and were just trued — include them in the gated source text so
standardized-phrasing claims in them are checked (non-matching prose is
simply not read). Verified: planting 997 in shortDescription fails the
gate; restored passes.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qgc6RYXWJPr5oW9DHU7zR4
Adopts the two verified findings from PR #940 (credit: @benrfairless):
- .codex-plugin/plugin.json still said v2.2.0 / 223 skills / 23 agents /
298 tools / 9 domains — roughly nine releases behind, and it is the
manifest Codex users see. Version, description, and the interface
short/long descriptions are trued to the v2.12.0 counters (380 skills /
20 domains / 706 tools / 823 refs / 114 agents / 138 commands / 96
plugins), with the top-level description written in the standardized
claim phrasing so the gate can read it.
- mkdocs.yml's site_description was content-correct after v2.12.0 but
ungated and phrased invisibly to extract_claims ('agent skills',
'installable plugins') — reworded to the standardized phrasing.
- derive_counters.py run_check() now reads both as claim sources
(mkdocs.yml restricted to the site_description line since its !!python
tags reject safe_load). Verified: planting 999/998 in the two sites
fails the gate naming both; restored values pass.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qgc6RYXWJPr5oW9DHU7zR4
Caught by review on the v2.12.0 promotion PR #985: README's Skills Overview
heading still said 370 and CLAUDE.md's footer Status line said 379 while the
banner/badges/scope line say the derived 380. Both wordings ('370 skills
across', '379 skills deployed across') were invisible to derive_counters.py's
claim patterns, which is why they could drift — reworded both into the
standardized '<N> production-ready skills across <D> domains' phrasing, made
extract_claims() validate every occurrence of a claim pattern instead of only
the first, and run_check() now reads CLAUDE.md's Status footer line alongside
Current Scope. Verified: planting 999/998 in the two lines fails the gate
naming both; restored values pass.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qgc6RYXWJPr5oW9DHU7zR4
The quality-review workflow's parse fallback emits 'unknown|0|0|0|ERROR'
whenever the tessl CLI dies (auth/quota/npm failure), and the verdict logic
only compared SCORE against the threshold — so a tool outage rendered as
0/100 'NEEDS WORK' and blocked the merge, indistinguishable from a genuinely
zero-quality skill. Both the v2.12.0 promotion PR (#985) and #984 hit this:
four skills scored an identical 0/100 with the whole review loop finishing
in ~8 seconds.
Now VSTATUS=ERROR renders as a 'TOOL ERROR (not scored)' row with the CLI's
actual output surfaced as a :⚠️: annotation and a report footer, and
does not set the blocking exit code. Genuine sub-threshold scores still
block. Verified with a mocked-tessl simulation: error -> non-blocking warn,
85/100 -> PASS, 40/100 -> blocking NEEDS WORK, all-error run -> job passes.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qgc6RYXWJPr5oW9DHU7zR4
PR #984's counter true-up bumped README badges and CHANGELOG to the derived
114 agents / 138 commands but left the CLAUDE.md Current Scope line and
marketplace.json metadata.description at the stale 111/131 (caught by review
on #984). derive_counters.py --check passed because CLAIM_PATTERNS had no
agents/commands patterns — added both (agents anchored on the "(cs-" suffix
so prose like "9 more coding agents" can't false-match), verified the new
gate fails on the pre-fix docs and passes post-fix.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qgc6RYXWJPr5oW9DHU7zR4
The Skill Security Audit failed PR #984 with 2 CRITICAL CMD-INJECT findings
on hivemind's Node scripts — pre-existing since #979 merged while Actions
wasn't triggering; touching the skill's agent files pulled it into audit
scope. Spawning headless opencode worker processes is this skill's core,
documented function (SKILL.md Prerequisites + the PR #979 dependency
disclosure), so the imports carry the auditor's own suppression directive
with the justification inline. Re-audit: PASS, 0 critical / 0 high.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qgc6RYXWJPr5oW9DHU7zR4
- CHANGELOG.md gains the [2.12.0] entry (first tagged release since v2.9.0):
consolidates the previously documented but untagged v2.10.0-v2.11.2 work,
all post-2.11.2 merges, and the full 17-issue triage sweep; the ten stacked
[Unreleased] sections are demoted into the 2.12.0 body so the Release
workflow tags and publishes the whole span. Verified parseable with
scripts/extract_release_notes.py (version 2.12.0, 554-line body).
- Version markers bumped to 2.12.0: marketplace.json metadata,
CLAUDE.md current-version header + footer.
- Counters trued to the derived values (380 skills / 96 plugins / 20 domains /
706 tools / 823 refs / 114 agents / 138 commands) in README badges + prose,
CLAUDE.md, marketplace.json, and the long-stale mkdocs.yml/docs/index.md
site description (was still claiming 345/78/17).
- Docs site regenerated via scripts/generate-docs.py (568 generated pages;
new pages for the recently merged plugins); codex/gemini mirrors resynced;
mkdocs build verified locally with the same plugin set static.yml uses
(670 HTML pages, no errors).
- Fix: the three hivemind worker personas (assets/agents/{coder,scout,tester}.md,
merged via #979 while Actions was not triggering) lacked the frontmatter
`name:` field and hard-failed the blocking G10 gate — named
hive-coder/hive-scout/hive-tester; 645 files now scan with 0 errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qgc6RYXWJPr5oW9DHU7zR4
Two doc nits from #981 review: (1) CLAUDE.md's 'Not auto-registered' paragraph used
'integrations/<name>/src/index.ts' in one sentence and 'integrations/<name>-mcp' two
sentences later — <name> meant two different things; align both to <name>-mcp.
(2) skills/pw/SKILL.md 'What's Included' listed '2 MCP servers ... integrations' with no
caveat, unlike README's equivalent line — add '(optional — not auto-registered)'.
dev landed a parallel #978 fix (deleted .mcp.json, added integrations/mcp-servers.example.json
opt-in template + README flow). Per maintainer decision, keep this PR's approach:
- README.md resolved to this branch's version (softened tagline/commands/heading + caveats).
- .mcp.json kept as empty {"mcpServers":{}} (servers not auto-registered).
- Restored dev's mcp-servers.example.json in full (a rename-merge artifact had gutted it to {}).
- Retains this PR's additive doc softening dev lacked: plugin.json + marketplace.json
descriptions, CLAUDE.md + testrail/browserstack/pw SKILL.md caveats.
All other dev changes merged cleanly.
- collect_sessions.py: name-only repo matches (worktree/basename fallback,
which can match an unrelated same-named repo) are now recorded per session
(repo_match), counted in inventory.json, called out in the summary, and
excludable via a new --strict-repo flag
- score_aggregator.py: never-scored detection tracks session ids in a set
instead of substring-matching error text, so a prefix-style id can no
longer suppress another session's never-scored error
- redact_secrets(): broader patterns no longer stack markers on top of an
already-redacted value
- session files read through the MAX_FILE_BYTES cap instead of slurped whole
- README deviations 21-22 recorded; count trued to 22 in CLAUDE.md and
authoring-notes; prefix-id regression + single-marker redaction verified
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017yFdbrdBnFL8Gw7DLrdg19
Earlier commits added a caveat before 'Integrations Setup' but left three earlier
spots in the same README describing TestRail/BrowserStack as working out of the box:
the H1 tagline, the /pw:testrail + /pw:browserstack Commands-table rows, and the
'2 MCP Integrations' heading under What's Inside. Add pointers/caveats to each so a
reader skimming the top of the README gets the same 'optional, manually enabled'
signal. Per review feedback on #981.
The CLAUDE.md caveat said 'cd integrations/<name>' but the real directories are
integrations/testrail-mcp and integrations/browserstack-mcp (the -mcp suffix that the
removed .mcp.json used and that the other four touched docs already spell correctly).
Following it literally would cd into a nonexistent dir. Per review feedback on #981.
Companion to the plugin.json description fix: the marketplace listing (the copy users
see before install) still advertised 'TestRail + BrowserStack MCP integrations' as
bundled. Match the softened plugin.json wording ('optional (manually enabled) ...') so
both listings are consistent. Per review feedback on #981.
Five of six findings were real. Verified each against the code rather than
taking them at face value; one was wrong and is noted below.
1. validate_examples.py carried a stale header from the spec-only phase --
"PARKED AS AN ASSET (deliberately not .py yet)... ON IMPLEMENTATION: rename
to skills/agent-memory/scripts/validate_examples.py". The file is already at
exactly that path. Rewritten to describe what it now is, keeping the
substantive part: why it exists, the seven check families, why it compares
the doc's algorithm by source text rather than exec()-ing a code fence, and
that nothing runs it automatically.
2. Missing shebang -- added. The same finding also claimed mode 100644; that
half is wrong, `git ls-files -s` shows 100755 for all five scripts.
3. hooks.json's description still opened "CONTRACT ONLY -- the referenced
scripts are not yet implemented", true of none of them now. Trimmed to keep
only the UserPromptSubmit provisionality (9.5 is genuinely still open) and
to record the measured latency alongside it.
4. The session-id fallback was the finding worth the most. `session_id` is the
right key -- engineering/security-guidance's shipped hook reads the same one
-- but the fallback was the CONSTANT "unknown-session", and sessions dedupe
by value. Had the key ever been absent, every session would collapse onto
one id, len(set(sessions)) would plateau at 1, and every claim would cap at
L1 forever with no error anywhere. Now falls back to the transcript's own
basename, which IS the session id. Verified end-to-end with session_id
omitted from the payload: the atom records the real session UUID.
5. Dead `now` parameter on _eligible_l1 -- removed.
6. marketplace.json metadata still said 104 agents / 120 slash commands,
pre-existing drift on a line this branch already edits. Trued up to 110/130.
Re-verified after: 69 checks 0 failures, SKILL.md 6/6 PASS, both blocking gates
still fire by name, check_paths 620 files clean, counters and plugin-json pass,
all 5 scripts --help, all 3 hooks parse.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Marketplace listing said 'sync with TestRail, run on BrowserStack' which reads as
out-of-the-box capability; the integrations now require manual enablement. Reword to
'optional (manually enabled) TestRail/BrowserStack integrations' so the listing itself
doesn't oversell. Per review feedback on #981.
Addresses review feedback on #981: README.md, skills/pw/SKILL.md, and the
testrail/browserstack SKILL.md files still described the integrations as working
after just exporting env vars. Add a caveat to each that pw-testrail/pw-browserstack
are no longer auto-registered and that /pw:testrail // /pw:browserstack (and the
testrail_*/browserstack_* MCP tools) fail with 'tool not found' until the server is
enabled manually, pointing to the CLAUDE.md Integrations section.
The freshly merged agent-launcher plugin's six SKILL.md files referenced
scripts and references relative to the plugin root (skills/<s>/scripts/x.py,
references/x.md), which resolves from none of the path linter's bases — so
check_paths.py --all fails on dev with 24 findings, and G1 is a blocking
gate on every future PR. Script commands now use repo-relative paths and
reference labels use the skill-dir-relative ../../references/ form that the
existing markdown link targets already used. 0 unresolvable after the fix.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qgc6RYXWJPr5oW9DHU7zR4
The pw-testrail and pw-browserstack servers were declared in playwright-pro/.mcp.json
and launched via `npx tsx integrations/<name>/src/index.ts`, but the plugin ships no
node_modules and nothing installs @modelcontextprotocol/sdk. Both therefore failed to
connect for every user — permanent 'Failed to connect' lines in `claude mcp list` —
whether or not TestRail/BrowserStack was configured.
Empty the .mcp.json server map (no build systems per repo convention; the integration
TS sources stay in-tree) and document in CLAUDE.md that the two integrations are no
longer auto-registered plus how to enable them manually (npm install + user/project
MCP config).
The two MCP servers registered in .mcp.json could never start: their
@modelcontextprotocol/sdk dependency is declared but never installed
(the plugin ships no node_modules and nothing runs npm install), so every
user saw a permanent 'Failed to connect' pair in `claude mcp list`.
Per the reporter's option 4 + docs: the registrations move to
integrations/mcp-servers.example.json (no longer auto-loaded), and the
README's Integrations Setup section now documents the two-step opt-in
(npm install inside the integration folder, copy the example to .mcp.json).
The integrations themselves are unchanged and keep working for users who
enable them.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qgc6RYXWJPr5oW9DHU7zR4
Turns DESIGN.md from a spec into a working plugin. Five stdlib scripts, three
hooks, agent, command, three references, plugin manifests.
The gates are the design:
L1 -> L2 >= 3 distinct sessions spanning >= 2 distinct calendar days
(`stated` = 2 sessions, day rule still applies; `verified` = 1
observation and is the only day-exempt path)
L2 -> L3 >= 2 distinct projects, >= 30 days, uncontested
Two gates refuse rather than guess. `redacted: true` blocks promotion on any
volume of evidence -- a durability-independent barrier, since a secret restated
across five sessions passes every recurrence gate; the flag firing means the
text was altered, a lexical filter finding one secret is not proof it found all
of them, and L2/L3 are committed to git. An open contradiction freezes both
claims, found by reverse join because the newer atom carries no flag.
All three hooks fail open: a broken memory system costs memory, never a session.
SessionEnd stages promotions to .memory/staged/ and never touches a CLAUDE.md;
only an explicit human adopt does, after backing both files up.
Verified, not asserted:
- all three pinned atom ids from DESIGN.md reproduce exactly
- both blocking gates demonstrated on sample input, named in the output
- end-to-end: two transcripts across two calendar days -> merged L1 atom ->
staged L2 promotion with the path prefix stripped
- reverse join blocks the unflagged newer atom
- cross-tier L2/L3 collision marked at injection time
- recall p50 29ms / p95 31ms / max 35ms spawn-to-exit, scoring itself 2-3ms
over 500 atoms -- interpreter cold start is the entire cost
- validate_examples.py 69 checks 0 failures; SKILL.md 6/6 PASS
- derive_counters --check, check_plugin_json --all, check_paths all clean
DESIGN.md 10.1's "+6" tool estimate corrected to +8 -- the delivered surface is
5 scripts + 3 hooks. README.md's deviations list is authoritative for that and
five other divergences from the pre-implementation spec.
Concept from TencentCloud/TencentDB-Agent-Memory (MIT). No upstream code.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
- root CLAUDE.md: Navigation Map row, Repository Structure tree line, and an
'Unreleased (post-v2.11.2, PR #961 merged)' narrative for the agent-launcher
domain (grep previously returned zero mentions)
- CHANGELOG: the verification sentence no longer points at
agent-launcher/DELIVERY-REPORT.md — per the maintainer finish-plan
(audit/pr-stream-2026-08) that report moved to gitignored documentation/;
SPEC.md remains the public build target
- sync scripts: v2.12 comment/description strings -> 'unreleased, post-v2.11.2'
to match the normalized plugin version; codex index regenerated
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012FwXG6TqCXKZQvF4iD69cv
check_paths.py resolves path tokens against the sub-skill root, the file's own
directory, or the repo root — the SKILL.md bash examples used plugin-root-relative
paths (skills/<skill>/scripts/x.py) that none of those bases resolve, and shared-
reference link texts (references/x.md) only resolved from the domain root. Bash
examples now use skill-dir-relative scripts/x.py; reference links use explicit
../../references/x.md. 617 files scanned, 0 findings; all other blocking gates
(G3/G4/G7/G8/G10, plugin.json, skill names) verified green locally.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012FwXG6TqCXKZQvF4iD69cv
Adds agent-launcher to the four sync scripts' domain lists and re-runs them:
.codex + .gemini indexes now carry the 6 skills; .vibe + .hermes repo trees
regenerated (also catches up skills merged since the last sync). The pre-existing
.codex/skills/run symlink collision (autoresearch-agent vs agenthub, both named
'run') is left at its previous target.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012FwXG6TqCXKZQvF4iD69cv
- CHANGELOG: [Unreleased] section for the agent-launcher domain (PR #961, merged 2026-08-21)
- 8-phase plugin audit: PASS WITH WARNINGS — structure 84.8-91.3 (orchestrator
EXCELLENT), security 0 critical/high across all 6 sub-skills, 18/18 scripts PASS
- audit auto-fixes: per-sub-skill READMEs (6), SKILL.md versions aligned to the
2.11.2 normalization from the merge, removed untracked scripts/my-agent/ test
debris (the one real security finding), my-agent/ added to .gitignore so user
launch artifacts can never be committed
- PUBLISH-CLAWHUB.md: publish order, slug-conflict fallbacks (cs- prefix registry-
only), 5-skills/hour drip constraint
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012FwXG6TqCXKZQvF4iD69cv
- tighten the SKILL.md description from 390 to 300 chars, core trigger first
- validate HIVEMIND_SERVER_URL and spawn opencode serve with an args array and
shell:false, so no environment value is shell-interpolated
- add LICENSE.txt (Apache 2.0); frontmatter stays name + description per CONVENTIONS
Hivemind delegates grunt work to headless opencode workers (scout/coder/tester)
while the orchestrating agent stays the planner, reviewer, and merger.
- placed under engineering/ per repo layout; targets dev per CONTRIBUTING
- frontmatter is name + description only; SKILL.md is 165 lines
- anti-patterns and cross-references sections included
- external opencode CLI dependency and free-model caveats documented up front
- runtime state (.runs/) gitignored, not committed
Round-44 review, three findings, all verified before fixing.
1. The schema's `redacted` description has always asserted "never
promoted to a committed tier without human review" -- a real gate that
DESIGN.md stated nowhere. Confirmed by grep. Added to 4.1 with the
reason the flag carries: redacted:true means the pass ALTERED the
claim, which is positive evidence the source was sensitive, and
redaction is lexical so finding one thing is not proof of finding
everything. Recurrence cannot substitute -- three sightings of a
scrubbed claim are three sightings of the same unresolved risk.
2. hooks.json did not quote ${CLAUDE_PLUGIN_ROOT} while both precedents
this PR cites do (handoff: python3 "${...}/hooks/session_start.py";
skillopt-sleep: "${...}/hooks/on-session-end.sh"). A path with a space
would break the command. Quoted all three.
3. 4.2.1 says "both sit at L1" but the schema marks only the older atom
(contested, contested_by), so the promotion gate cannot be a field
read on both sides. Specified the reverse join: blocked if own
`contested` is set OR own id appears in another atom's contested_by.
Deliberately not a mirrored `contests` field -- same fact in two
places, needing sync, with nothing able to say which copy is right.
Cheap by construction: 5.2 caps the store at 500 atoms and measured a
full pass at 2-3ms.
Did NOT add a schema->doc dangling-section-ref check. Wrote one, it
reported 3.1.1 and 4.1.2 as dangling, and both exist -- my heading regex
required a trailing period that sub-sections do not carry. Re-ran
correctly: zero dangling refs. A brittle checker for an empty class,
which I got wrong twice inside two minutes, is worse than no checker.
Verified: hooks.json parses; 69 checks, 0 failures; derive_counters.py
--check passes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Round-43 review found the Windows gap that 42 rounds missed. Verified it
is a hard break, not cosmetic: the schema's L1 pattern is
^~/\.claude/projects/[^/]+/[A-Za-z0-9._-]+\.jsonl#L[0-9]+$ -- literal ~/
and forward slashes -- so a path built from %USERPROFILE%\.claude\...
matches nothing and an extractor recording the OS path verbatim emits an
atom the schema rejects outright.
Resolved rather than added to 9, because it is mechanical: `source` and
`first_source` store a canonical form, not an observed one. The extractor
derives the ~/-relative forward-slash form from whatever the platform
handed it, the same way 3.1.1's promotion derives the stripped form
rather than storing what it saw -- recording is already a transform here.
Worth noting the blast radius: L2 and L3 are already platform-neutral,
since the stripped form is a bare <session>.jsonl#L<n> with no path.
Nothing committed is affected, only the gitignored L1. 3.1.1's
de-identification stripping bought portability for free.
Also stated first-run behaviour, which 5.4 skipped while specifying
concurrent writers in detail: a missing .memory/atoms.jsonl is the normal
initial state, read as an empty store and created on first write, with
recall returning nothing rather than failing.
Verified: 69 checks, 0 failures; derive_counters.py --check passes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Round-42 review: the "run the validator before editing" requirement lived
in 10.1 and the PR body. Someone opening DESIGN.md six months from now
reads neither -- and "a future editor who does not know the file exists"
is the exact failure the doc names. Now a callout at the top with the
command in it. Fourth time this review series has turned up a rule
stated somewhere other than where the person who needs it is looking.
Also sharpened what round 41 recorded about 9. The reviewer read "~700
lines of settled contract downstream of an unmeasured question" as a
reason to trim 4-5 until the extraction spike reports. Worth being
precise instead: a "no" on (2) does not make the promotion machinery
wrong -- recurrence counting, the tier caps and the contradiction
detector operate on atoms however they were produced, and none reference
the extraction method. It makes them unused. Content that would need
rework is worth deferring; content that would go unread is not, since
deleting reviewed text to re-derive it later costs more than leaving it.
Recorded as a sequencing lesson for the next spec this size rather than
a call to cut.
Verified: 69 checks, 0 failures; derive_counters.py --check passes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Round-41 review, two findings.
The 1 size claim went stale in a way worth being precise about. 85,875
bytes was correct at 67a1228, but merging dev moved this branch's base
and the file is now 90,312 -- and the parenthetical says "measured at
this branch's base", so it was false as written. Updated to 88 KB /
90,312, and noted that it grew 4,437 bytes while this PR was open, which
is 1's own thesis demonstrating itself on the file it is about. Round
29's principle still holds: the checker verifies the sentence's internal
consistency (method named, units agree), never a live comparison -- both
checks pass on the new figures.
Second, and the better finding: 9 listed six decisions as a flat set,
which understated that two of them decide whether there is a system at
all. (2) extraction-without-an-LLM gates everything downstream -- the
session gate, the tier caps, the contradiction detector are only as good
as what the extractor produces -- and (3) is answered by (2), since
9.3's 2-week trial IS the test of it. The other four are local: each
changes one mechanism and leaves the rest standing, including (5), whose
worst case deletes one hook while the tiering survives on SessionStart.
Now a table, with the cost stated plainly: ~700 lines of settled contract
sit downstream of a question nobody has measured.
Verified: 69 checks, 0 failures; derive_counters.py --check passes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Round-40 review made a point the spec had left to inference: the
recurrence gates are a durability filter, not a secrets filter. A secret
seen in three sessions across three days is exactly as much a secret as
one seen once, so the gates were never protecting CLAUDE.md from a leak
-- they only made one slower. The `verified` fast path removes even that,
taking a claim from a single sighting to a committed marker block with
6 rule 1's redaction pass as the sole barrier.
Stated in the fast-path block itself rather than left to a reader
combining 4.1 with 6 -- the third time this review has turned up a rule
living in one section while the surface an implementer builds from lives
in another. Two consequences named: redaction must not be shortcut on the
`verified` path ("a script confirmed it" says nothing about whether the
text holds a credential -- "the staging key sk-... works" is a plausible
verified claim), and a verified 1-observation atom carrying a secret is
the first behavioural test memory_promote.py should have, since it is the
shortest path in the system from raw transcript to committed file.
Verified: 69 checks, 0 failures; derive_counters.py --check passes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
The decision-driving §2 predated engineering/memory-engineering landing on
dev (#947) and never mentioned it. Adds the missing subsection: layer
distinction (it audits memory systems; this would be one), the namespace
fence both SKILL.mds must carry, a commitment that §5.1's eviction and
contradiction rules stay expressible in forgetting_policy_linter.py's F1/F4
form, and memory_cost_profiler.py as the §7 budget framework. Conclusion
renumbered 2.5 -> 2.6. Counters untouched by design (spec-only folder).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Bzm6Pafyxja6g4jUDPcei
- Conflict resolution takes dev's counter surfaces and re-applies the
agent-launcher marketplace entry (description trimmed to 950 chars for the
new <=1024 guard) and README domain row
- plugin.json source/attribution moved verbatim to authoring-notes.json per
the post-#954 schema dev now enforces; version aligned to 2.11.2
- claude-opus-4-8 (retired, G7-blocking since #938) pinned to claude-opus-5
across 5 scripts + example build sheet; all touched scripts re-smoke-tested
- 4 references topped up with external sources (7-8 each)
- DELIVERY-REPORT.md removed from the public tree (sprint artifact; content
preserved in PR #961 body and git history) — SPEC.md stays as build target
- Gates green: derive_counters --check pass, plugin-json 94 OK + marketplace
guard OK, frontmatter 0 errors, model freshness 0 findings, smoke 0 failed,
hooks exit 0 with and without AGENT_LAUNCHER_SESSION
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Bzm6Pafyxja6g4jUDPcei
Round-2 sweep after re-auditing all 15 reported issues against the merged dev:
- #885 generalized: the original fix only renamed self-improving-agent's
status/review, but three more plugins shipped skills whose bare names
shadow Claude Code built-ins. Renamed with the same convention:
playwright-pro init/review -> pw-init/pw-review, agenthub init/status ->
hub-init/hub-status, autoresearch-agent status/resume -> ar-status/
ar-resume. All command references (/pw: /hub: /ar:), docs, audit records,
harness manifests, and mirror trees/indexes updated; the flat mirror
namespace no longer collides on 'status'. New scripts/check_skill_names.py
gate (wired into ci-quality-gate.yml as blocking) fails CI on any future
bare reserved name; rule added to SKILL-AUTHORING-STANDARD.md.
- #969 follow-through: five more scripts print box-drawing characters that
cannot exist in cp1252 (api_scorecard, api_linter,
breaking_change_detector, humanizer_scorer, content_scorer) — same
guarded UTF-8 reconfigure applied; all smoke-tested under a forced
legacy encoding.
Verified: check_skill_names (incl. negative test), check_plugin_json,
check_paths, derive_counters, check_dual_publish, smoke_scripts (634/634),
0 broken mirror symlinks.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qgc6RYXWJPr5oW9DHU7zR4
Review follow-up on PR #972: the Windows Notes section now sits between
Verification & Testing and Troubleshooting, matching the Table of Contents
order, and the four scripts patched for #969 are back to exactly two blank
lines after the reconfigure block.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qgc6RYXWJPr5oW9DHU7zR4
Review follow-up on PR #972: docs/plugins/index.md still described the old
"two approved extension fields in plugin.json" policy reversed by #954 —
rewritten to point at .claude-plugin/authoring-notes.json and the CI
hard-fail. 32 generated docs pages still linked the gitignored megaprompts/
tree via absolute GitHub URLs (404s); converted to the same annotated
plain-text form used in the source files.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qgc6RYXWJPr5oW9DHU7zR4
Public audit record audit/pr-stream-2026-08/: every open PR against dev
(#788-#967) deep-read and re-executed against the repo's own gates.
Verdicts: 8 MERGE, 8 MERGE-WITH-CHANGES, 6 CLOSE, 3 maintainer-draft
finish plans. Names the four blocking maintainer decisions (extension-key
policy #966-vs-#940, agent skills: preloading, DESIGN-only folders,
release framing), a six-phase global merge order, and per-PR executable
verification plans.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Bzm6Pafyxja6g4jUDPcei
- #954: strip non-spec source/attribution keys from all 39 plugin.json
manifests so Claude Code's validator accepts them; metadata preserved in
new .claude-plugin/authoring-notes.json sidecars; check_plugin_json.py now
hard-fails manifests carrying those keys and sanity-checks the sidecar;
CLAUDE.md ClawHub schema section updated to the new rule.
- #949: move the c-level-agents plugin out of c-level-advisor/ to a
top-level directory so the two marketplace sources no longer overlap;
updated marketplace.json source, homepage, descriptions, all
cross-references, docs, harness manifest, mirror-tree symlinks/indexes,
and rebased the moved files' relative links; domain counters trued up
(18 -> 19 domains).
- #933: replace dead links to the gitignored maintainer-local megaprompts/
tree with annotated plain-text references (44 files: SKILL.md, READMEs,
agents, commands).
- #931: DynamoDB on-demand pricing updated to post-Nov-2024 rates
($0.625/M writes, $0.125/M strongly consistent reads).
- #969: skill_security_auditor.py and the three dossier scripts reconfigure
stdout/stderr to UTF-8 (errors=replace) so legacy Windows codepages no
longer crash at print time; PYTHONUTF8=1 documented.
- #968: Windows Notes section in INSTALLATION.md + README pointer for the
core.symlinks mirror-tree checkout caveat.
- #924/#885 residuals: hook commands quote "${CLAUDE_PLUGIN_ROOT}" paths in
all plugin hooks.json/settings.json (space-safe roots); removed the stale
pre-rename status/review mirror symlinks and index entries left over from
the memory-status/memory-review rename.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qgc6RYXWJPr5oW9DHU7zR4
GitHub Copilot CLI reads .claude-plugin/marketplace.json but enforces a
1024-character cap on each plugin's description. Four entries exceed it, so
Copilot rejects the entire catalog with:
Invalid marketplace.json: plugins.N.description: String must contain at most
1024 character(s)
Shortens engineering-advanced-skills (1132 -> 986), research-ops-skills
(1593 -> 957), markdown-html-skills (1240 -> 914) and memory-engineering
(1044 -> 964), trimming only redundant parenthetical detail. Skill inventories,
version history, hard rules, tool/reference counts and attributions are kept.
No other field is touched.
Verified with Copilot CLI: marketplace adds successfully and all 90 plugins are
listed.
Independent 10-agent verification workflow: 9/9 spec parts PASS, overall PASS,
zero differences from spec. Records the verdict table, design decisions, and
reproducible verification steps.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012FwXG6TqCXKZQvF4iD69cv
Adds the agent-launcher/ top-level domain — a plugin re-implementation of
Anthropic's launch-your-agent reference skill (Apache-2.0; independent, not a
fork) for building Claude Managed Agents (CMA) in the user's own account.
Every session starts with a goal (./my-agent/goal.json, surfaced by an opt-in
AGENT_LAUNCHER_SESSION=1 SessionStart hook + /cs:goal); loop_compiler.py
compiles that goal into a bounded grade->iterate loop (CMA user.define_outcome
self-grading, max_iterations 1..20), a recurring POSIX-cron scheduled-deployment
loop, or a single-pass interview->stage->launch workflow.
- 6 skills: agent-launcher-orchestrator (context: fork goal router) + interview
+ stage-launch + grade-iterate + run-without-you + wrap-up
- 18 stdlib-only deterministic scaffolder tools (NO network/API calls; live
launches emitted as BYOK curl that never prints the key); all pass --help/--sample
- 4 agents (orchestrator + interviewer + grader + deployer), 8 /cs:* commands
- opt-in SessionStart/SessionEnd hooks (exit 0 on any error), 5 shared
references, 4 assets (build-sheet schema + overview/next-directions templates
+ example)
- validators enforce CMA limits (<=20 skills/session, <=8 memory stores,
depth-1 multiagent, max_iterations <=20, <=1000 deployments/org)
- registered in marketplace.json; headline counters trued up via
derive_counters.py --check (skills 362->368, domains 18->19, tools 644->664,
refs 741->746, agents 102->106, commands 116->124, plugins 88->89)
Distinct from engineering/agent-harness (generic bounded loop over any domain)
and engineering/write-a-skill (authors Claude Code skills, not CMAs).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012FwXG6TqCXKZQvF4iD69cv
Round-38 review noticed that the committed contract files already encode
an answer to some of 9's open decisions -- hooks.json wires
UserPromptSubmit even though 9.5's option (c) is to delete that hook.
The doc knew: 9.5 already says "if (c) wins, hooks.json must shrink too."
But that only helps a reader holding both files. Read on its own a
hooks.json says "these three hooks exist", which is precisely the wrong
impression, and a contract file is exactly the artifact someone reads on
its own before implementing. Same lesson as round 36's contested-tag gap,
one level up: a cross-reference is not a contract, and that applies
between files as much as between sections.
hooks.json's own description now marks the entry PROVISIONAL, names the
open decision, gives the reason (the budget is dominated by interpreter
cold-start, not by the script's work), and says plainly that listing the
hook is a contract for the shape it would take IF it survives -- not
evidence the decision was made. SessionStart and SessionEnd are marked
not provisional so the warning stays scoped.
Verified: hooks.json parses; 69 checks, 0 failures; derive_counters.py
--check unchanged (363/89/663).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Round-37 review. The substantive finding: 9.5's options (a) fits /
(b) raise the budget / (c) drop the hook all treat spawn cost as a
constant to tolerate -- while last round's measurement showed spawn cost
is the ONLY cost that matters (scan 2-3ms, interpreter ~20ms). None of
the three attacks the measured bottleneck. That follows directly from a
number this doc already carried, and I should have drawn it rather than
waiting for a reviewer to.
Added (d): a warm resident process holding the store in memory, with the
hook reduced to a socket round-trip. Named as a real option because it is
the only one that removes the dominant term, explicitly NOT as the
recommendation -- its costs land on this design's own properties. A
"never blocks, exit 0" hook gains a liveness dependency and must keep the
cold path anyway, so complexity is added to rather than swapped for what
(a)-(c) need; lifecycle and stale-socket handling are a second heuristic
alongside 5.4's; a resident process holding memory contents in RAM is a
different security surface; and stdlib-scripts-that-exit is this repo's
shape. Sequenced behind the busy-machine measurement: if 100ms holds
under load, a daemon buys latency nobody needed.
Also trimmed the three passages the review named as archive-not-spec.
One of them ("the sentence went stale twice (53 -> 57 -> 67)") was itself
stale at 69, which is the argument for cutting it rather than updating it.
Verified: 69 checks, 0 failures; derive_counters.py --check unchanged
(363/89/663).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Round-36 review, three real findings.
1. Session-id uniqueness was the one load-bearing claim in 3.1.1 asserted
rather than evidenced, while everything around it cites line numbers or
arithmetic. Measured it: transcript filenames on a live install are
RFC-4122 UUIDs (version 5, RFC-4122 variant), shown with the commands
that produced them. One install is enough to establish shape, not to
promise the scheme is stable -- so the more useful half of the fix is
the fallback the reviewer noted was missing. The glob now has defined
behaviour for all three outcomes, and the >= 2 row is the one that
matters: without it a naive implementation takes the first match and
attributes a claim to the wrong session, which is a *wrong* citation
rather than a missing one, and 6 rule 6 cares about that distinction.
2. 4.2 states the contested-rendering rule tier-agnostically, but 5.2 is
the contract user_prompt_submit.py actually gets built from and never
mentioned it. An implementer working strictly from 5.2 ships a recall
path that surfaces a contested claim as plain fact. Stated in both
places now -- cross-references are not a contract.
3. L1 had a stored cap (500 atoms); L2/L3 had only injection budgets, so
a marker block could grow without bound while every session saw a
silently truncated view -- the 1 failure this design exists to prevent,
one layer down. L2 caps at 60 atoms with overflow demoted to L1
(recoverable, re-promotable); L3 caps at 30 and refuses further
promotions instead of deleting, since "never auto-demoted" means the
cap blocks inflow rather than choosing what to lose.
Verified: 69 checks, 0 failures; derive_counters.py --check unchanged
(363/89/663).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Round-35 review called the 100ms recall budget the highest-risk
unverified assumption, and estimated interpreter cold start at 20-40ms.
9.5 has prescribed the measurement since it was written -- "time a no-op
python3 -c pass plus a 500-atom scoring pass at p50/p95" -- so I ran it
rather than citing an estimate.
n=40, Linux container, otherwise idle:
python3 -c pass p50 12.4 p95 30.8 max 36.0
spawn + 500 atoms + score + top-5 p50 23.2 p95 30.1 max 50.6
...of which in-script work p50 2.1 p95 3.0
This reframes the risk rather than settling it. The scoring pass is
~2-3ms, so the 500-atom cap is not the binding constraint and never was
-- cold start is essentially the whole cost, which makes the budget a
process-spawn question rather than an algorithmic one. 100ms holds with
~3x headroom here; the 50.6ms max shows a real tail that would widen
under load. Recorded as a floor, not the answer: 9.5 asks for a busy
machine and this was an idle container.
Also cut two asides the review named as review-thread artifact rather
than spec: the 3.1 paragraph on why a rationale cannot be a $comment
inside a fixture (5 lines -> 3, keeping the reason), and the validator's
8-line comment on not whitelisting $comment (-> 4, keeping the warning a
future editor needs).
Verified: 69 checks, 0 failures; derive_counters.py --check unchanged
(363/89/663).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Round-34 review, two actionable items.
5.1 had no internal-budget discussion while 5.2 argues at length that its
1s hook timeout is a backstop rather than the target -- an asymmetry a
reader can only resolve by guessing. Stated why it is deliberate: this
hook runs once per session rather than once per prompt, so a slow run
costs one startup instead of compounding; and its work is bounded by the
2KB/4KB byte caps rather than by a scan that grows with history, where
recall scores up to 500 atoms. Also noted that 9.5's cold-start finding
lands here too if it comes back bad.
Addressed the .py.txt parking as a *precedent* rather than defending this
instance. What makes it legitimate is not intent, which is unfalsifiable,
but that the file is not a tool: no plugin ships it, no skill owns it,
nothing invokes it, and counting it would make python_tools less accurate
rather than more. The abuse it could be mistaken for -- a real tool
renamed to keep a headline number down -- is separable by one question a
reviewer can ask: is anything supposed to run this? Pointed at 11's
audit/ option as the way to avoid the pattern entirely.
Not changed: hooks.json naming three scripts that do not exist. Checked
whether the hypothetical lint exists -- nothing in scripts/ or
.github/workflows/ references hooks.json at all -- so the file's own
"CONTRACT ONLY" description is the whole mitigation needed today.
Verified: 69 checks, 0 failures; derive_counters.py --check unchanged
(363/89/663).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Round-33 review. 4.1's L1->L2 gate has two clauses -- >= 3 sessions AND
>= 2 distinct calendar days (UTC) -- and family 4 only checked the count.
The days clause is the half that stops one long working day from minting
an L2 claim, which is the exact case 4.1 calls out for the `stated` fast
path, and it had neither a check nor a fixture exercising it.
Added it for L2 atoms whose confidence is not `verified` (4.1 names
`verified` as the only exempt path). Worth stating why the test is
sound rather than approximate: first_seen and last_seen bound every
observation, so date(first) != date(last) is equivalent to ">= 2 distinct
days", not a proxy for it. Same date means every observation fell inside
it; different dates means at least two were touched.
Verified by shrinking the L2 fixture's window to one day:
FAILED: atm_961f033d spans >= 2 distinct calendar days
FAILED: atm_961f033d/L2 promoted_at falls inside its own observation window
The second is family 7 catching a side effect of the same injection,
which is the intended overlap.
Also fixed the placement section's framing. It claimed "neither option is
endorsed here" and then introduced its bullets with "both cut against
staying here" -- a lean, contradicting the sentence above it, and the
third reviewer in a row to read it as one. Now two symmetric cost lists
with nothing weighed.
Verified: 68 -> 69 checks, 0 failures; derive_counters.py --check
unchanged (363/89/663).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Round-32 review. 4.1.1 step 3 enumerated nine of the schema's thirteen
required fields, so a memory_promote.py written literally against it
would emit a schema-invalid atom. The reviewer also caught that 4.1.3's
confidence-merge rule is scoped to "(5.3)" -- the same-tier SessionEnd
merge -- so it does not cover this cross-project one by implication.
Added a table for the four: `claim` from the earliest contributor (the
group normalizes identically; earliest is for determinism, since
normalization is lossy on case and punctuation), `confidence` = max()
across all contributors (4.1.3's principle, restated rather than
assumed), `redacted` = true if any is (over-claiming costs nothing,
under-claiming loses the signal), and `kind` must agree or the group is
ineligible -- `kind` is not in the hash key, so two projects classifying
the same sentence differently means the "same claim" premise is what is
shaky. Refusing keeps this section's one-directional property: L3
under-fires, it never mis-fires.
This step has now shipped three omissions (`source`,
`promoted_from_projects`, and these four), each caught by a human
reading the list against the schema. Added a check for the class: every
schema-required field must appear in 4.1.1. Re-injecting the omission
fails on ['kind', 'redacted'].
Two notes on that check, both found by verifying it rather than trusting
it. It first reported first_seen/last_seen/first_source as missing --
false, because norm_prose strips `_` as an italic marker, so the needles
had to be normalized the same way. And it is a substring test over the
section, so `confidence` and `claim` satisfy it via incidental mentions
elsewhere; that limit is now stated in the code rather than implied.
Verified: 67 -> 68 checks, 0 failures; derive_counters.py --check
unchanged (363/89/663).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Round-31 review spotted "other-project" sitting inert in the validator's
allow-list. It is inert for a reason worth fixing rather than tidying:
the check only scanned the path-embedded `-home-user-<slug>` form, so
`project` and `promoted_from_projects` -- where names appear bare -- were
never checked at all. That is the whole coverage gap, not a dead entry.
The consequence was the exact leak 6.5 exists to prevent. The rule came
from a fixture that named a private repo; a fixture naming one in
`project` rather than in a path would have passed clean. Verified by
injecting one:
FAILED: no unknown project names in fixtures, in paths or in fields
['acme-internal-private']
Now gathers names from both sources before comparing. Check count
unchanged at 67.
Verified: 67 checks, 0 failures; derive_counters.py --check unchanged
(363/89/663).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Two of three notes from the eighth PR review round; the third needed no change.
1. `--max-rounds` was per-invocation, so `open` and a later `close` could
disagree about the cap and G5 escalation depended on how the command
happened to be typed. `open` now records the agreed cap in gate state and
status/collect/close inherit it. Passing the flag again is an explicit
renegotiation and prints the change rather than silently overriding.
Before: `open --max-rounds 2` then `status` -> "max_rounds": 5
After: same sequence -> "max_rounds": 2
2. The protocol-relative and own-asset URL allowances were documented in a
comment but nothing checked them, unlike the void-element and template-token
regressions which each got a fixture. `--sample` fixtures now carry
must-keep / must-drop URL assertions alongside the block count, and
`SAMPLE_HTML` exercises all three cases (`//host/x`, `https:` image,
`javascript:`). Verified the assertion bites: adding "javascript" to the
scheme allowlist turns --sample red with `FAIL - kept javascript:`, exit 2.
3. No change for cross-origin `<svg><use href="https://...">`. `href` is
already in URL_ATTRS and scheme-checked; `https:` is allowed there by the
same deliberate rule that lets a reviewed page's own `<img src>` load. It is
not a gap in the allowlist, it is the allowlist working as designed.
Gates: derive_counters --check pass, check_plugin_json --all pass, all three
scripts --help/--sample exit 0, write-a-skill checklist PASS.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01233Eggb2cjSYf96X6C3pCm
Round-30 review: ~70 lines of meta-discussion about where this file
should live stood between a reader and the tiering design. Moved to a
new 11 at the end, leaving a three-line pointer at the top. Old 11
(Attribution) renumbered to 12; the heading-order linter confirms the
sequence is still consistent.
The content is kept rather than dropped -- it is the record of an open
maintainer decision that three reviewers have now asked about -- but it
is not part of the design and should not be read first.
Verified: 67 checks, 0 failures; derive_counters.py --check unchanged
(363/89/663).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Round-29 review. Family 6 compared 1's cited byte count against the
CURRENT size of the repo-root CLAUDE.md -- a file this repo appends a
release note to on nearly every point release. The next unrelated PR
touching it would have turned this suite red for a reason with nothing
to do with this folder. 10.1's own thesis is that a checker must own its
ground truth; this one borrowed a moving one.
Snapshotting the byte count as a constant in the checker was the
reviewer's other suggestion and is not better: it puts the same number in
a second place that can drift from the first, with nothing able to say
which is wrong.
Replaced with two properties of the sentence itself, both of which the
doc controls: the claim must name `wc -c` and carry a real byte figure,
and its two units must agree (84 KB == 85,875 bytes). That still catches
the defect this check was written for -- 1 once read "~40 KB",
eyeballed, off by more than 2x -- verified by re-injecting it:
A (eyeballed, no byte figure): FAILED names `wc -c` and cites a byte figure
B (42 KB vs 85,875 bytes): FAILED KB and byte figures agree
Check count is unchanged at 67 (two removed, two added), so the
self-referential count assertion still holds. Also fixed a docstring in
_find() that still described the repo-root lookup this removes.
Verified: 67 checks, 0 failures; derive_counters.py --check unchanged
(363/89/663).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Round-28 review. Three changes, two held.
5.1 now carries the consequence 9.6 leaves live: L2 and L3 are injected
together and 4.2.1's detector cannot reach L3, so nothing upstream
guarantees they agree. Stated as a constraint on the hook -- never emit
two colliding claims as plain assertions -- rather than a mechanism, so
it holds under all three of 9.6's candidates. The reviewer is right that
retrofitting conflict-marking after session_start.py ships costs more
than honouring it in the first version; that does not require settling
9.6 itself, only refusing to ship the unmarked case.
AGENT_MEMORY_RECALL -> AGENT_MEMORY_USERPROMPTSUBMIT, in DESIGN.md and
hooks.json. The old justification (shorter; matches section 3's
vocabulary) traded away a property worth more: with all three vars
mirroring their hook name, a user who knows Claude Code's hook names can
derive all three without reading this doc. Three vars under two
conventions also invites the typo report the reviewer predicts.
Added the exact CI workflow snippet to 10.1. Still not wiring it into
ci-quality-gate.yml -- that runs on every PR in the repo, for a folder
9.3 permits deleting after a two-week trial -- but saying yes now costs
one paste rather than a design conversation.
Held: the placement decision, and the suggestion to split mechanical
rationale into references/. The second turns out to be blocked by the
first, which was worth measuring: a references/*.md under
engineering/agent-memory/ moves the references counter 746 -> 747, while
the same file under audit/ is pruned and free. The status header now
tables that alongside the parking hack and the double-relocation cost --
three open items resolving from one decision, which is the argument for
answering it before the implementation PR.
Verified: 67 checks, 0 failures; hooks.json parses; derive_counters.py
--check unchanged (363/89/663).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Three findings from the seventh PR review round.
1. `marketplace.json` still said "zero network requests" flat. An earlier
commit corrected exactly that wording in README.md, SKILL.md and
plugin.json — a reviewed HTML artifact's own https: assets do load, and
deliberately so — but missed marketplace.json. Now matches the others.
2. `GATED_ELSEWHERE` lived in human_gate.py as free-text prefixes matched
against messages generated in feedback_parser.py: an implicit cross-file
contract nothing enforced. The prefixes now live beside the
`problems.append()` calls that emit them and are read from the loaded
parser module, with the old literal kept only as a fallback for an older
parser.
Reproduced the drift on pre-fix code by rewording the G3 message:
G3 round 1 has no named reviewer
G7 round 1 integrity: unknown severity/kind 'BLOKCER'
G7 round 1 integrity: the sidecar names no reviewer - ... <- duplicate
Same reword post-fix produces only the first two lines.
3. `ATTR_RE` truncated a quoted header attribute at the first space:
`target="q3 plan.md"` parsed as `q3`. Quoted values now parse, and the
docstring states the quoting rule and that `target` is a display hint —
quote verification runs against the `--target` path.
Gates: derive_counters --check pass, check_plugin_json --all 90/90 OK,
marketplace.json parses, all three scripts --help/--sample exit 0.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01233Eggb2cjSYf96X6C3pCm
Round-27 review: DESIGN.md had accumulated its own review history inline
("round 3's fixture fix", "round 7 shipped two ids", "an earlier draft
violated..."), which reads as a PR changelog in a document an
implementer reads once. Fair, and I had been adding to it every round --
the previous commit put "until round 26" into 10.1.
Rewrote every such site to state the rule and the failure it prevents,
without the narration of who found it when. The rationale is what stops
a rule being re-broken; the round number is not. Two examples:
- 3.1's lifecycle callout now names the drift a "one lifecycle" claim
invites (two atoms that each validate alone and contradict each other
side by side) rather than reporting that a draft once did it.
- 10.1's property 1 now reads as a prohibition -- "it must not get this
property by exec-ing the fence" -- which is what a future editor needs,
instead of a note about when the exec was removed.
Same pass over the validator's comments, keeping the warnings (a future
editor of that file does need to know why $comment is not whitelisted)
and dropping the round counters.
Also stopped the status header reading as a lean toward audit/. Two
consecutive reviewers took "a better fit than this note originally
claimed" as an endorsement; it was meant as a correction to the note.
Now states plainly that neither option is endorsed and the decision is
the maintainer's, with the costs of each listed below it.
No rules, thresholds or contracts changed. Verified: 67 checks, 0
failures; derive_counters.py --check unchanged (363/89/663).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Round-26 review asked for a trust-boundary comment on published_normalize()'s
exec of a fenced block extracted from DESIGN.md. Removed the exec instead,
because the same review's other finding turns the comment into an
insufficient answer.
Findings 1 and 2 interact. Wiring the validator into CI -- correctly
observed to be possible today, since a temp .py copy is never seen by
derive_counters.py -- would have escalated the exec from "a maintainer
runs this on a branch they trust" to "any PR author executes arbitrary
code," because ci-quality-gate.yml triggers on pull_request and that
includes forks. The exec's safety depended on a fact outside the file,
and the obvious next improvement silently falsified it. A comment
documenting the trust boundary would have been read, agreed with, and
then invalidated by the very next commit.
The property the exec bought -- doc and fixtures cannot silently diverge
-- is preserved by comparing source text: the checker holds its own
normalize() and refuses to run if the doc's fenced block differs.
Verified by editing the doc's algorithm without updating the checker:
FATAL, both bodies printed. Fails closed on a cosmetic reformat too,
which is the safe direction.
Also corrected two claims this round proved wrong: 10.1 implied the .txt
parking blocks CI gating (it does not -- temp-copy works today, and the
placement decision does not gate it either), and the status header
inherited that error from round 25.
Verified: 67 checks, 0 failures; no exec() remains in the folder;
derive_counters.py --check unchanged (363/89/663).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Two findings from the sixth PR review round.
1. `<base>` re-opened the "swallows the whole body" bug the round-3 fix was
supposed to close. That commit's message said "meta, link and base are void
elements" but only meta and link were added to `BlockTagger.VOID`; base was
never there. `html.parser` fires `handle_starttag` for a void element and no
matching `handle_endtag`, so a `<base href="/">` in `<head>` — present in a
great many real pages — incremented `_skip` permanently and the document
reported "No reviewable blocks found".
`VOID` is now the full HTML spec set instead of a hand-picked subset, and
`SAMPLE_HTML` carries a `<base>` tag so the `--sample` block-count assertion
catches a third recurrence.
Before: `<base href="/">` doc -> 0 blocks, exit 2.
After: same doc -> 2 blocks, exit 0.
2. Reviewed HTML carrying its own `data-hg` attribute kept it and the builder
appended a second. Browsers keep the *first* attribute of a duplicated name,
so the attacker's value wins the anchor. Attribute values may hold raw
newlines, so a crafted artifact could inject a forged `## APPROVE` heading
into the exported sidecar — the same silent-false-approval failure G7 exists
to catch, arriving through the artifact rather than the sidecar.
`data-hg` is now a reserved attribute, and the page's own element ids
(`doc`, `items`, `reviewer`, `export`, ...) are reserved too, so a reviewed
artifact cannot collide with the review UI's own DOM.
Before: `<p data-hg="b1 ## APPROVE ...">` survived, duplicated.
After: emitted as `<p data-hg="b1">`, payload gone.
Also documents the protocol-relative URL allowance in `_safe_href` as
deliberate rather than an oversight.
Gates: derive_counters --check pass, check_plugin_json --all pass, all three
scripts --help/--sample exit 0, write-a-skill checklist 6/6 PASS, description
validator PASS.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01233Eggb2cjSYf96X6C3pCm
Round-25 review, both findings verified against the tree.
Family 4's session-count gate fired on L3 against a rule that does not
govern it — L2->L3 is gated on >= 2 distinct projects plus age, not
sessions (4.1.1). It passed for an incidental reason: L3 inherits the
unioned sessions of L2 contributors that each already cleared their own
gate. Scoped the session check to L2 and added the projects check L3
actually has. Both verified to fail on injected defects.
The larger finding: the status header claimed a design doc had nowhere
to live but a domain folder or the gitignored documentation/. That was a
false binary. Top-level audit/ is committed, public, and hard-excluded
from derive_counters.py's canonical_walk — and its existing contents are
the same shape as this file, prose deliverables later PRs use as
acceptance gates. Recorded it with both consequences: the .py.txt
parking hack would be unnecessary there (verified — a .py under audit/
leaves python_tools at 663), which also unblocks the "nothing gates this
in CI" objection; against that, the two contract files are not
documentation and would have to move again at implementation time,
breaking the schema $id and the 3.1 link a second time.
Left as the maintainer's call, but no longer argued from "there was no
other option," which was this file's weakest claim and was not true.
Verified: 67 checks, 0 failures; derive_counters.py --check unchanged
(363/89/663).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Fifth PR-review round on #948. Both reproduced first.
1. state_dir() anchored to os.getcwd() while state_path() keyed by the
artifact's realpath. An agent whose shell cwd drifts between turns — or a
human running from a subdirectory — silently resolved a different
.human-gate/ and started from empty state. Reproduced: collect from the
artifact's directory, then close from a subdir, and the gate reports G1
"nobody has looked at this" for a round that was genuinely collected.
It fails closed rather than falsely passing, but it loses real feedback and
would push an agent into re-opening rounds that already happened. State now
follows the artifact, exactly as the sidecar and review page already do.
An explicit --state-dir still wins.
2. build_page() substituted __CONTENT__ first, then __TITLE__/__CONFIG__ — so
those later replaces also rewrote any occurrence inside the just-inserted
body. Reviewing a document that mentions the tokens (this skill's own docs
being the obvious case) injected the entire JSON config into the visible
page, not just a garbled title. Worse than the report suggested.
All three slots now fill in one re.sub pass, so no substituted value can be
re-substituted — which also covers the reverse direction, where block text
inside the config JSON contains __CONTENT__. The Markdown --sample fixture
now carries the token text, so the case is guarded rather than reasoned
about.
Minor: `--waive` with nothing to waive now prints "nothing to waive" instead of
silently discarding the flag.
Re-verified: derive_counters --check, check_plugin_json --all, checklist 6/6
PASS, description validator PASS, all three scripts --help/--sample green,
--sample asserts both fixtures' block counts.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01233Eggb2cjSYf96X6C3pCm
Round-24 review. One actionable finding, verified: 4.2 promised
contradiction handling "at L2/L3", but 4.2.1's detector groups atoms by
`project` and an L3 atom is scope=global with no `project` field — the
schema forbids one. Detection can never fire against L3, the one tier
that is always in context and never auto-demoted.
Scoped 4.2 to L1/L2 and split detection from rendering: the injected
`[contested]` tag stays tier-agnostic, since the schema permits
`contested` anywhere and a human can set it at adopt.
Added 9.6 rather than a loop change, because the L3 case is
underdetermined, not unbuilt. A project claim that differs from a global
one is either a correction to an over-generalised L3 atom or a
legitimate local exception, and no string-shape rule separates them.
Guessing "correction" is the expensive direction: it would tag the
persona tier as unreliable the first time any project deviates —
section 1's false-permanence failure, inverted. Records the live
consequence (5.1 injects L2 and L3 together, so two contradictory lines
can enter one context block unmarked) and three candidates, leaning
specificity-wins for v1.
Also: the "53 checks in six families" claim in 10.1 was stale by two
rounds and a reviewer quoted it back. Rather than correcting the number,
made the program own it — a final check asserts the doc cites the count
actually executed, so the sentence cannot go stale again. Documented the
working invocation in 10.1 too; the `.txt` parking means nothing in CI
gates this yet, and `python3 <(cat ...)` does not work because path
resolution walks up from __file__.
Verified: 69 checks, 0 failures; the count check fails when the doc
disagrees. derive_counters.py --check unchanged (363/89/663).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Fourth PR-review round on #948. All four reproduced first.
1. The gate was one flag away from opt-out. --waive applied to whatever
gate_refusals() returned, including G1 "no review round has been collected",
so `close --waive "no time"` exited 0 with nobody having looked at the
artifact. That is the most tempting shortcut for an agent under time
pressure and it defeats the skill's whole premise.
G1 is now unwaivable, with its own refusal message: a waiver accepts
objections a reviewer raised, it cannot manufacture a review that never
happened. Waiving a genuine objection (G2/G3/G4/G7) still works.
2. Inline `style` was unsanitized, so a reviewed draft containing
`background-image:url(https://attacker/beacon.png)` fired a request the
moment the reviewer opened the page — no script needed, and directly
contrary to the no-network property the README and manifest advertise.
Added to DROP_ATTRS. The <style> tag was already dropped, so keeping the
attribute was inconsistent as well as leaky.
3. Markdown `` never rendered. LINK's regex was not anchored against
a preceding `!`, so an image became `!<a href=...>` — and _safe_href's
image=True branch, which exists to allowlist data:image URIs, was dead code
on that path. Added an IMAGE regex ahead of LINK, negative-lookbehind on
LINK, and real <img> rendering through the same scheme allowlist. Verified a
javascript: src degrades to inert alt text.
4. An unterminated <script> silently swallowed the rest of the body — same
confusing failure shape as the void-tag bug, though it fails safe. Now emits
a named diagnostic to stderr instead of vanishing.
Nit: raw-HTML `target="_blank"` anchors get the rel="noreferrer noopener" the
Markdown path already added to its own.
Re-verified: derive_counters --check, check_plugin_json --all, checklist 6/6
PASS, description validator PASS, all three scripts --help/--sample green.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01233Eggb2cjSYf96X6C3pCm
Round-23 review. All three findings verified against the tree first.
Fixture drift (3.1 L1 vs the schema's L2 example, captioned "one atom's
lifecycle read side by side"): the L1 snapshot carried the L2's
last_seen as its own first_seen, putting the first sighting three weeks
*after* the promotion it precedes. A second incoherence in the same pair
went unmentioned by the review and is arguably worse: the L1
back-pointer used the L2's `source` line (#L412) where its `first_source`
(#L77) belonged, which 3.1.1 forbids — promotion strips the path prefix
and nothing else, so a line number cannot drift across it. Both fixed by
anchoring the L1 fixture on the L2's first-sighting fields.
Added family 7 to the checker: within an atom, first_seen <= promoted_at
<= last_seen; across a lifecycle group, first_seen identical (4.1.1 takes
the min), last_seen/observations monotonic, sessions a superset, and
first_source surviving with only the prefix stripped. Families 1-6 all
passed the broken fixtures because each atom was independently
well-formed and nothing compared them — a prose claim that two fixtures
are one story imposes constraints no per-atom check can see. Verified by
re-injecting the old values: 2 failures, both named.
Manifest precedent was "5 for 5" and is 4 of 5. llm-wiki uses the same
on-disk nesting but declares the bare ["./skills"] — which IS one of root
CLAUDE.md's documented forms. That inverts the maintainer follow-up: the
question is which of two shapes the repo wants, not whether to bless an
undocumented fourth one, since a documented form already covers this
layout.
10.1 cited 644 -> 645 for the counter delta while a sibling file in the
same PR cited 663 -> 664. 663 is current; 644 predates book-to-skill.
Verified: 57 -> 68 checks, 0 failures; derive_counters.py --check
unchanged (363 skills, 89 plugins, 663 tools).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Three findings from the automated review, all contract-level:
- memory_schema.json: the tier=L3 -> promoted_from_projects conditional
was one-sided, so an L1/L2 atom carrying promoted_from_projects was
accepted. Added the else branch forbidding it outside L3 — the field
is not merely unnecessary there, it is meaningless, since scope is
still `project` and the array would claim cross-project evidence the
atom does not have.
- hooks.json: SessionStart declared no timeout and fell back to the
Claude Code default. Pinned to 5s. UserPromptSubmit keeps its 1s
backstop; SessionEnd stays async.
- DESIGN.md 4.1.1: state that the L2 -> L3 merge is lexical. normalize()
collapses whitespace/case/punctuation only, so two projects holding
the same rule in different words never merge. The failure is
one-directional — L3 under-fires, the claim stays live at L2 in each
project — and widening it needs an LLM or a per-user synonym table,
neither of which belongs in v1. Named in the same style as 4.2.1's
contradiction-detector limits.
Verified: assets/validate_examples.py.txt 57 checks / 0 failures; all
three schema examples still validate; an L1 atom carrying
promoted_from_projects is now rejected; derive_counters.py --check
passes unchanged (363 skills, 89 plugins, 663 tools).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Third PR-review round on #948. All three reproduced first.
1. HIGH — every realistic HTML5 document produced zero blocks. meta, link and
base are void elements: html.parser fires handle_starttag for them but never
a matching handle_endtag. They were also in DROP_TAGS, so each bare
`<meta charset>` incremented self._skip permanently and every subsequent
starttag/endtag/data callback inside <body> hit the skip guard. Result:
empty out, empty blocks, "No reviewable blocks found", exit 2.
The documented landing-page use case therefore did not work at all. It
survived three review rounds because every HTML fixture I wrote used only
<title>/<style> in head — the sanitizer test included. Void drop-tags no
longer touch the counter.
--sample now builds BOTH fixtures (Markdown + a full DOCTYPE HTML5 doc with
bare meta/link), asserts the expected block count for each, and exits 2 on
regression, so this cannot come back silently. It also writes to a temp dir
instead of cwd — the same class of mistake that leaked a stray artifact into
an earlier commit.
2. MEDIUM — xlink:href bypassed the URL allowlist. SVG anchors still honour it,
so `<svg><a xlink:href="javascript:alert(1)">` survived the hardening added
one commit earlier. Added with xlink:role and xlink:arcrole.
3. MEDIUM — status did not mirror close. It inspected only blocking_open, so a
round with no named reviewer reported exit 0 while close refused on G3 —
directly contradicting the exit-code contract the docstring advertises.
Both now call a shared gate_refusals(), so they cannot drift: verified they
agree on 2 (G3 open) and on 0 (clean round). status also prints which rules
would refuse rather than just a count.
Re-verified: derive_counters --check, check_plugin_json --all, checklist 6/6
PASS, description validator PASS, all three scripts --help/--sample green.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01233Eggb2cjSYf96X6C3pCm
Twenty-first review round. One fresh finding, and its sharp half is the
round-20 failure mode again in a new place.
validate_examples.py.txt derived BASE as dirname(dirname(__file__)) —
correct only at its current depth (assets/, two below the plugin root).
§10.1 moves it to skills/agent-memory/scripts/, four below, where that
form lands on the SKILL root instead. Verified by simulating both
layouts rather than reasoning about it:
- SCHEMA still resolved, by coincidence (assets/ and scripts/ become
siblings under the skill).
- DESIGN resolved to a path that does not exist and raised.
- The repo-root CLAUDE.md size check resolved to a nonexistent path and
was SKIPPED by its own `if os.path.exists(root)` guard — so the 84 KB
claim would stop being verified with the suite still printing green.
That last one is what makes this worth more than a path fix. Round 20 was
a whitelist that made a checker excuse the author's defect; this is a
guard that makes a checker excuse its own inability to run. Both report
success while checking nothing. A check that cannot locate its input has
FAILED, not passed, so the exists() guard is now an assertion.
BASE is anchored on a marker (walk up to DESIGN.md) instead of a fixed
dirname count, so the move cannot quietly disable anything. The repo root
is found by predicate — the directory holding BOTH CLAUDE.md and
scripts/derive_counters.py — because `.claude-plugin` alone is not a
repo-root marker: engineering/ carries one too, and anchoring on it lands
one level short. My first attempt did exactly that and the new assertion
caught it, which is the argument for the assertion.
Verified in three layouts: current (57 checks, 0 failures), the simulated
post-§10.1 move with links updated (57 checks, 0 failures — identical
count, so nothing is dropped by the move), and an orphaned copy with no
repo root above it (fails loudly, exit 1).
Counters unchanged: 363 / 89.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Twentieth review round. One real defect, and the worse half is mine.
examples[0] embedded a $comment inside the atom object. `examples` entries
are INSTANCE data, and the schema declares additionalProperties: false
with no $comment in properties — so under any real validator (jsonschema,
ajv) that fixture fails the very schema it exists to demonstrate. The
distinction that makes this a bug rather than a style choice: $comment is
a SCHEMA keyword. It is legal at schema top level and inside the allOf
branches — where it still lives, untouched — and illegal in an instance.
The worse half: validate_examples.py.txt computed its allowed-property set
as `set(schema["properties"]) | {"$comment"}`. I wrote that whitelist to
make my own annotation pass. That is not a missing check; it is a check
deliberately weakened to tolerate the author's defect, which is strictly
worse than the round-8 happy-path gap — that one failed to look, this one
looked and was told to ignore what it saw. It also falsified the PR's own
testing claim, which said the examples validate against
additionalProperties when what they validated against was a checker built
to excuse them.
Fixed by removing the annotation from the fixture (option b) rather than
widening the schema, because instance data must be valid instance data.
The rationale it carried — why a third, L1 fixture exists at all: it is
the only thing exercising the L1 branch of the back-pointer conditional,
the one with PII consequences — now lives in §3.1 prose, where an
annotation about the fixtures belongs.
The workaround is gone from the checker, with a comment recording why it
must not come back. Verified both directions: re-injecting a $comment into
an example now fails "declares no unknown fields" (exit 1), and an
independent pass confirms all three fixtures carry zero undeclared keys.
Counters unchanged: 363 / 89.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Nineteenth review round, no blocking issues. Two acted on.
1. §4.1.1's "age >= 30 days" gate and §4.3's demotion both key off
promoted_at, but nothing required it — so an atom could reach L2
without recording when, never satisfy the age test, and sit
un-promotable forever without anything flagging it. Exactly the
silent-skip mode that made `redacted` required last round.
Now conditionally required at L2/L3. Deliberately NOT forbidden at L1,
which the reviewer's phrasing already got right and which matters more
than it looks: §4.3 demotes an expired L2 claim BACK to L1, and that
atom legitimately keeps the promoted_at from its earlier life —
forbidding it there would make every demoted atom invalid. The
asymmetry is documented in the field description rather than left for
someone to rediscover.
Added to the committed checker too, not just the schema (56 checks now,
was 54): a schema conditional nothing exercises is the same class of
gap as the rule it fixes. Verified — deleting promoted_at from the L2
fixture fails "committed tier records promoted_at", exit 1.
2. §8's citations were unverifiable to a reviewer without the upstream
repo. They are now checkable: the clone was read at commit
b44c6db5f5b1a011eed645efb1949840f99f961a (2026-08-05, tip of main at
inspection), and the Chinese source comment quoted in point 1 is
verbatim from MemoryProxy/src/agent-adapters/claude-code.ts lines 2-6.
Pinning the sha means the citation stays checkable even after upstream
moves.
Not acted on: the root CLAUDE.md pointer (same answer as last round — it
advertises the convention before it is ruled on, so it lands with the
maintainer's yes), and blessing the .py.txt parking pattern, which is the
same convention call and belongs in the same decision.
Counters unchanged: 363 / 89.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
README and SKILL.md were corrected in 70c908a; the manifest still carried the
flat 'zero network requests'. The page makes no request of its own, but a
reviewed HTML artifact's own https: assets do load. Also notes the HTML
sanitization added in the same commit.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01233Eggb2cjSYf96X6C3pCm
Eighteenth review round, no correctness bugs found. Two items acted on.
1. §6 rule 1 calls redaction "non-negotiable ... before any write", but
`redacted` was optional in the schema — so an atom that skipped the
pass entirely was schema-VALID, which is precisely the state the rule
forbids. The reviewer's framing is right: an invariant the schema
does not carry is a promise, not a guarantee.
`redacted` is now the 13th unconditionally required field. All four
fixtures already set it, so the rule is enforced immediately rather
than aspirationally, and memory_promote.py can now CHECK that
redaction ran instead of trusting every writer to remember. §3.1
separates it from the genuinely later-stage fields (contested,
contested_by, promoted_at) and says why it differs: those are set by
contradiction handling and promotion, whereas redaction has already
run by the time any atom exists on disk.
2. validate_examples.py.txt's published_normalize() did a bare
re.search(...).group(0) — a moved or renamed fence would raise a raw
AttributeError from inside a checker whose entire job is to fail
legibly. Now three explicit SystemExit paths (fence missing, fence
present but not valid Python, block ran but defined no normalize),
each naming the cause and the fix. Verified by renaming the function:
the checker prints the guidance and exits 1 rather than tracebacking.
Both regressions confirmed caught: dropping `redacted` from a fixture now
fails "has all required fields" (exit 1); the clean tree still passes 54
checks (exit 0).
Items 3 and 4 not acted on. 3 is the maintainer's convention call, now
raised by six reviewers. 4 (a pointer in root CLAUDE.md's Unreleased
section) is deliberately coupled to it — advertising this folder in the
repo's headline changelog would pre-empt the very decision I have been
declining to settle by commit, and would need reverting if the ruling
goes the other way.
Counters unchanged: 363 / 89.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Second PR-review round on #948. All four reproduced before fixing.
1. HIGH — reviewed HTML executed in the review page. BlockTagger re-emitted
attributes verbatim, escaping values but never filtering attribute names or
URL schemes. The Markdown path has had _safe_href scheme-allowlisting all
along; the HTML path had nothing. Reproduced: a draft.html containing
`<img src=x onerror=...>`, `<a href="javascript:alert(1)">` and an <iframe>
passed straight into the page a reviewer opens — and reviewing a landing-page
draft is a documented use of this skill.
sanitize_attrs() drops on* handlers, srcdoc and srcset, and runs href/src/
action/formaction/poster/cite/background through the scheme allowlist.
_safe_href now strips control characters before reading the scheme (so
`java\tscript:` cannot smuggle one) and allows data:image only for image
attributes. DROP_TAGS removes iframe/object/embed/frame/base/applet as well
as script/style/head/link/meta. Verified: handlers, javascript: (plain and
tab-smuggled), and iframes all gone; https links and relative images kept.
2. MEDIUM — verify_quotes compared rendered text against raw markup. A quote
comes from window.getSelection(), which is what the browser rendered, so
selecting a sentence containing **bold**, `code` or a link never matched the
raw source. G7 had just made that blocking, so this refused legitimate
closes. Now matched against raw OR a rendered-text projection (inline markup
stripped for Markdown, tags stripped and entities unescaped for HTML). A
fabricated quote is still caught — verified both directions.
3. MEDIUM — state["waiver"] was never cleared, so after waived-close → reopen →
a clean round, close still printed the old waiver reason. For a tool whose
premise is an honest record of what was actually reviewed and waived, that is
its own integrity bug. Cleared whenever a close passes with zero refusals.
4. LOW — status returned 4 for both "no sidecar yet" and "collected, blockers
open". The blocked case now returns 2, matching close, so an agent can branch
on the exit code alone: 0 clear, 2 blocked, 3 collect, 4 nothing yet.
Also corrected an over-broad claim of my own: the page makes no network request
of its own, but a reviewed HTML artifact's own https: assets do load, as they
must for the review to be faithful. README and SKILL.md now say that precisely.
Re-verified: derive_counters --check, check_plugin_json --all, checklist 6/6
PASS, description validator PASS, all three scripts --help/--sample green.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01233Eggb2cjSYf96X6C3pCm
Seventeenth review round, nothing blocking. One suggestion acted on, two
already-open items left open.
The reviewer's point on automating the example<->schema check is right,
and the sharpest version of it is one I had not weighed when declining
this twice on counter grounds: my verification logic has lived only in
throwaway shell heredocs, so it dies with the session that wrote it. The
next person editing this spec inherits nothing. Drift between DESIGN.md,
the schema and the fixtures has been the DOMINANT defect class across the
review — required-field drift, a tier the examples never exercised, ids
that stopped reproducing, headings inserted out of order, a confidence
value contradicting its own lifecycle narrative. Losing the checks that
found those is the real cost.
Added assets/validate_examples.py.txt — stdlib-only, 54 checks in six
families. Two properties make it more than a linter:
1. It EXECUTES the normalize() that DESIGN.md publishes rather than
reimplementing it, so doc and fixtures cannot silently disagree.
2. It is tested against INJECTED regressions, not just the happy path.
Four deliberate defects — an unstripped back-pointer (the OS-username
leak), a broken tier->scope pair, a wrong id, a confidence downgrade
— each make it exit 1; the clean tree exits 0. A checker that only
ever passes proves nothing, which is why the happy-path-only version
of this check missed the round-8 gap.
Parked as .txt, not .py, deliberately: this PR is spec-only and a .py
here is counted by derive_counters.py (measured 663 -> 664), producing a
counted tool belonging to no plugin in a folder that deliberately has no
SKILL.md. New §10.1 records that, names it the FIRST file the
implementation PR should land — before memory_extract.py, since
everything else is written against the contract it guards — and states
the reversal condition: if a spec-stage folder may carry tooling, it
becomes a .py and three counter files move, nothing else.
Suggestions 2 and 3 (the DESIGN.md-only convention; resolving §9.2 before
merge) are maintainer decisions already surfaced in the PR body. Five
reviewers have now independently raised the first.
Counters unchanged: 363 / 89.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Sixteenth review round. One real inconsistency, one scoping fix.
The §3.1 atom (atm_961f033d, L1) carries confidence "observed"; the same
id at L2 in the schema carries "stated" — and round 14 explicitly paired
those two as "one atom's lifecycle", so the pairing turned an
undocumented transition into a visible contradiction. Nothing in §4.1 or
§5.3's merge description said confidence could change at all.
This is not cosmetic: confidence selects both the session count (3/2/1)
and the distinct-days exemption, so WHEN it may change decides which gate
an atom is held to. Left unstated, two implementers would reasonably
build different machines.
Resolved by documenting the transition rather than flattening the
examples, because upgrading is correct on the merits — a claim the agent
inferred can later be stated outright or confirmed by a check, and
freezing confidence at extraction would hold the atom to a stricter gate
than its evidence warrants. New §4.1.3: total order observed < stated <
verified; merge takes max(existing, incoming); never downgrades, so a
weak re-observation cannot silently re-impose the slower gate; the gate
re-reads confidence at promotion time, not creation. §5.3's merge step
now lists it alongside observations and sessions.
Verification proves the example pair is a legal upgrade and that the L2
atom clears the gate its own confidence implies, rather than asserting
the prose is consistent.
Also scoped the fast paths to "(L1 → L2 only)" — L2 → L3 is gated on
distinct projects, not session count, so neither shortcut applies there.
Note: the heading-order linter added in round 13 caught me repeating the
round-13 mistake — §4.1.3 was inserted between 4.1.1 and 4.1.2. Fixed
before commit. That is the linter earning its keep one round after being
written.
Counters unchanged: 363 / 89.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Both from PR review on #948, both reproduced before fixing.
G7 — a real hole in the skill's core promise. feedback_parser downgrades an
unrecognised severity heading to NIT and records it only as advisory prose in
`problems`, which cmd_close never read. Reproduced: a sidecar with `## BLOKCER`
carrying "No source. Do not ship this." collected as a NIT, and close exited 0 —
a reviewer's genuine blocker lost to a typo. Same gap covered EDIT items with no
`+ after:` line and quotes that do not appear in the target file.
close now refuses (exit 2) while the last collected round carries unresolved
integrity problems. Problems that already have their own rule are filtered via
GATED_ELSEWHERE so G2/G3 are not double-reported. Verified: typo'd severity,
missing EDIT replacement, and quote-not-in-file each refuse; a clean sidecar
still passes; a missing reviewer still reports G3 alone.
Stray artifact — quarterly-plan.review.html was committed at the repo root. It
came from a `review_page_builder.py --sample` run during the post-merge
verification sweep with cwd at the repo root, then got swept up by `git add -A`.
Removed, and .gitignore now covers `*.review.html` + `.human-gate/` so neither
this repo nor a user of the skill re-commits a disposable review page. The
sidecar (<artifact>.review.md) is deliberately NOT ignored — that is the
reviewer's feedback and belongs in git.
G7 documented in the script docstring, SKILL.md, README, the command, plugin.json
(description + derivation_note) and CHANGELOG. Not acted on: the reviewer's note
that cmd_status's success line is terse — they flagged it as "not a real issue"
and the JSON branch already carries blocking_open.
Re-verified: derive_counters --check passes, check_plugin_json --all 90/90,
write-a-skill checklist 6/6 PASS, description validator PASS, all three scripts
--help/--sample green.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01233Eggb2cjSYf96X6C3pCm
Fifteenth review round, no correctness findings. Three concrete gaps,
all worth closing before implementation starts.
1. §5.4 said a writer that cannot acquire the lock "gives up and drops
its atoms, logging the loss" — and never said where. That is the one
place in the design where data disappears silently, so an unspecified
destination made the sentence decorative. Pinned to
.memory/errors.log (gitignored, 0600, capped 200 lines), added to the
§6 layout, and explicitly NOT stderr: SessionEnd is async, so its
stderr reaches nobody, which would make "logging the loss" a fiction.
/cs:memory status surfaces recent entries — a log nobody is pointed at
is the same as no log.
2. §10's planned tree moves assets/ under skills/agent-memory/, which
silently breaks two references: DESIGN.md's relative link to the
schema, and the schema's own $id. DESIGN.md stays at the plugin root
(it documents the plugin, not the skill), so the link lengthens rather
than staying put. Both now called out in a table with their post-move
values, matching how every other forward-looking wrinkle in this doc
is handled.
3. Open decision #2 has a repo-wide cost if it resolves toward an LLM
extractor that nobody had priced. Root CLAUDE.md's anti-patterns bullet
reads "one documented, opt-in exception" and names skillopt-sleep by
file; a second LLM-calling script makes that sentence false. The
implementation PR would have to amend that bullet rather than become a
silent second carve-out. Recorded as part of the cost of (b) — it is a
real argument for the rule-based path beyond recall.
Also stated in the Status header why a design doc lives under
engineering/ rather than the gitignored documentation/ folder (nothing
there is visible in a PR), while keeping the "is this a repeatable
pattern" question explicitly open for the maintainer.
Link checking now strips code spans before resolving relative links —
the previous version flagged the illustrative post-move path in item 2's
table as a dead link, which it is not.
Counters unchanged: 363 / 89.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
book-to-skill landed in dev while this branch was open. All four conflicts were
counter/registry collisions in the shared headline files — resolved by taking
dev's side, then re-deriving from the tree so both plugins are counted:
skills 363 -> 364 · tools 663 -> 666 · refs 746 -> 749
agents 103 -> 104 · commands 118 -> 119 · plugins 89 -> 90
README engineering row 85 -> 86
Also fixed two merge artifacts: the README engineering row lost its human-gate
mention (dev edited the same row for book-to-skill), and the both-sides CHANGELOG
resolution left an orphaned duplicate fable-goal header at the seam — dev had
retitled the real entry "(previous PR)".
Verified after merge: derive_counters --check passes, check_plugin_json --all 90/90
OK, human-gate 6/6 on the write-a-skill checklist, all three scripts --sample green,
no conflict markers left in the tree.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01233Eggb2cjSYf96X6C3pCm
Fourteenth review round, no correctness findings. Three clarity items,
all of which were real double-takes rather than nitpicks.
1. §5.4's 60s stale-break and 5s acquire timeout read as contradictory
("5 < 60, so how does stale-break ever fire?") because the doc never
said they answer different questions. Added a table: 60s is an mtime
AGE test — older than that, break immediately, no waiting; 5s is how
long a writer waits on a lock that is live and younger than 60s. The
stale path is checked first, not gated behind the wait.
2. AGENT_MEMORY_RECALL breaks the naming symmetry its two siblings keep
(they mirror SessionStart/SessionEnd exactly). Recorded why:
AGENT_MEMORY_USERPROMPTSUBMIT is the consistent name and is rejected
on ergonomics, since this is the variable a user reaches for most
often. Marked deliberate so a later round does not "fix" it.
3. atm_961f033d appears at tier L1 in DESIGN.md and tier L2 in the
schema, which reads like copy-paste. It is the atom's lifecycle: id
hashes claim+project with no tier component, so L1->L2 keeps it, and
stability is required because merge-on-re-observation keys on the id.
Writing that callout surfaced a defect in my own first draft of it: I
claimed promotion never mints a new id, but §4.1.1 step 3 does exactly
that at L2->L3, because dropping the project component changes the
hash input. Corrected before commit, and verification now PROVES both
halves by computing them (aid(claim, project) == the L1/L2 id;
aid(claim) != it) rather than asserting the prose is right.
Counters unchanged: 363 / 89.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Audits petergyang/human-review and ships a conceptual derivation that fits this
repo's stdlib-only conventions.
Audit (audit/human-review-2026-08/AUDIT.md): upstream is a well-engineered ~5,200
LOC Node app — its own test suite passes 90/90, and its security model (loopback
bind, DNS-rebinding Host check, constant-time token compare, realpath traversal
guard, inert Markdown renderer, 45-min idle shutdown) is better than most
local-server tools. It still does not fit: Node 20 + an npm runtime dependency
fails the same stdlib-only test that kept the heavier skillopt package out in
v2.11.2. Seven findings, three material — F1 (HIGH) unpinned `npx -y` executes a
newly published version on every run; F2 (MED) "do not end your turn" plus
re-poll on timeout with no headless guard or retry cap; F3 (MED) only /api/* is
token-gated.
Also: despite the name it is not a humanizer. This is human approval, not human
voice — no overlap with behuman or content-humanizer.
New plugin engineering/human-gate, three stdlib scripts, no server or socket:
- review_page_builder.py — Markdown/HTML to a single-file anchored review page
with zero network requests (~11 KB, opens over file://). Escapes before
applying inline markup, scheme-allowlists hrefs, drops script/style on HTML
input.
- feedback_parser.py — sidecar to batch.v1 JSON. BLOCKER/MAJOR/MINOR/NIT
(matching md-review) plus EDIT/NOTE/APPROVE. Verifies quotes against the real
file; strips HTML comments so a documented example cannot parse as a real
sign-off.
- human_gate.py — open/status/collect/close/reset with atomic writes and
0700/0600 state. Rules G1-G6 refuse to close on: no collected round, an open
BLOCKER/MAJOR, an unnamed reviewer, a sidecar changed after collection, an
exhausted round cap (exit 5 = escalate), or an undocumented waiver.
Loop discipline deliberately inverts upstream: no blocking poll, a headless
guard, a round cap that escalates. The sidecar is hand-writable Markdown, so the
loop closes over SSH and in CI. The optional bridge to upstream is opt-in and
always version-pinned.
Adds 3 references (7-8 sources each), a batch.v1 schema, a worked example,
cs-human-gate agent, /cs:human-gate command. SKILL.md passes the write-a-skill
6-item checklist 6/6; description validator PASS.
Counters: skills 362->363, tools 644->647, refs 741->744, agents 102->103,
commands 116->117, plugins 88->89.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01233Eggb2cjSYf96X6C3pCm
Thirteenth review round. Three structural defects, all introduced by my
own earlier edits rather than present in the original draft.
1. §4.1.2 was placed physically BEFORE §4.1.1 — and §4.1.2's argument
cites the L2→L3 merge as the reason a state is unreachable, so a
reader met the citation before the section defining it. Reordered.
2. §4.1.1 and §4.1.2 were ### (h3), the same level as §4.1 itself,
while §3.1.1/§3.1.2 and §4.2.1 correctly use ####. Both bumped to
####. Both defects date to round 11, where the two sections were
spliced in without reconciling against the document's own structure.
3. "Hashing" was orphaned on its own line, residue from the round-7 edit
that replaced the text around it. Reattached.
The reviewer's framing is the right one: these undercut a document whose
pitch is self-checking rigor. So the fix is not just the three edits —
verification now includes a structural linter that derives expectations
from the numbering itself rather than checking known strings: heading
LEVEL must equal numbering depth + 1, and heading NUMBERS must ascend in
document order. Both would have failed on this state before the fix, and
they cover every section, not the three that happened to break.
Also the sixth round where a check failed on my own assertion rather than
the artifact (backticks in `scope`). Prose checks now normalize markdown
emphasis and code markers alongside case and whitespace, which is the
last of the three ways these assertions have been brittle.
Counters unchanged: 363 / 89.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Fourth review on PR #947 reported two functional bugs, explicitly noting it had
not run anything. Both reproduced, and the first is severe.
1. F1 -- the blocking gate -- could be bypassed by a typo.
_check_forgetting_rule() failed only when `rule` was literally
"none"/""/"never", and otherwise inferred PASS from what the rule was *not*.
So anything unrecognized fell through to the PASS branch with an empty
mechanism list. Reproduced:
{"rule": "asdf"} -> F1=PASS "Forgetting is designed: ."
{"rule": "ttl"} (no ttl_days)-> F1=PASS "Forgetting is designed: ."
A misspelling silently passed the one check this entire skill is built
around, and the nonsensical detail string was the only hint.
The check is now allowlist-based: PASS is unreachable unless a concrete
mechanism is actually found (ttl_days > 0, max_records/max_bytes > 0, or a
decay setting). Failure messages now distinguish an unrecognized rule from a
declared-but-unconfigured one, so a typo is never mistaken for a deliberate
decision not to forget. Booleans are rejected where a number is expected,
and ttl_days=0 counts as absent.
Verified across 10 cases: all six bypass variants now FAIL at exit 4, all
four legitimate mechanisms still PASS, and the empty-mechanism string can no
longer be emitted.
2. --print-sample-spec was unreachable on all three scripts that offer it.
The flag sat outside a mutually-exclusive group declared required=True, and
argparse enforces that during parse_args() -- before any of our code runs.
So the flag alone exited 2 with a usage error, which broke the first line of
the workflow SKILL.md documents verbatim:
python scripts/memory_cost_profiler.py --print-sample-spec > workload.json
The group is now required=False with explicit post-parse validation, so
no-args still errors helpfully and names all valid entry points. Verified the
full round-trip on all three: --print-sample-spec > f.json, then feed f.json
back in.
This slipped through because the PR's own checklist covered --help, --sample
and --output json, but never ran --print-sample-spec standalone.
Also removed the identity dict in render() flagged as a nit.
Verified: 4/4 scripts help/sample/json; error paths 3/4/4; all six blocking
gates; checklist 6/6 PASS; security auditor PASS (0 critical, 0 high, 0 info).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jt1sqt5kQmopyfXu2Hhjnv
Twelfth review round.
1. Section 1 and section 9.1 both claimed root CLAUDE.md is "~40 KB".
It is 85,875 bytes — 84 KB, more than 2x the stated figure. The
argument survives (the real number strengthens the bloat case), but
the error is the embarrassing kind for this doc specifically: section
2 opens "verified by reading the code, not the docs", and this was
eyeballed. Both sites now carry the measured figure with the method
(wc -c) so it is checkable rather than asserted, and verification
recomputes it from the file instead of matching a string.
2. The promotion table read "observations >= 3 across >= 3 distinct
sessions", presenting two conditions where there is one. The schema's
own observations description says the field is informational and the
gate counts sessions; since observations is always >= len(sessions),
the extra clause adds nothing except the risk that an implementer
gates on the wrong field — the exact confusion the sessions-as-a-set
rule exists to prevent. Row now names sessions as the gate and says
explicitly that observations is not it.
Also fifth round running where a verification check failed on my own
assertion rather than the artifact (this time case: "Informational" vs
"informational"). Prose checks now normalize case and whitespace once at
the top rather than being patched per-match.
Counters verified on the merged base: 363 / 89, unchanged by this PR.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Third review on PR #947 caught a counter this branch's sync missed.
README.md line 30 read "**Reference docs** — 746 templates, checklists, and
domain-specific knowledge files". The sync pass replaced the string "746
reference guides", which is the phrasing used in CLAUDE.md and
marketplace.json, so this differently-worded line was never matched.
Root cause worth recording: `derive_counters.py --check` does not cover this
line. Verified by setting it to a deliberately wrong 111 — the gate still
passes. So this class of drift is invisible to CI, which is why a reviewer
found it and the automated gate did not. Not fixing the checker here: it is
shared infra, and widening its coverage could surface pre-existing drift in
unrelated rows and turn CI red for reasons that have nothing to do with this
PR. Flagged on the PR for the maintainer instead.
Also swept README for any other stale counter adjacent to counter vocabulary
(skills/tools/references/agents/commands/plugins, old value vs new): no other
occurrences. Badges and both prose lines now read 364 / 667 / 750 / 104 / 120 / 90.
Left untouched: CLAUDE.md line 183, which records book-to-skill's own
"refs 741 -> 746" delta. That is historically correct for that release note
and must not be re-pointed at the current total.
All six blocking gates pass.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jt1sqt5kQmopyfXu2Hhjnv
Second automated review on PR #947 found a real bug, verified by execution:
`pick()` looks up `tuple(sorted([winner, runner_up]))`, but two of the four
TIE_BREAKERS keys were authored in the other order, so they could never match:
('flat_rag', 'structured_rag') sorted -> matches
('structured_rag', 'agentic') sorted -> ('agentic', ...) DEAD
('long_context', 'flat_rag') sorted -> ('flat_rag', ...) DEAD
('long_context', 'structured_rag') sorted -> matches
Only 2 of 4 authored questions were reachable. The two dead ones are the
plausible near-ties (structured_rag vs agentic on a high-recall/high-mutability
workload; long_context vs flat_rag under build-budget pressure), so the tool's
most distinctive behaviour — an authored, specific tie-breaking question —
silently degraded to the generic fallback with no error.
Keys are now normalized through sorted() at import, with a collision check that
raises if two entries describe the same pair. Verified by injecting a duplicate
in the reverse order: the guard fires. This repo has no test suite, so the check
runs at import rather than living in a test.
Confirmed by execution, not inspection: all 4 keys reachable, and a constraint
set that ties structured_rag against agentic now returns the authored question
("Does your memory need to correct itself without a human in the loop?")
instead of the fallback.
Also from the review: the SKILL.md workflow block labelled steps 1-4 while the
prose referenced a step 5, so a reader skimming only the code block would not
know it existed. Added a `# 5 - No command.` line and compensated elsewhere to
stay within the checklist's 100-line limit (still 6/6 PASS).
Verified: 4/4 scripts --help/--sample/--output json; all six blocking gates.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jt1sqt5kQmopyfXu2Hhjnv
Eleventh review round. Two genuine design gaps in the state machine, both
of which would have surfaced mid-implementation.
1. A tier=L1/scope=global atom was schema-legal but could never promote.
The scope field's own description said scope "is assigned at
extraction", so an extractor could mint one; but L1->L2 requires "same
project" and a global atom has no project field, while L2->L3 is a
merge over two or more L2 atoms. Such an atom would sit at L1 until it
expired at 90 days, silently, since nothing flagged it.
Closed by making scope a function of tier rather than a free choice:
L1 and L2 are project, global exists ONLY as the product of the L2->L3
merge. Enforced with a tier/scope conditional so a wrong extractor
fails validation instead of quietly producing orphans. This is also
correct on the merits — whether a claim is global is not knowable at
extraction; it becomes global by holding in a second project, which is
exactly what the merge represents. New section 4.1.2.
2. Section 4.1 gated L1->L2 on "no contradiction open", but 4.2 defined
contradiction handling only at L2/L3 — so the gate referenced a state
nothing produced. New section 4.2.1 defines detection at L1 with two
deterministic rules (explicit negation; same-subject different-value),
run at merge time within a project. States plainly what they do NOT
catch (semantic contradiction needs meaning, not string shape) and why
that is acceptable: the miss is bounded, since 4.2's L2/L3 handling
catches it one tier later and the human gate at adopt is what actually
holds. A narrow detector claiming completeness would be worse than one
that documents its edge.
Also: merged dev (branch was cut before #941) so the "adds nothing
countable" claim is verified against the real base — derive_counters
--check passes at 363 skills / 89 plugins, up from the 362/88 the branch
was cut at. Corrected the stale productivity/handoff evidence in section
10 (7 scripts + 2 hooks = 9 counted tools, not 5 + 2); the underlying
claim that hooks/*.py count was independently verified and is unchanged.
Section 1's skill count is now "360+" so it stops drifting with dev.
Counters verified on the merged base: 363 / 89, unchanged by this PR.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Automated review on PR #947 flagged find_duplicates() undercounting. Verified
and fixed, though the diagnosis was incomplete in a way that changes the fix.
`seen.add(j)` only ever recorded the second member of a matching pair, so for
a fully-connected cluster of k mutually-duplicate records len(seen) == k-1.
That number is not meaningless -- it is exactly the count of redundant copies
you could delete. The actual defect is that it was reported under the name
`records_with_a_duplicate`, and rendered as "N records have a near-duplicate",
which describes participants (k), not redundant copies (k-1). Two valid
metrics, one reported under the other's name.
So rather than just adding `seen.add(i)`, both are now computed and reported:
participants -- every record with >= 1 near-duplicate; drives duplicate_share
and the DUPLICATE_BLOATED threshold, matching the wording
redundant -- participants minus one survivor per connected cluster
Clusters are resolved with union-find, not by counting pair endpoints: a
3-record cluster emits pairs (i,j), (i,k), (j,k), so endpoint arithmetic gets
the redundant count wrong. Verified k=2/3/4 give participants=k, redundant=k-1,
and that a 3-cluster plus an unrelated record still gives 3/2.
Sample output moves from "1 record (17%)" to "2 records (33%), of which 1
redundant" -- the reviewer's point that this could tip a real store under the
15% threshold was correct.
Also from the same review:
- Dropped the stale `-> list[dict]` hint (the function returns a tuple); the
return shape is documented in the docstring instead.
- Capped the O(n^2) scan at MAX_DUPLICATE_SCAN=2000 eligible records and made
the tool print how many were skipped, per this repo's no-silent-caps rule --
a quiet cap reads as "no duplicates found".
Verified: 4/4 scripts --help/--sample/--output json; all six blocking gates;
skill checklist 6/6 PASS; real-directory run unchanged.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jt1sqt5kQmopyfXu2Hhjnv
Keeps the branch current with dev (363 skills / 89 plugins) so the
'adds nothing countable' claim is verified against the real base rather
than the stale one the branch was cut from.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
dev moved 8 commits ahead (engineering/book-to-skill), and both branches
touched the same three headline-counter files, so marketplace.json, CLAUDE.md
and README.md all conflicted.
Resolved by taking dev's version of each file wholesale, then re-applying this
branch's additions on top — rather than hand-merging the counter arithmetic,
which is exactly the kind of edit that silently drifts:
- marketplace.json: re-inserted the memory-engineering entry next to
agent-harness (dev's 89 plugins -> 90)
- CLAUDE.md: re-applied the memory-engineering release note above the
fable-goal note
- README.md: engineering-POWERFUL row 85 -> 86 plus the plugin mention
Then re-derived every headline number from the merged tree instead of
assuming my original deltas still held — they did not, since book-to-skill
had already consumed them. True values are now skills 364, tools 667, refs
750, agents 104, commands 120, plugins 90. The release note's own delta line
was rewritten to sit on top of book-to-skill rather than claiming the stale
362->363 range.
Verified on the merged tree: all six blocking gates pass (check_plugin_json,
check_paths, check_dual_publish, smoke_scripts, smoke_json_output,
derive_counters --check), compileall clean, skill checklist still 6/6 PASS,
no conflict markers remain.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jt1sqt5kQmopyfXu2Hhjnv
Tenth review round, no blocking findings. All three folded in.
1. The examples array held only L2 and L3 atoms, both using the stripped
back-pointer form — so the L1 branch of the tier conditional, the one
the $comment calls out as having PII consequences, was never exercised
by the schema's own self-test. DESIGN.md showed an L1 atom in prose,
but the schema read standalone never demonstrated the prefixed form.
My own verification had the same hole: it hand-evaluated L1 with a
synthetic case rather than a committed fixture, so nothing in the
repo pinned it.
Added a third example at tier L1 carrying the full <cwd-slug> path.
Chose a claim with kind='failure' so it also demonstrates a third
kind (the others were constraint and preference) rather than only
patching the coverage gap. Verification now asserts the examples span
all three tiers and both scope branches, and still rejects both an
unstripped L2 pointer and a prefix-less L1.
2. The L1->L2 row read "≥ 3 distinct sessions, ≥ 2 of them on distinct
days", which invites the wrong reading (2 of which sessions?). The
intent, stated precisely later in 4.1, is that the sessions SPAN two
days. Row now reads "spanning ≥ 2 distinct calendar days (UTC)",
matching the precision used elsewhere.
3. Recorded the stale-lock TOCTOU as a deliberate acceptance rather than
leaving it to be discovered. Two writers can both judge a lock stale;
the consequence is bounded by the design already there — each still
commits via os.replace, so the loser's atoms are lost, not corrupted,
and lost L1 candidates re-observe next session. A true mutex costs
portability (fcntl semantics vary across NFS and Windows) to buy
durability this tier does not need. Noted that it should not be
"fixed" without first showing the loss is observable.
Counters unchanged (362 / 88).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Ninth review round, no blocking findings. Three of four folded in; the
fourth is a maintainer call I have deliberately not made.
1. Added section 3.1.2 — the invariants JSON Schema CANNOT enforce,
because it validates one atom at a time and a valid atom does not
imply a valid store: first_seen <= last_seen (no cross-field
comparison), id uniqueness across atoms.jsonl, and per-claim session
uniqueness across records (uniqueItems is within-array only). Each is
assigned an owner in memory_extract.py / memory_promote.py. Verified
the one thing the schema DOES enforce — within-atom sessions
uniqueness, which is what the durability gate actually depends on, so
the boundary is exact rather than hand-waved. Recorded because "the
schema validates" is easy to mistake for "the store is consistent".
2. Section 9.5 now says that if the cold-start measurement forces
outcome (c) — drop UserPromptSubmit — hooks/hooks.json must shrink
with it. Deleting the hook from the design alone would leave the
contract file asserting a hook the design no longer wants; a contract
must not outlive the decision that justified it.
3. Recorded the $id rationale as a $comment in the schema. Three
separate review rounds have now proposed conflicting changes to this
non-functional field (blob-vs-raw, dev-vs-main), so the reasoning is
written down to stop the churn: raw.githubusercontent because
github.com/blob/ serves HTML and breaks $ref dereferencing, and main
because $id identifies the published artifact — a dead link until the
dev -> main promotion lands is accepted deliberately over a URL that
goes stale the moment it does.
Not acted on: whether a DESIGN.md-only folder under a domain is a
pattern to keep or a one-off. Two reviewers have now raised it; it is a
repo-convention decision for the maintainer, not one to settle by
pushing a commit.
Counters unchanged (362 / 88).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Eighth review round. Three findings, one of which closes a gap round 7
opened.
1. The tier-dependent back-pointer rule was prose-only. Round 7 argued
hard that stripping the ~/.claude/projects/<cwd-slug>/ prefix at
promotion is "not cosmetic" — an unstripped L2/L3 back-pointer commits
a contributor's OS username to a shared CLAUDE.md. But the schema left
source/first_source as bare {"type":"string"} with a description,
while the two OTHER promotion rules (project<->scope,
promoted_from_projects<->tier) were both machine-enforced
conditionals. The one rule with PII consequences was the one relying
on prose — which contradicts round 7's own framing that a contract
must be self-checking rather than self-asserting.
Added a tier-keyed conditional: at L1, source and first_source must
match ^~/\.claude/projects/[^/]+/...\.jsonl#L[0-9]+$; at L2/L3 they
must match ^[A-Za-z0-9._-]+\.jsonl#L[0-9]+$, which no path-prefixed
value can satisfy. memory_promote.py now fails loudly on a bad
promotion instead of leaking silently.
Verification hand-evaluates the conditional (jsonschema is not
available — stdlib-only repo) against three cases beyond the fixtures:
an unstripped L2 pointer is REJECTED, the stripped form is ACCEPTED,
and a prefix-less L1 is REJECTED so the local form stays
direct-openable. Asserting the rule fires is the point; asserting only
that the fixtures pass would have missed it.
2. Section 4.3 cited section 5.3 for the L3 cap. 5.3 is SessionEnd
capture; the cap ("Budget: 2 KB L3 + 4 KB L2", truncate by last_seen)
is in 5.1, SessionStart read. Corrected, and the check now confirms
the cited section actually contains the budget rather than trusting
the number.
3. The section 3.1.1 insertion split section 3.1's field bullet list,
leaving the `confidence` bullet abutting 3.1.1's closing paragraph
where it read as a stray continuation. Moved 3.1.1 to after the
complete list, so the list stays whole and the back-pointer deep-dive
is its own uninterrupted unit.
Counters unchanged (362 / 88).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
CI gate G1 (scripts/check_paths.py) failed with 8 unresolvable references.
Both command files referenced `scripts/<tool>.py` and `assets/<file>` as if
they were relative to the command file, but commands/ sits at the plugin root
while the scripts live under skills/memory-engineering/. SKILL.md was correct
already — it sits inside the skill directory, so its bare `scripts/...` paths
resolve — which is why this only showed up in the two command files.
Rewritten to the plugin-root-relative form
(`skills/memory-engineering/scripts/...`), matching how agent-harness writes
its command paths.
check_paths.py --all now reports 0 findings across 586 files. Also re-ran the
other five blocking gates locally: check_plugin_json, check_dual_publish,
smoke_scripts, smoke_json_output, derive_counters --check — all pass, plus
compileall on the plugin.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jt1sqt5kQmopyfXu2Hhjnv
Two follow-ups after running the repo's own CI auditors locally:
- Removed `from __future__ import annotations` from all 4 scripts. The repo's
skill_validator.py counts it as an external import (script_tester.py
disagrees and reports the same files as stdlib-only, but the stricter of the
two is what CI surfaces). PEP 585 generics are native on the 3.11 CI runner,
and the single PEP 604 union annotation was the only thing needing the
import — it is now unannotated. Takes this skill from 7 validator errors to
3, matching productivity/weekly-review and better than productivity/fable-goal
(4). The 3 remaining are the legacy v2.0.0 schema checks (min-100-lines, and
Tier/Category/Features/Usage frontmatter+sections) that directly contradict
the Matt Pocock checklist CLAUDE.md declares binding for post-v2.6.0 skills —
every recently-merged skill carries the same ones.
- SKILL.md: steps 4 and 5 used a bold-number style left over from the
compression pass while steps 1-3 had become prose. Reworded to match; still
exactly 100 lines and 6/6 PASS.
Verified after the change: 4/4 scripts pass --help / --sample / --output json;
script_tester 5/5 PASS; security auditor PASS (0 critical, 0 high, 0 info).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jt1sqt5kQmopyfXu2Hhjnv
Seventh review round. Two real defects, both in the contract file.
1. The back-pointer format contradicted the de-identification rule it is
promoted through. source/first_source are required at EVERY tier, and
the format is ~/.claude/projects/<cwd-slug>/<session>.jsonl#L<line>
where <cwd-slug> is Claude Code's slugification of the ABSOLUTE working
directory — so on a real machine it reads -home-alice-work-... and
embeds the OS username. A strictly-compliant implementation of rule 4
("cite, don't invent") would therefore write a contributor's username
into a shared, git-tracked CLAUDE.md on the first promotion, violating
section 6's de-identification requirement. Rule 4 would have won,
being the more mechanical of the two.
Resolution: the format is now explicitly tier-dependent. L1
(gitignored) keeps the full local path; promotion into L2/L3 strips
the prefix to <session>.jsonl#L<line>. Nothing is lost — session ids
are globally unique, so the prefix is recoverable at read time by
globbing ~/.claude/projects/*/<session>.jsonl. Required at BOTH
promotion boundaries, since L1->L2 is the first crossing into
committed territory.
Round 3's fixture fix masked this: the placeholder read -home-user-,
which looks de-identified only because that machine's username is
literally "user". The L2/L3 fixtures now carry the portable form, so
the examples demonstrate the rule instead of hiding it.
2. Neither worked example id reproduced. atm_7f3a9c21 / atm_b41c8de0
were invented in round 1, before sha256 was pinned in round 3, and
nothing since re-derived them — in the file that calls itself the
contract. Recomputed to atm_961f033d / atm_12cc1dc2, and the exact
normalize() is now pinned in the doc (collapse whitespace, casefold,
strip trailing punctuation — order matters). Verification executes
that published function and re-derives every id, so the contract is
self-checking rather than self-asserting.
Also: stale-lock threshold quantified at 60s (the one unquantified
number in the doc), and the section 10 manifest form recorded as a
follow-up for root CLAUDE.md rather than silently changed here.
Counters unchanged (362 / 88).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
New engineering/memory-engineering/ plugin. The repo had no skill for
designing, pricing, or auditing an agent memory system: llm-wiki maintains
one vault, skillopt-sleep runs a consolidation loop, agent-harness bounds a
task loop. This bounds a store.
Four stdlib scripts, one per lens:
- memory_cost_profiler.py — construction vs query split, cost per correct
answer, amortization ratio, construction co-location warning
- memory_architecture_picker.py — scores the four paradigm families,
disqualifies on hard constraints, names the cost the choice makes you pay,
and refuses to pick when the top two tie (exit 2 + tie-breaking question)
- memory_density_auditor.py — classifies records FACT/SKILL/LOG/PROSE, finds
near-duplicates, flags staleness and time-relative wording, scores density;
runs on a real --dir or --jsonl
- forgetting_policy_linter.py — the gate. 8 checks; F1 (explicit forgetting
rule) and F4 (contradictions surfaced, never auto-merged) block at exit 4
Evidence discipline: the four-lens framing is synthesized from @N01ennn's
"How to be a Memory Engineer", but every quantitative claim is re-cited to
the primary source, and two of the article's paraphrases are corrected in the
references rather than propagated — the 47x energy figure is the spread across
ten evaluated systems (not an accuracy-matched pair), and the 97%
first-pass-error figure is Rakuten's named vendor testimonial (not a
controlled study). Per-claim confidence levels throughout.
Three classifier defects found and fixed during the build, each of which would
have produced garbage on a real repo: markdown headings inside fenced code
blocks were splitting records (258 phantom records -> 107 on a real directory);
short fragments matched trivially at 1.00 Jaccard (41 false-positive
duplicates); and signal-less prose was labeled LOG, firing LOG_HEAVY at 74% on
a documentation folder — now its own PROSE class.
Also ships 4 references (7 sources each), a seven-question forcing worksheet,
a combined example spec consumed by all three spec-taking scripts, an F1–F8
policy template, cs-memory-engineer, /cs:memory-engineering and
/cs:forgetting-audit.
Verified: all 4 scripts pass --help / --sample / --output json, stdlib-only,
correct exit codes on error paths; SKILL.md 6/6 PASS on the write-a-skill
checklist; check_plugin_json.py --all and derive_counters.py --check both pass.
Counters: skills 362->363, tools 644->648, refs 741->745, agents 102->103,
commands 116->118, plugins 88->89.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jt1sqt5kQmopyfXu2Hhjnv
Sixth review round, one substantive nit.
Section 3.1 opened "Every field is mandatory", which is false: 12 of the
18 fields are unconditionally required, and the example directly beneath
it shows two that are not (project is conditional on scope, redacted is
set by a later stage). Left as-is this would push whoever writes
memory_extract.py to over-constrain the extractor — emitting fields at
extraction time that belong to redaction, contradiction handling, or
promotion, and emitting `project` on global-scoped atoms where the schema
forbids it outright.
Replaced with the true count plus an explicit accounting of why each of
the other six is conditional or deferred, and a note that the example
carries project/redacted because of what that particular atom is, not
because either is universal. Verification now cross-checks the prose
against the schema field by field rather than pattern-matching a phrase,
so the two cannot drift apart again.
Counters unchanged (362 / 88).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Fifth review round. Three findings, all verified empirically rather than
reasoned about — two were wrong in ways that would have broken the
implementation PR's CI.
1. Section 10 claimed "tools +3", counting only scripts/*.py.
derive_counters.py counts EVERY .py outside repo-root scripts/, so the
three hooks/*.py count too. Verified by adding one file under hooks/
in this tree: python_tools moved 644 -> 645. productivity/handoff
confirms it independently — 5 scripts/ + 2 hooks/ files, documented
repo-wide as "7 stdlib-only Python tools". Corrected to +6, with the
evidence recorded so the implementation PR does not trip
derive_counters.py --check.
2. The planned layout put SKILL.md flat at the plugin root. Every
comparable agents+commands plugin nests it under skills/<name>/ —
skillopt-sleep, write-a-skill, agent-harness, handoff and llm-wiki are
5 for 5, and two of them are already cited in this doc for their hook
and staging patterns, so matching their directory shape too is the
consistent call. Tree corrected, and the plugin.json skills form
pinned to ["./skills/agent-memory"] to match.
3. Section 6 listed .memory/ as gitignored while marking adopted.log
inside it as committed, with no pattern shown. Not a contradiction but
it needed stating, because the obvious spelling does not work: a
directory-level `.memory/` ignore is never descended into, so a `!`
negation cannot re-include anything under it. Verified both spellings
in a scratch repo — `.memory/*` + negation tracks adopted.log,
`.memory/` + negation tracks nothing. Documented the working pattern
and why adopted.log is public by design (it records what already
cleared the L2/L3 bar into CLAUDE.md).
Also scoped the chmod non-negotiable to runtime-created files: git
tracks no POSIX mode beyond the executable bit, so a fresh checkout
materializes adopted.log at the cloner's umask and no in-repo
declaration changes that. Anything whose confidentiality depends on
mode bits must be gitignored, which is now stated as the reason
atoms.jsonl and staged/ are.
Counters unchanged (362 / 88) — still no SKILL.md.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Fourth review round. Five findings, all valid.
1. Section 4.1.1's L2->L3 merge assigned first_source but never source,
though the schema requires both — so memory_promote.py written against
this contract would have emitted atoms the schema rejects. Same class
as the promoted_from_projects gap from round 3. Merge now sets source
from the contributor with the latest last_seen, which also preserves
the field contract (first_source = oldest, source = newest) across the
merge boundary rather than only within one atom's history.
2. Concurrency was entirely unaddressed. SessionEnd is async and does a
read-modify-write on .memory/atoms.jsonl; two sessions on one repo
(several terminals, or worktrees) interleave and lose writes, and the
recall read can catch a partially-rewritten file. New section 5.4
reuses the repo's existing pattern rather than inventing one, citing
both precedents by line: agent-harness loop_controller.py:54-62 and
skillopt-sleep state.py:77. Writers take an exclusive lock then temp +
os.replace; readers take NO lock, because blocking UserPromptSubmit on
a lock held by an async SessionEnd would blow the 100ms budget for a
hook whose failure mode is meant to be "return nothing" — atomic
replacement is what makes lock-free reads safe. Writers that cannot
acquire within 5s drop their atoms and log it: losing one session's
candidates is recoverable, a wedged SessionEnd is not.
3. The aggregate collision claim was wrong. "Likelier than not across ~30
users" does not follow from a 0.29% per-file rate — 30 files give
8.4%, and even odds needs ~239. Replaced with the correct figures. The
conclusion (widen the id if the cap rises) was unaffected, but the
stated justification was false.
4. Fixtures used the real session id that generated this PR, which
section 6.5 — added last round precisely to stop fixture-realism
violations — forbids. All seven ids are now uniformly synthetic
(01SESSION<X>...), so none can be mistaken for real and the pattern is
assertable.
5. confidence:"verified" is the sharpest form of the extraction risk
section 9.2 only gestured at generally: hardest to assign lexically
(it requires recognising a check actually ran) yet lowest promotion
bar (1 observation, exempt from the distinct-days clause). Leaning
recorded: a rule-based extractor must never assign it — reserve it for
atoms minted by a tool that ran the check and can name it.
Counters unchanged (362 / 88).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Third review round. Both findings valid; the first is sharper than the
report framed it.
1. The spec violated its OWN admission policy inside its own examples.
Section 6 requires committed content be "interpreted, de-identified,
non-confidential" — and the fixtures named a repo that appears nowhere
in this public tree and embedded its local transcript path. Two costs:
the section 6 analogy was unverifiable to any reader of this repo, and
a project name that was not ours to publish shipped in a committed
file. Fixtures are committed data; the policy binds them.
Fixed by genericizing the example project and restating the admission
analogy against llm-wiki, which is in this tree and checkable. Added
rule 6.5 making the policy explicitly binding on the spec's own
examples, since the underlying mistake was treating fixture data as
exempt — that is the part that would otherwise recur.
2. The id hash was unspecified. Section 4.1 said hash() without naming a
function, which for Python is actively dangerous: the builtin hash()
is salted per process for str, so ids would differ every run and
merging — the mechanism the whole durability gate rests on — would
silently never fire. Now pinned to stdlib hashlib.sha256 truncated to
8 hex, with the salting hazard called out.
Also replaced the unstated 32-bit id-space assumption with arithmetic:
birthday collision is 0.0029% at the 500-atom cap, 0.29% at 5000, so
raising the cap requires widening the id. A collision silently merges
two unrelated claims' durability counters, which is the same failure
project-scoping was added to prevent.
Verification now asserts fixtures carry no unknown project slugs, and
recomputes the collision table rather than trusting the numbers in prose.
Counters unchanged (362 / 88).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Second review round. Two findings were real schema bugs that would have
corrupted promotion logic once memory_promote.py was written against it.
1. The schema could not represent the L2->L3 criterion it exists to gate.
Section 4.1 requires a claim hold at L2 in >= 2 distinct projects, but
`project` is a single string and the scope conditional FORBIDS it once
scope flips to "global" — so the multi-project evidence was discarded
at exactly the moment it stopped being an eligibility test and became
an audit trail. Added `promoted_from_projects`, required at L3 with a
minItems:2 conditional so the rule is enforced by the schema rather
than merely described in prose.
2. Atom identity was not project-scoped. `id` hashed claim text alone, so
two unrelated claims normalizing alike in different repos ("tests must
pass before merge") would collide and merge their `sessions` arrays
across projects — manufacturing false durability, since the L1->L2
gate requires sessions from the SAME project. Now
hash(claim + NUL + project) for project-scoped atoms.
This made a genuinely missing step visible: with project-scoped ids a
claim held in two projects is TWO atoms, so L2->L3 is a merge, not a
flag flip. That step was undocumented anywhere. New section 4.1.1
specifies it — group by the project-free hash, union sessions, sum
observations, min/max the timestamps, record contributors, retain the
contributing L2 atoms as the provenance chain.
3. `source` was a single string overwritten on every merge, so an
"anti-fabrication" field retained only the latest sighting and lost
the evidence that first justified the claim. Added `first_source`,
written once and never overwritten; both are now required.
Also fixed the $id ref dev -> main for a stable identifier. Deliberately
NOT switched to the github.com/blob/ form used by the repo's one other
schema: blob URLs serve HTML, not JSON, so that convention breaks any
tooling that resolves $id. Noted as pre-existing rather than propagated.
Verification now walks every JSON block in DESIGN.md plus the schema
examples, and asserts the L3 conditional is enforced rather than only
documented. Counters unchanged (362 / 88).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Six findings from automated review, all verified against the files before
acting. None architectural; all resolved in place.
1. Latency budget contradicted its own contract. DESIGN.md led with a
"hard 100 ms budget" while hooks.json set "timeout": 1 — the hook
timeout field is in SECONDS, so the contract permitted 10x the stated
budget. Split into two explicitly-named limits: a 100 ms internal
self-budget the script enforces against a monotonic clock, and the 1 s
hook timeout as a wedged-process backstop. States outright that
finishing under 1 s does not satisfy the spec.
2. The 100 ms budget was asserted with no mechanism to reach it. Bounded
the work: .memory/atoms.jsonl capped at 500 atoms with last_seen
eviction, single linear pass, bounded top-5 heap. Added open decision
9.5 requiring the budget be MEASURED before implementation, since
interpreter cold-start is the dominant cost and is not controllable
from inside the script — and naming "drop UserPromptSubmit entirely"
as an acceptable outcome. A recall hook that misses its budget every
prompt is worse than no recall hook.
3. The section 3.1 atom example omitted the required `tier` field, so a
reader could copy an invalid atom out of the doc that is meant to BE
the contract. Added; verification now parses every JSON block in
DESIGN.md, not only the schema's own examples, which is why this
drifted undetected.
4. Session ids were 8 chars in the schema examples and 24 in DESIGN.md.
Normalized to 24 everywhere; check asserts a single length across all
examples.
5. Schema $id was not a resolvable URL (GitHub blob path missing /blob/
<ref>/), which fails silently if tooling ever resolves it for $ref.
Now a raw.githubusercontent.com URL.
6. The "stated" fast path (2 sessions instead of 3) did not say whether
the >= 2-distinct-days clause survived, so one long working day could
have minted an L2 claim. Clause explicitly retained; "verified"
documented as the only exemption.
Counters unchanged (362 skills / 88 plugins) — still no SKILL.md.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Design spec only — no SKILL.md, no plugin.json, no Python. Repo counters
are deliberately untouched (derive_counters counts skills by SKILL.md).
Derived from an inspection of TencentCloud/TencentDB-Agent-Memory (MIT).
Borrows two design ideas — the L0->L3 memory tiering and the
ownership/visibility model — and rejects its integration mechanism. No
code vendored.
The core idea: flat CLAUDE.md has exactly one injection policy (always,
in full), which causes bloat, staleness, and false permanence. Tiering
splits memory by durability and gives each tier its own retrieval policy:
L0 transcripts never injected, L1 atoms recalled on relevance, L2
injected per-project at SessionStart, L3 always in context under a cap.
Promotion is deterministic and recurrence-based (>= 3 distinct sessions
across >= 2 days for L1->L2), not importance-based, and requires a live
L0 back-pointer — keeping it stdlib-only per the no-LLM-in-scripts rule.
Includes a grounded overlap analysis against existing skills. Notably
skillopt-sleep already implements the L0 reader (harvest.py walks
~/.claude/projects/*/*.jsonl) and the protected-marker-block write; the
delta is tiering, prompt-time recall, and a durability gate. Spec
concludes agent-memory must be a separate self-contained plugin rather
than an extension, since skillopt-sleep is a vendored copy carrying 23
re-vendor deviations, and cross-skill imports are a repo anti-pattern.
Rejects MemoryProxy (ANTHROPIC_BASE_URL interception) on four grounds:
reverse-engineered CC internals, subscription-to-metered billing change,
raw conversation persistence incompatible with the repo's compliance
posture, and zero test coverage.
Files: DESIGN.md, hooks/hooks.json (contract), assets/memory_schema.json.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EM5xmJ7AmTMg31rq68BCym
Addresses the residual TOCTOU raised in the fourth review. The reviewer called
it non-blocking; it verified as slightly worse than described, and the fix is
small, so it is closed rather than deferred.
The claim checks out: `mkdir(parents=True, exist_ok=True)` does NOT raise on a
symlink-to-directory, because its exists-branch tests `is_dir()`, which follows
symlinks. Demonstrated directly — mkdir succeeded silently on a planted link and
a subsequent write landed in the attacker's directory.
What the review did not note is why the second layer failed to catch it: a file
inside a swapped directory is an ordinary file, not a symlink, so
`_write_private`'s `is_symlink()` check could never see a directory swap. The
artifact-level guard did not back up the directory-level one at all.
Three changes:
- `resolve_workdir()` attempts `mkdir` FIRST and only inspects a path that
already existed, via `os.lstat` — which does not follow the final component.
That removes the check-then-create ordering.
- `open_workdir()` pins the directory with `O_NOFOLLOW|O_DIRECTORY`, and both
artifacts are written through that descriptor. An fd names an inode, so a
rename or symlink swap of the path afterwards cannot redirect the write.
- `_write_private()` creates with `O_CREAT|O_EXCL|O_NOFOLLOW` at mode 0600 —
no check-then-act window at all. An artifact from a previous run into the same
--workdir is unlinked first; unlink removes the link, never its target.
Verified against a live race: pin the directory, rename it away, plant a symlink
to an attacker directory, then write — data lands in the pinned inode, attacker
directory stays empty. Also verified a pre-planted `full_text.txt -> victim`
symlink leaves the victim's content intact and is replaced by a 0600 file we own,
and that re-running into the same --workdir still succeeds.
Degrades to the previous path-based checks where `dir_fd`/`O_NOFOLLOW` are
unavailable (Windows).
Recorded as deviation 25. Full regression re-run: EPUB bomb, EPUB entity,
extensionless sniff bomb, DOCX bomb, emitter symlink, rights gate and the
estimator path check all still refuse; a clean EPUB still extracts. All gates
green.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017zu9Gmm9S78c2t3kDLnpPX
Read the skill as a skill rather than as code, which the previous three review
rounds had not done. Four findings, all now fixed and verified.
1. The documented quick-start did not run. SKILL.md's copy-paste block referenced
$WORKDIR and $SKILLS_HOME without ever assigning them, so following it
literally produced a FileNotFoundError traceback at step 2. Both are now real
assignments, and all five steps were executed verbatim end to end as a check.
The plugin README's block had the same defect and is fixed the same way. A
quick-start that does not run is the worst kind of doc bug: it is the part a
reader trusts most.
2. A gate tool reported success for a path that was not there.
`token_budget_estimator.py --skill-dir <typo>` produced a complete,
plausible-looking budget audit — every row "missing", every cap satisfied,
exit 0 — which reads as a pass. It now refuses a missing directory, a
non-directory, and a directory with no SKILL.md (exit 2). `--full-text
<missing>` raised a bare traceback and now refuses cleanly. The other three
tools already validated their inputs; this one was the outlier.
3. Three upstream artifacts cleaned, one of them load-bearing. epub.py's
`except (KeyError, Exception)` is simply `except Exception` — it swallowed
everything including the size refusal `safe_read()` now raises, quietly
disarming deviation 17 at that call site. Narrowed so ExtractionError
propagates and only genuine parse failures fall through to the .opf glob.
utils.py emitted a dynamic {pages_label: pages} key beside a literal "pages",
colliding whenever the label was "pages"; the alias is now conditional. A
stray artifact word removed from a pdf.py comment.
4. `tool | head` no longer tracebacks. Observed once on the emitter (racy on
flush timing, 0/20 on retry) — all four CLIs now exit 141 quietly, the
standard SIGPIPE convention.
Token cost re-measured: SKILL.md 2,256 tokens resident (229 lines), references
10,216 on demand. Healthy against the ~5k practical ceiling for a resident body.
Full security regression re-run after the changes: EPUB bomb, EPUB entity,
extensionless sniff bomb, DOCX bomb, planted workdir symlink, emitter symlink
and the rights gate all still refuse; a clean EPUB still extracts.
Recorded as deviations 21-24; count synced across plugin.json, CLAUDE.md and
CHANGELOG. All gates green.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017zu9Gmm9S78c2t3kDLnpPX
Addresses the third automated review on PR #941.
[High] The magic-byte sniffing path bypassed the zip-bomb budget it was built
to enforce. extract_single_file() reads a `mimetype` member with a bare
zf.read() when the extension is unrecognized — the earliest attacker-controlled
point in the pipeline, running before a format is chosen and before any check in
zip_safety.py. zip_safety.py's own docstring claims "every read goes through
safe_read()"; this one did not, which makes it a documentation defect as much as
a security one. Now routed through safe_read(). Its ExtractionError sits outside
the surrounding except tuple on purpose, so a bomb reports as a bomb rather than
as a generic unsupported format.
Verified: a 200 MB / 1029x fixture with no file extension is refused at ~15 MB
peak RSS instead of being decompressed.
[Medium] --author / --author-url never reached the printed marketplace entry.
_plugin_manifest() threaded them correctly into the emitted plugin.json, but
_marketplace_entry() took no author parameter and hardcoded one name — so the
snippet whose entire purpose is preventing hand-edit mistakes contradicted the
manifest sitting next to it for anyone but the default author. Threaded through.
Verified: --author "Jane Doe" now appears in both.
[Low] Narrow TOCTOU between _assert_no_symlinks() and copytree. copytree already
runs with symlinks=True, so a link planted in that window is copied as a link
rather than dereferenced — no content leak. Now fully closed: the emitted tree
is re-walked after the copy, and the package is deleted rather than shipped if
any link appeared.
Verified with a monkeypatched guard that plants a symlink immediately after the
check passes: refused, package removed, secret content absent.
[Nit] plugin.json asserted "license": "MIT" unconditionally, with the "MIT
covers the converter, not the compiled content" caveat living only in README
prose. Added source.license_scope stating it in the manifest, so a tool reading
only the manifest sees the distinction, plus a code comment at the assignment.
Recorded as deviations 19 and 20; count synced across plugin.json, CLAUDE.md
and CHANGELOG.
All gates green: compileall, check_paths --all, check_dual_publish,
smoke_scripts (0 failed), derive_counters --check, check_plugin_json --all
(0 FAIL). All four CLIs pass --help / --sample.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017zu9Gmm9S78c2t3kDLnpPX
Addresses the second automated review on PR #941. All three code findings
verified against the actual behaviour, not just patched.
[Medium] shutil.copytree dereferenced symlinks the validator never saw. The
validator checks SKILL.md, the three supporting files and chapters/*.md; the
copy then followed a link anywhere else in the tree (assets/, any subdirectory)
and baked the target's real content into a package that can go out as
--distribution shareable. _assert_no_symlinks() now walks the whole tree and
refuses, and runs BEFORE the validation branch so --skip-validation cannot
bypass it. copytree also passes symlinks=True so loosening that check later
cannot silently reintroduce dereferencing.
Verified: a symlink in assets/ pointing at a secret file is refused both with
and without --skip-validation, the secret never lands in a package, and a clean
tree still emits.
[Medium] The DOCX XXE/entity guard did not extend to EPUB's ebooklib path.
Upstream hardened DOCX only. EPUB is the same zip-of-XML shape and ebooklib —
one of the packages this skill recommends installing — parsed container.xml,
the OPF and content docs with no equivalent pre-check. The guard moved to a new
book_to_skill/zip_safety.py and now runs for both formats.
Verified: an EPUB whose OPF declares an entity is refused; a clean EPUB still
extracts and detects its chapter.
[Low] No size cap before decompressing zip members. Every archive read now goes
through safe_read(), which checks the declared uncompressed size and the
compression ratio against the central directory before decompressing, and
charges actual bytes against a per-archive budget so a lying directory cannot
get past it either.
Verified: a 200 MB / 1029x bomb is refused at ~14 MB peak RSS instead of being
materialized.
[Low] The PR body's "12 numbered items" was stale against README's list. Fixed
in the PR description; the in-repo count is synced to 18 across plugin.json,
CLAUDE.md and CHANGELOG.
Recorded as deviations 17 and 18. Counters: tools 662 -> 663 (zip_safety.py);
that module is allowlisted in smoke_exceptions.txt like its siblings.
All gates green: compileall, check_paths --all, check_dual_publish,
smoke_scripts (0 failed), derive_counters --check, check_plugin_json --all
(0 FAIL). Security auditor unchanged at 0 critical / 4 high.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017zu9Gmm9S78c2t3kDLnpPX
Addresses the automated review on PR #941.
Security (the one item flagged as wanted-before-merge): upstream defaults the
extraction workdir to a fixed `<tempdir>/book_skill_work`. On a shared host that
is CWE-377/CWE-59 — any local user can pre-create the directory in a
world-writable /tmp (the sticky bit prevents deletion, not creation) and plant a
symlink named full_text.txt or metadata.json pointing at a file the victim can
write, because Path.write_text follows symlinks. Two concurrent runs also
silently clobber each other.
- Default workdir is now a fresh `tempfile.mkdtemp(prefix="book_skill_work_")`:
unpredictable name, 0700 by construction, never shared with a concurrent run.
The path is printed and carried in metadata.json's `output_text`.
- Artifacts are written 0600, and each write refuses a symlink at the target.
- An explicit --workdir / BOOK_SKILL_WORKDIR is still honoured, but is
symlink-refused, created 0700, and chmod-tightened if it already exists.
- parsers/calibre.py no longer writes its ebook-convert scratch file to the
shared directory. That also fixes a real bug the review did not name: it read
a module-level OUTPUT_DIR constant, so the scratch file ignored --workdir
entirely and escaped the directory the caller asked for.
Verified: default workdir 0700 with 0600 artifacts and a per-invocation name;
two runs get distinct directories; a 777 --workdir is tightened to 700; a
symlinked workdir is refused; and a planted `full_text.txt -> victim` symlink is
refused with the victim file left untouched.
Also from the review:
- book_skill_validator.py and token_budget_estimator.py restated the same
BUDGETS dict. Both now import SKILL_FILE_BUDGETS / CHAPTER_TOKEN_CEILING from
book_to_skill/config.py so the two gating tools cannot drift.
- Corrected the smoke_exceptions.txt rationale: the list is "modules the G8
probe trips on", not "modules that aren't CLIs". config.py, exceptions.py,
sanitize.py, parsers/__init__.py, parsers/pdf.py and parsers/text.py are
equally not CLIs and pass only because they have no argv handling.
Recorded as deviations 15 and 16; count synced in plugin.json, CLAUDE.md and
CHANGELOG. Docs updated: the workdir path is now read from the tool's output
rather than hardcoded.
All gates green: compileall, check_paths --all, check_dual_publish,
smoke_scripts (0 failed), derive_counters --check, check_plugin_json --all
(0 FAIL). Security auditor unchanged at 0 critical / 4 high (documented).
End-to-end pipeline re-run clean: extract -> verdict -> validate -> emit.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017zu9Gmm9S78c2t3kDLnpPX
CI gate G1 (check_paths.py) failed: the agent's tool table referenced
`scripts/<tool>.py`, which resolves relative to the agent's own folder, not the
skill's. Now uses `../skills/book-to-skill/scripts/...` like cs-skill-author.
Two more issues found running the full gate set locally:
- Renamed `parsers/html.py` -> `parsers/html_text.py`. A module named `html.py`
shadows the stdlib `html` package whenever its own directory lands on
sys.path[0], and `import html.parser` then fails with "'html' is not a
package". Renaming removes the hazard rather than documenting it; two import
lines changed. Verified: HTML extraction still detects chapters, emits block
boundaries, and tab-joins table cells.
- Registered the eight vendored library modules in scripts/smoke_exceptions.txt.
They are imported as `book_to_skill.*`, never run as CLIs, so gate G8's
`--help` probe can only ever fail on them. The four real entry points are
smoke-tested normally and pass.
Recorded as deviations 13 and 14 in the plugin README; count synced in
plugin.json, CLAUDE.md and CHANGELOG.
All blocking gates green locally: compileall, check_plugin_json --all (89 OK),
check_paths --all (0 findings), check_dual_publish (0 drift), smoke_scripts
(0 failed), derive_counters --check.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017zu9Gmm9S78c2t3kDLnpPX
Derived from virgiliojr94/book-to-skill (MIT). Compiles a book, docs folder, or
spec collection (PDF, EPUB, DOCX, HTML, Markdown, RST, AsciiDoc, RTF, MOBI/AZW)
into an agent skill: a resident master SKILL.md (core frameworks + chapter index
+ topic index, capped at 4k tokens) plus on-demand chapter files, a glossary, a
patterns file, and a decision cheatsheet.
The extraction library (scripts/book_to_skill/, 12 modules incl. 7 per-format
parsers) is vendored close to verbatim and keeps upstream's format chains,
chapter detection across Latin/Roman/Chinese/Thai/Korean heading styles,
invisible-Unicode (Trojan Source) sanitization, and the DOCX entity guard.
12 numbered deviations recorded in the plugin README (authoritative list):
- No implicit installs: --install-missing defaults to `report`, printing the pip
command and using the stdlib fallback, where upstream prompts on a TTY and
installs into the caller's environment.
- Rights gate: emitting a shareable package refuses without --rights from
public-domain|open-license|internal-docs|author-permission. `fair-use` is
deliberately excluded — a defence, not a licence.
- Validator merged and extended: upstream's two validators become one four-family
gate, adding budget (token caps) and index (dead chapter links, unindexed
chapters, dangling topic refs) — the failure that silently breaks navigation
while the skill still looks complete.
- Folded YAML scalars now parse, so a wrapped description no longer under-reports
its length past the 1024-char cap.
- token_budget_estimator replaces discovery_tax: tiktoken path dropped for one
deterministic estimator, post-flight budget audit added, plus an explicit
worth-converting verdict that says "just read it" below ~3x the compiled size.
- Two PRIV-ESC criticals fixed: upstream install hints contained a literal
`sudo apt install`; they now name the package manager without escalating.
Repo-native addition with no upstream counterpart — Step 11 / /cs:book-to-plugin:
upstream stops at a bare ~/.claude/skills folder this library cannot route to.
skill_plugin_emitter.py wraps a compiled skill as a full plugin package (manifest
+ cs-<slug> agent + /cs:<slug> command + README) and prints the marketplace entry
without editing marketplace.json. Its --force path is guarded against symlinks,
paths outside the destination root, and non-package directories.
Ships 4 stdlib-only tools (all --help/--sample/--output json), 5 references citing
7-8 sources each, 3 asset templates, cs-book-to-skill agent, 2 commands.
Cross-linked into write-a-skill ("author first, compile second").
Regenerated the engineering harness manifest: picked up book-to-skill plus three
skills that had drifted out (minimalist, skillopt-sleep, strict-api), 81 -> 85.
Counters: skills 362 -> 363, tools 644 -> 662, refs 741 -> 746, agents 102 -> 103,
commands 116 -> 118, plugins 88 -> 89 (derive_counters.py --check passes).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017zu9Gmm9S78c2t3kDLnpPX
Clears every reference the new G7 lint flags, then makes it blocking so the
class cannot drift back. audit/engineering-agentic-2026-07 marked the
senior-ml-engineer half of this STILL-OPEN.
Deleted rather than updated:
- agent-designer/agent_evaluator.py's _define_cost_benchmarks() held
per-token prices for gpt-4, gpt-3.5-turbo and claude-3 at 2024 rates. The
result was assigned to self.cost_benchmarks and never read by anything, so
the method is gone. Cost analysis uses the cost_usd the caller supplies per
execution log, which is the only figure that can be accurate
Made model-agnostic, following the precedent already set by
senior-prompt-engineer/scripts/prompt_optimizer.py's --price-per-mtok:
- senior-ml-engineer SKILL.md and llm_integration_guide.md drop both 2024
price tables and the context-window table (which claimed GPT-4 = 8,192).
calculate_cost() takes rates as parameters; count_tokens() takes an
encoding name, since encodings outlive model IDs and
encoding_for_model() raises KeyError on anything unmapped
- OpenAIProvider loses its default model, so the caller must pass one
- llm-cost-optimizer's routing table names tiers, not models
Pinned to current IDs where an example genuinely needs one: SKILL_PIPELINE.md
(claude-opus-4-6 -> claude-opus-5), prompt-governance (claude-sonnet-4-5 ->
claude-sonnet-5), agent-designer README. Both dual-publish copies of the CAIO
pricing move together, so G4 stays green.
TEAM_STRUCTURE_GUIDE.md documented `prompt_optimizer.py --model gpt-4 --task
classification`. That contract no longer exists: there is no --task flag and
`prompt` is a required positional. Replaced with a runnable invocation.
Four references stay, with reasons in the allowlist: two litreview examples
where the retired model is the subject of the literature being reviewed, one
dated Computer Use citation, and the embedding benchmark already labelled a
2024 snapshot.
Assisted-by: Claude Code:claude-opus-5
audit/newgen-2026-06/00-MASTER.md proposed a "model-name freshness ... regex
deny-list for retired model identifiers" gate. It was never built, which is
why retired IDs and 2024 price tables survived both the June and July 2026
audits and are still in the tree today.
check_model_freshness.py flags references that mislead or break on execution:
script defaults, config values, cost tables keyed on a retired model, and
copy-pasteable CLI examples pinning a retired versioned ID. It distinguishes
these from legitimate dated citations, which stay silent when the line carries
a year, an arXiv ID, or wording like "model card" / "as of" / "historical" —
unless the line also looks like a live default, since
`model: str = "claude-3-opus" # 2024 default` still breaks.
Haiku 4.5 is excluded from the Claude 4 sweep in the patterns rather than
per-file, because claude-haiku-4-5-20251001 is current.
Advisory (continue-on-error) for now: it reports 34 references, 13 of them in
executable positions, and the content fixes land in the next change. Flip to
blocking there. --executable-only prints just the 13 that matter first.
Assisted-by: Claude Code:claude-opus-5
Every existing gate reads frontmatter with a regex or a line scan
(generate-docs.py, sync-codex-skills.py, check_paths.py), so a block that is
not valid YAML passed CI while Claude Code loaded the skill with no metadata.
The 14 files fixed in the previous commit had drifted that way unnoticed.
check_frontmatter.py parses each block with yaml.safe_load and enforces what
Claude Code actually reads:
errors - unparseable YAML, non-mapping frontmatter, missing description,
missing agent name, an agent name containing ':' (refused since
CC 2.1.218), or a missing frontmatter block
warnings - keys outside the current skill/agent frontmatter spec, and a
combined description + when_to_use over the 1536-char cap that
the skill listing truncates at
Warnings are non-blocking so this lands without requiring the wider metadata
cleanup; --strict flips them fatal. The run also tallies the off-spec keys no
runtime reads (license 172, metadata 125, domain 76, compatible_tools 37,
triggers 14), which gives that cleanup a worklist regenerated on every run.
Clean on the current tree: 593 files, 0 errors, 17 warnings.
Assisted-by: Claude Code:claude-opus-5
skill_validator.py required frontmatter fields ["Name", "Tier", "Category",
"Dependencies", "Author", "Version"] and sections ["Name", "Description",
"Features", "Usage", "Examples"]. That is the bold key/value convention used
by its own assets/sample-skill fixture, not YAML frontmatter and not a schema
any real skill has followed. All 362 skills failed both checks identically, so
skill-quality-review.yml has been printing the same two errors on every run
and nobody has acted on them.
- frontmatter now requires name + description, what Claude Code actually
reads, and lists the current optional fields for reference
- the fixed section list becomes a scored recommendation drawn from measured
usage. No heading appears in even 30% of the 361 real SKILL.md files, so a
required list cannot be justified; a miss is now a warning, not an error
- _check_external_imports uses sys.stdlib_module_names instead of a
hand-maintained set. The old set omitted __future__, so every script using
`from __future__ import annotations` was reported as carrying an external
dependency. Real third-party imports are still caught
- the sample-skill fixture gets valid YAML frontmatter, so the reference
implementation stops teaching the schema that caused this
cfo-advisor goes from 86.4 with 2 bogus errors to 95.5 with none. The one
remaining error class, "SKILL.md too short: minimum 100 lines", is left alone:
it contradicts skill_review_checklist_runner.py's under-100-lines check and
SKILL-AUTHORING-STANDARD.md's 10KB cap, and picking a winner belongs with the
wider CONVENTIONS.md reconciliation.
Assisted-by: Claude Code:claude-opus-5
Twelve files had frontmatter that yaml.safe_load rejects, all from the same
cause: an unquoted plain scalar containing ": " inside description. Claude Code
responds by loading the body with empty metadata, so the skill keeps working
via /name but has no description for the model to match against, and the seven
affected agents (where name and description are required) may not load at all.
Eleven are fixed by quoting the existing scalar, leaving the text
byte-identical. design-system carries both ' and " so quoting would defeat the
repo's regex extractors in generate-docs.py and sync-codex-skills.py; its one
colon-space is reworded instead ("Precedence:" -> "Precedence is").
Two agents had no frontmatter at all and were being listed with a placeholder
description; both now declare name and description. tools is deliberately
omitted so they keep inheriting the full set, as before.
Assisted-by: Claude Code:claude-opus-5
- Replace subprocess.run(cmd, shell=True) with shlex.split(cmd, comments=True) +
shell=False. Recipe templates contain unquoted {placeholder} tokens clearly
meant for future parameter substitution; shell=True combined with any future
substitution logic is a straightforward shell command injection vector, since
none of the placeholder positions are quoted. Removing shell=True closes that
class of bug now, before substitution is added, instead of relying on future
contributors to remember to quote/escape interpolated values.
- Require an explicit --yes flag before executing a non-dry-run recipe. Several
recipes are irreversible (gws drive files emptyTrash, gws gmail
users.messages send, gws drive permissions create, ...); previously --run
alone (without --dry-run) executed them immediately with no confirmation
gate.
This document outlines a skill for suggesting and vetting business names that align with cultural origins and market appropriateness. It includes steps for gathering information, running fit checks, suggesting names, and verifying their suitability.
Review round 8 on PR #921 found the third misattribution path: plain
'Name will ...' lines credited any sentence-initial capitalized word
outside a small pronoun list — 'Friday will be a half day' rendered as
a commitment owned by 'Friday' with no ORPHAN flag. Two deterministic
guards added, applied to both the entry pattern and the checkbox
refine pass:
- NON_OWNER_WORDS: pronouns + weekdays + months + common non-name
sentence starters (Today/Tomorrow/Next/Last/There/...)
- STATIVE_CONTINUATIONS: 'will be/need/probably/likely/not/...' reads
as a prediction or status, not a commitment — the line is simply not
an action item
Verified: all three reviewer examples no longer captured; real
commitments (Maria will send..., Alex will confirm...), checkbox
refines, the round-5 committer case, and the round-7 ORPHAN case all
unchanged; --help/--sample clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TQLKzYb1bR2LYqwYUupm5f
Review round 7 gut-check on the MENTION_ANY fallback, resolved in favor
of scoping: '- [ ] follow up with @sam about pricing' no longer credits
sam — a mid-text mention is the task's object, not its owner (the same
misattribution shape as the round-5 bug, via a different entry path).
Head-anchored mentions ('@sam: book the room', '@sam book the room',
'@sam to book the room') still attribute and strip the owner phrase;
object-only lines now flag ORPHAN for a human to assign, per the
skill's never-silently-guess rule. Docstrings updated; unused
MENTION_ANY_RE removed.
Verified across six patterns incl. the round-5 regression case;
--help/--sample clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TQLKzYb1bR2LYqwYUupm5f
Review round 6 on PR #921 found (and execution confirmed) that batch B
was appended directly, bypassing advance(): on tight schedules
(start_b == cursor) two work blocks landed back-to-back with
'Buffers 0min', violating the docstring's own buffer invariant. The
backward pass now reserves BUFFER_MIN whenever batch B would directly
follow a work block: the overflow check includes it (a day that only
fits without the buffer is now correctly refused, exit 2) and a
explicit Buffer event is emitted when it fits.
Also fixes the cosmetic inconsistency in action_item_extractor's
ACTION:/TODO: path — a leading '@owner will/to' inside the captured
text now strips the owner phrase (matching the Name-will branch), so
'ACTION: @sam to book X' renders as 'book X' under sam.
Verified: tight two-batch day refuses by exactly 10 min; +10-min day
fits with visible buffer; deep->batchB and roomy (buffer+flex) days
correct; --help/--sample clean on both scripts; mid-text-mention and
ORPHAN behavior unchanged.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TQLKzYb1bR2LYqwYUupm5f
Review round 5 on PR #921 found a real, silent misattribution:
'@maria will ask @sam to review the doc by Friday' credited sam (the
person being asked) instead of maria (the committer), because
extract() ran the _extract_owner_and_text refine pass unconditionally
and MENTION_ANY_RE matched the second @mention. The refine pass now
runs only when no owner was captured at the head of the line — its
original purpose (checkbox/ACTION-prefix lines that start ownerless).
Verified all four paths: owned-@mention keeps the committer, 'Name
will ... @other' prose keeps the committer, checkbox '@sam to ...'
still refines to sam, ownerless lines still flag ORPHAN; --help and
--sample unchanged.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TQLKzYb1bR2LYqwYUupm5f
Closes the last open note from PR #921's review loop: usage errors
(malformed --topic, missing/bad flags) now exit 1 like
meeting_cost_calculator, keeping exit codes 0/2/3 exclusively for
verdicts across the 9-script batch. Epilog updated; all five exit
paths re-verified (usage=1, no-outcome=2, overflow=3, sample/help=0).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TQLKzYb1bR2LYqwYUupm5f
- meeting_cost_calculator.py: usage errors now exit 1 instead of 2, so
the ASYNC verdict (exit 2) is unambiguous for exit-code-driven
callers; epilog documents the new code
- focus_session_logger.py: top-level --json now works with --sample
(canned JSON status), matching the uniform --sample --json contract
of the other 8 scripts; subcommand --json unchanged
- time_block_planner.py: deep-only overflow no longer says 'defer
shallow work ... trim the deep blocks' — it now names deep demand as
the cause when there is no shallow work to defer
Verified: usage-err=1 / ASYNC=2 / MEET-sample=0; --sample --json parses
as JSON; subcommand --json regression-checked against a real state
file; deep-only overflow message exercised; --help sweep clean on all
30 productivity scripts.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TQLKzYb1bR2LYqwYUupm5f
Per review note on PR #921 — the three new plugins were stamped 2.11.1;
new entries should carry the current release version. plugin.json +
marketplace entries updated; validators and counter check still clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TQLKzYb1bR2LYqwYUupm5f
- agenda_builder.py: parse --topic with right-anchored split so desired
outcomes may contain colons (structured minutes/owner fields split
from the right, title at the first colon); clearer malformed-spec
error text
- focus_session_logger.py / action_item_extractor.py: bare tuple return
annotations -> typing.Tuple for consistency with the files' own style
Verified: --help/--sample exit 0 on all touched scripts; colon-bearing
outcome ('Decide: usage-based vs seat-based') parses and still sorts
decision-first; malformed topic still hard-errors. The reviewer's
time_block_planner lunch/overflow edge case was checked empirically:
batch B is anchored to --end and backward-pass lunch insertion is
guarded by 'lunch + 30 <= start_b', so the day never extends past
--end; the worst case is an explicit 'lunch could not be placed' note.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TQLKzYb1bR2LYqwYUupm5f
Picks up weekly-review, deep-work, meetings — plus previously unsynced
skills (fable-goal, skillopt-sleep, agent-harness, and other strays the
automation had not yet mirrored). Vibe/Hermes/Codebuff home-dir syncs
verified in-session (11 productivity skills discovered each).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TQLKzYb1bR2LYqwYUupm5f
Resolves conflicts in CLAUDE.md, README.md, and marketplace.json between
this branch's v2.11.2 skillopt-sleep vendoring and dev's productivity/fable-goal
addition — both narratives are kept, ordered by landing time. Headline
counters (skills/tools/refs/agents/commands/plugins) re-derived from the
merged tree via scripts/derive_counters.py and brought back into agreement
across all three files (--check now passes).
parser.error (exit 2) instead of silently preferring --sample when both
a prompt file and --sample are passed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YYh4KrhicuBaS5nRtBeLXK
Sixth review round asked for the CHANGELOG.md entry matching the
established [Unreleased] backfill convention (roast, local-seo-manager).
Mirrors the CLAUDE.md post-v2.11.1 narrative block.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YYh4KrhicuBaS5nRtBeLXK
- CLAUDE.md gains an 'Unreleased (post-v2.11.1)' narrative block for
fable-goal so the changelog-of-record covers the addition without
inventing a release version (review round 5 ask; counters in arrow
form to stay clear of derive_counters claim regexes — check passes)
- goal_prompt_self_check.py destination pattern now matches 'the N
links' phrasing ('the \d*\s*links?'); --sample still 6/6, verified
'the 3 links' now matches standalone
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YYh4KrhicuBaS5nRtBeLXK
Two independent reviews flagged the missing scripts/ folder against the
productivity-domain convention and the repo's 'Algorithm over AI'
principle. Adds one stdlib tool, goal_prompt_self_check.py, which
mechanically verifies the checkable subset of the SKILL.md step-5
self-check on a drafted /goal prompt: word count in the 150-350 band,
goal line, autonomy directive, verification-loop language,
creative-freedom grant, and delivery destination. Exit 0/1/2; --sample
and --output json supported; judgment calls (deliverable concreteness,
resource verification) explicitly stay with the author.
Smoke-verified: --help OK, --sample passes 6/6, degenerate prompt fails
0/6 with exit 1. SKILL.md references the runner in step 5 (79 lines,
checklist still full PASS). agents/ and assets/ remain intentionally
omitted: a single reasoning pass has nothing to orchestrate and no
templates to ship. Counters: python_tools 602 -> 603.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YYh4KrhicuBaS5nRtBeLXK
- plugin.json + marketplace version 2.11.2 → 2.11.1 (tracks repo version
at touch time, matching sibling plugins)
- attribution block clarifies the upstream informal grant is not SPDX and
that the MIT declaration covers only text authored in this repository
- /cs:fable-goal command gains argument-hint frontmatter (roast/handoff
convention)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YYh4KrhicuBaS5nRtBeLXK
Improved port of duncan-buildroom/freeskills fable-goal ('free to use and
modify'). Converts a rambling description of a desired outcome into one
polished, copy-paste /goal prompt for a fresh autonomous session.
Improvements over upstream:
- Wrong-tool check (build-now vs write-the-prompt) promoted into the body
- Observable-done principle: every deliverable gets a self-checkable
completion condition
- Six-slot extraction (deliverable/quantity/stakes/tools/quality/destination)
- Per-medium verification defaults (web, CLI, video, written, data, design)
- Six-point pre-delivery self-check
- Anti-pattern list + failure-mode catalog reference with rationale per
anatomy part
- Second worked example in a non-web medium (CLI with dry-run verification)
- /cs:fable-goal command; attribution block in plugin.json
SKILL.md passes the write-a-skill 6-item checklist (full PASS, 77 lines).
Counters trued up via scripts/derive_counters.py (includes pre-existing
engineering drift 81→83): skills 355→358, refs 731→732, commands 109→110,
plugins 83→84.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YYh4KrhicuBaS5nRtBeLXK
ceo-advisor and cto-advisor SKILL.md files live under skills/, but the
README links pointed one directory too shallow.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
A tenth review pass, after confirming all nine prior rounds of fixes
hold up under independent re-reading, found two more low-severity
gaps and offered to accept a follow-up -- fixed both now for
consistency with how every prior round's findings were handled:
1. schedule had no confirmation gate at the CLI layer. The "confirm
with the user before schedule" safeguard (deviation #15) lived only
in commands/skillopt-sleep.md's agent-facing instructions --
cmd_schedule() called scheduler.schedule() directly and installed a
real crontab entry immediately. Fine for the documented Claude Code
agent workflow (which confirms in chat first), but anyone invoking
`python -m skillopt_sleep schedule` directly bypassed it entirely.
Fixed: schedule now requires --yes; an interactive terminal without
it gets a [y/N] prompt, a non-interactive one refuses outright
(exit 2) pointing at --yes. commands/skillopt-sleep.md updated so
the driving agent passes --yes once it has confirmed with the user
in chat -- that's what --yes records, not a redundant re-prompt
that would hang forever with no TTY inside a non-interactive Bash
tool call.
2. mkdir-then-chmod wasn't atomic in write_staging()/SleepState.save(),
leaving a brief window where a freshly-created sensitive directory
sat at the process's default umask. Fixed: the os.makedirs() calls
creating the state dir, staging leaf dir, and backup dir now pass
mode=0o700 directly, on top of (not instead of) the existing
post-creation chmod calls, which still matter for intermediate
parent dirs and pre-existing directories that mode= doesn't cover.
The equivalent race for individual files was judged a larger
rewrite (every open() call site would need os.open() with an
explicit mode) than this specific low-severity finding warranted --
documented as a known, narrower residual gap rather than silently
claimed as fully closed.
Verified: non-interactive schedule without --yes refuses with exit 2,
with --yes it proceeds to the same scheduler.schedule() call as
before; a synthetic run confirms state dir/state.json/staging leaf
still land at 0700/0600/0700 after the mode= change.
Added as README deviations #22-23 and reconciled the count across all
three documents to 23 (6 cosmetic, 17 safety/hardening) across ten
review rounds -- cross-checked with grep.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TX374i2YGrjNV4Yi3AmaKS
A ninth review pass found scheduler.py's schedule()/unschedule() both
located "this project's" managed cron line via marker not in ln, a
bare substring test, not an exact-match or delimiter-anchored check.
Failure scenario: two projects scheduled where one path is a literal
prefix of the other (e.g. /home/user/app and /home/user/app-v2) --
"# project=/home/user/app" is itself a substring of
"# project=/home/user/app-v2"'s line. Running schedule() or
unschedule() for /home/user/app would silently drop app-v2's cron
entry too, with no error or warning.
harvest.py's _project_matches() (added in this same PR) already gets
this right via delimiter-anchored comparison; scheduler.py's marker
matching didn't follow the same discipline.
Fixed: added _line_matches_project(), anchored on
ln.rstrip().endswith(marker) since the marker is always the last token
of a generated line -- used at both call sites.
Also fixed the related minor nit: install-cron.sh's printed --backend
value was unquoted next to otherwise-quoted ${RUNNER}/${PROJECT} in
its heredoc (low risk since that script only prints a line for the
user to copy, never executes anything itself, but inconsistent with
the quoting discipline everywhere else).
Verified two ways: a standalone reproduction confirmed the bug before
the fix and its absence after, and a full schedule()/unschedule()
round-trip through the actual public API (crontab -l/crontab - swapped
for an in-memory fake) confirmed scheduling both /home/user/app and
/home/user/app-v2, then unscheduling only app, correctly leaves
app-v2's line intact.
Added as README deviations #20-21 and reconciled the count across all
three documents to 21 (6 cosmetic, 15 safety/hardening) across nine
review rounds -- cross-checked with grep.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TX374i2YGrjNV4Yi3AmaKS
An eighth review pass found that seven rounds of redaction fixes were
all file-level (write_staging(), diagnostics.json, state.json's
archive) but __main__.py's cmd_run() reads the same in-memory Report
object and prints EditRecord.content directly to the console, and
_report_payload() serializes it unredacted for --json --
write_staging()'s redaction runs on a copy (report.to_dict()) used
only for the on-disk JSON, it never touches report.edits itself.
Concretely: scheduler.py's cron entry redirects run's stdout/stderr
straight into <project>/.skillopt-sleep/cron.log -- a secret that
leaked into a proposed edit's content would land there in plaintext on
every scheduled night, in a file that (unlike state.json/staged files)
also had no chmod protection.
Fixed:
- _report_payload() and cmd_run()'s plain-text edit printing now run
through redact_secrets(), gated on the same redact_secrets config
flag as everywhere else.
- cmd_harvest()'s debug output (--json, --output <file>, and the
plain-text loop) gets the same treatment -- it prints raw mined
TaskRecord.intent text so a human can review it before setting
"reviewed": true on a --tasks-file, and redaction only strips
secret-shaped substrings, so it doesn't reduce what's reviewable
while closing the same leak path.
- scheduler.py's generated cron line now chmod 700s the .skillopt-sleep
log dir and chmod 600s cron.log itself (best-effort, 2>/dev/null)
before each run appends to it -- that file was never covered by the
state/staging chmod pass in an earlier round.
Verified: a synthetic secret seeded into a task's intent no longer
appears in cmd_run's --json payload, plain-text edit output, or
cmd_harvest's redacted payload; executing the actual generated cron
line end-to-end (not just inspecting the string) produces a 0700 log
dir and 0600 log file on disk.
Added as README deviation #19 and reconciled the count across all
three documents to 19 (5 cosmetic, 14 safety/hardening) across eight
review rounds -- cross-checked with grep.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TX374i2YGrjNV4Yi3AmaKS
A seventh review pass noted plugin.json's top-level description
(930 chars) was noticeably longer than this repo's typical plugin.json
descriptions (median ~600 chars) -- it duplicated detail that
attribution.derivation_note already carries in full. Trimmed to a
single dense paragraph (705 chars) that keeps the essential
what-it-does/safety-model/trigger-phrase content and points to
derivation_note for the full vendoring story, rather than repeating it.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TX374i2YGrjNV4Yi3AmaKS
A sixth review pass found sleep.sh and run-sleep.sh still described and
partially resolved against upstream's <repo>/plugins/claude-code/ and
<repo>/plugins/run-sleep.sh layout, not this vendored copy's actual
layout (scripts/ and skillopt_sleep/ as siblings directly under the
plugin root, engineering/skillopt-sleep/). The primary co-located and
repo-relative resolution branches happen to still succeed regardless
(so this was unreachable in normal operation), but the documented
SKILLOPT_SLEEP_REPO and CLAUDE_PLUGIN_ROOT escape hatches would have
silently failed for anyone actually relying on them -- e.g. after a
future re-vendor that missed copying run-sleep.sh into scripts/.
Fixed: sleep.sh's SKILLOPT_SLEEP_REPO branch now checks
$SKILLOPT_SLEEP_REPO/scripts/run-sleep.sh; run-sleep.sh's
CLAUDE_PLUGIN_ROOT branch now checks $CLAUDE_PLUGIN_ROOT/skillopt_sleep
(this repo's actual layout) ahead of the upstream two-levels-up check
(kept for portability if this script is ever reused in that shape
again). Header comments in both files corrected to describe the real
layout instead of upstream's.
Verified both previously-broken fallback branches resolve correctly
when isolated from the co-located script (copied each launcher to a
scratch dir and ran it standalone with only the relevant env var set).
Added as README deviation #18 (cosmetic/hardening) and reconciled the
count across all three documents to 18 (5 cosmetic, 13 safety/
hardening) across six review rounds -- cross-checked with grep.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TX374i2YGrjNV4Yi3AmaKS
A fifth review pass found staging.py's sk-[A-Za-z0-9_-]{10,} secret
pattern -- which matches OpenAI, Anthropic (sk-ant-...), and other
vendors sharing the sk- prefix convention -- was labeled
[REDACTED_OPENAI_KEY] regardless of which vendor's key shape it
actually matched. Redaction itself was unaffected (the text was
scrubbed either way), just a misleading placeholder if a user reads it
literally. Relabeled to [REDACTED_API_KEY].
Added as README deviation #17 (cosmetic) and reconciled the count
across all three documents (README.md's numbered list, plugin.json,
CLAUDE.md) to 17 (4 cosmetic, 13 safety/hardening) across five review
rounds -- cross-checked with grep, not just eyeballed.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TX374i2YGrjNV4Yi3AmaKS
A fourth automated review pass on PR #907 found the deviation count had
drifted out of sync across the three places that document it, plus two
more real gaps in the vendored plugin:
1. Deviation count inconsistency: plugin.json and README.md both said
13 (after round 3), but CLAUDE.md's v2.11.2 section said "8
deviations" with an itemized list that didn't map onto the real
13-item README list -- it named a "dead cross-reference to a
non-vendored design doc" as a cosmetic item that was never actually
added as a numbered README deviation (it was fixed in round 3's
commit but never itemized). Fixed: added it as README deviation
#14, updated plugin.json's derivation_note with a note that
README.md's numbered list is the single source of truth if any
summary disagrees again, and rewrote CLAUDE.md's bullet to match.
2. commands/skillopt-sleep.md's action table listed `schedule` as an
ordinary action alongside safe previews (`status`/`dry-run`/`run`),
while its own "Safety reminders" section separately said to point
users at the print-only install-cron.sh instead -- two
uncoordinated stories about the same action. scheduler.schedule()
writes directly to the user's real crontab the moment it runs, with
no confirmation step. Fixed (README deviation #15): "Steps to
follow" now has an explicit step 1 telling the agent to confirm
with the user before running `schedule`; "Safety reminders" no
longer contradicts the action table.
3. state.json (the cross-night task archive) and
.skillopt-sleep/staging/<ts>/'s proposal/report/diagnostics files
contain real harvested session content in plaintext, created via
plain os.makedirs/open(...,"w") -- world-readable-by-default on a
typical multi-user box. Fixed (README deviation #16): state.py and
staging.py now chmod every directory they create to 0700 and every
file they write to 0600 (best-effort). Live CLAUDE.md/SKILL.md
files are intentionally left alone -- those are the user's own,
often-committed files, not new output this plugin introduces.
All three documents (README.md's numbered list, plugin.json's
derivation_note, CLAUDE.md's v2.11.2 section) now agree on 16
deviations (3 cosmetic, 13 safety/hardening) -- verified by grep.
Verified: py_compile clean, mock-backend dry-run still exits 0, a
synthetic test confirms state dir/state.json/staging dir/staging files
land at 0700/0600/0700/0600 respectively after this fix (previously
default umask permissions), all 4 repo CI gates pass locally.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TX374i2YGrjNV4Yi3AmaKS
A third automated review pass on PR #907 found 2 HIGH and 5 further
gaps in the vendored skillopt-sleep plugin, all in the same family as
rounds 1-2 (a safety claim in the docs the code didn't fully back up):
HIGH:
1. state.py's add_to_archive() persisted raw TaskRecord content
(intent/context_excerpt/attempted_solution -- real harvested
prompt/response text) to ~/.skillopt-sleep/state.json indefinitely,
entirely outside the staging dir a user is ever told to review.
Fixed: cycle.py now redacts each task dict before archiving, using
the same redact_enabled flag as everything else.
2. report.md / report.json were never redacted, despite being the two
files a human is told to read FIRST (the SKILL.md's own workflow:
"show the user the exact proposed edits"). EditRecord.content/
.rationale come from the optimizer's reflect() output over real
failing task responses. Fixed: write_staging() now redacts the
rendered report_md string and report.to_dict() before writing.
MEDIUM/LOW:
3. replay_mode: "fresh" (worktree replay) was declared in config but
never implemented anywhere -- only fed a cosmetic report label.
Implementing real worktree isolation was judged too invasive for a
vendored copy; instead cycle.py now warns loudly when it's set to
anything but "mock" rather than silently implying isolation that
isn't happening.
4. backend.py shipped an AzureOpenAIBackend/AzureResponsesBackend pair
with 5 internal-looking Azure endpoint hostnames and a hardcoded
Managed Identity client ID, commented as sourced from "the intern's
avail_api.md" -- reads like leaked internal Microsoft dev infra.
Already unreachable from this plugin's documented mock/claude/
codex/copilot --backend choices and requires deps this repo doesn't
vendor. Removed entirely (classes, constants, get_backend()/
build_backend() dispatch branches, the now-unused azure_endpoint
param); get_backend("azure") now safely falls back to MockBackend.
5. attempt_with_tools() (all three CLI backends) used a task's tool
name both as a shim filename and interpolated unescaped into the
shim's generated shell body. Tool names originate from a
hand-authored --tasks-file's judge.checks[].arg, never validated --
not reachable via harvest/mine today, but a documented user-facing
input. Fixed: a shared _sanitize_tool_names() helper filters to a
safe-identifier allowlist before any name is used as a filename or
shell text.
6. SKILL.md pointed to a design doc path (docs/superpowers/specs/...)
that was deliberately not vendored. Fixed: points to the real
upstream guide URL instead, with a note on why the local path is
absent.
7. CLAUDE.md's "Current Scope" line claimed v2.11.2 but no dated
version section existed for it. Added one matching the repo's
established per-release convention.
All 13 deviations (2 cosmetic, 11 safety/hardening) cross-documented
in plugin.json's derivation_note and README.md's "Deviations from
upstream" + "Safety model" + "What was and wasn't vendored" sections.
Verified: py_compile clean, mock-backend dry-run still exits 0, all 4
repo CI gates pass, and a synthetic test with a real API-key-shaped
secret confirms it appears in NONE of state.json's task archive,
report.md, or report.json after this fix (all three fired positive
signal for the leak before it).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TX374i2YGrjNV4Yi3AmaKS
A second automated review pass on PR #907 confirmed the prior 3 safety
patches and found 3 more small gaps:
1. plugin.json's attribution.derivation_note still asserted "no logic
modified" after the round-1 patches changed staging.py/scheduler.py/
cycle.py/backend.py. Updated to match README.md's deviation log.
2. redact_secrets was declared in config.py's DEFAULTS but never read
anywhere -- write_staging() redacted unconditionally regardless of
the flag (safe direction, but a dead config knob). Wired
cfg.get("redact_secrets", True) through write_staging() and the
diagnostics.json fields; disabling it is honored but never
silently -- fires a loud report note.
3. scheduler.py's _runner_cmd shlex.quote()-d project/logdir/log/repo
root (round-1 fix) but left the `extra` flags parameter raw. Not
exploitable today (it's only ever a hardcoded literal), but closes
the same class of gap defensively via shlex.split + per-token
shlex.quote so a future multi-flag `extra` can't reopen it.
Also applied the reviewer's non-blocking hardening suggestion: adopt()
now re-runs redact_secrets() on staged content before writing to the
live path (read+redact+write instead of a raw shutil.copy2), covering
the case where a staged proposal is hand-edited between `stage` and
`adopt` -- exactly the workflow staging exists to allow.
All 6 deviations now cross-documented in plugin.json's
derivation_note and README.md's "Deviations from upstream" +
"Safety model" sections so re-vendoring can't silently drop them.
Verified: py_compile clean, mock-backend dry-run still exits 0,
synthetic tests confirm both the empty/populated extra-quoting paths
and the redact_secrets on/off report-note behavior, all four repo CI
gates (smoke_scripts, check_plugin_json, check_paths, derive_counters)
pass locally.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TX374i2YGrjNV4Yi3AmaKS
Automated review on PR #907 read the actual module code (not just the
surface docs) and found the vendored plugin's own safety claims didn't
fully match its behavior. Patches applied directly to our vendored copy
(documented as deviations in the plugin README for re-vendor):
1. staging.py: redact_secrets() was applied to diagnostics.json but not
to proposed_SKILL.md/proposed_CLAUDE.md -- the exact files adopt()
copies over the live CLAUDE.md/SKILL.md (with --auto-adopt, with no
human in the loop). A secret pasted into a real debugging session
could have landed in live memory unredacted. Now redacted before
write_staging() persists either file.
2. scheduler.py: the generated crontab line interpolated an arbitrary
project path via unescaped f-string into a command cron runs through
sh -c on every fire. A path containing shell metacharacters could
break out of the quoting. Now shlex.quote()-d.
3. cycle.py: max_tokens_per_night was declared in config.py's DEFAULTS
and budget.py already had a Budget/plan_depth heuristic built for
it, but nothing in the production run_sleep_cycle() path ever read
it -- a real-backend night had no actual token ceiling. Now a
Budget starts right after backend construction (harvest/mine spend
counts too), sizes dream_rollouts down via plan_depth() when
remaining budget is tight, and the report notes when it caps
rollouts or the budget is exhausted -- no silent truncation. This
caps rollout depth per task, not a hard mid-call abort; documented
as a residual limitation in the README.
Also dropped a leftover hardcoded nvm path in backend.py's
resolve_codex_path() (the generic scan a few lines below already
covers it) and added a one-line acknowledgment to CLAUDE.md's
Anti-Patterns list that this plugin's non-mock backends are a
documented, opt-in exception to "no LLM calls in scripts" -- not
precedent for adding LLM calls to analysis/reference skills.
Verified: py_compile clean, mock-backend dry-run still exits 0,
synthetic test confirms dream_rollouts capping actually engages under
a tight budget and is a no-op under the default budget, all repo CI
gates (smoke_scripts, check_plugin_json, check_paths, derive_counters)
still pass.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TX374i2YGrjNV4Yi3AmaKS
.gemini/skills/memory-status/SKILL.md symlink was added in the
previous commit but its skills-index.json entry was missed, so the
skill was discoverable on disk but not listed in the generated index.
Added the entry (mirroring the memory-review one already present) and
bumped total_skills 419 -> 420 to match.
Addresses review feedback on PR #906.
scripts/smoke_scripts.py runs every .py file standalone as
`python3 <file> --help`, but the vendored skillopt_sleep engine is a
package meant to be invoked only via `python -m skillopt_sleep` (already
verified working). Running any single file directly breaks two ways:
1. skillopt_sleep/types.py shadows the stdlib `types` module once the
file's own directory is prepended to sys.path, cascading into
"cannot import name 'GenericAlias'/'asdict' from partially
initialized module" for every sibling that imports
dataclasses/typing.
2. experiments/*.py use absolute `from skillopt_sleep.x import y`
imports that require the package's parent directory on sys.path,
which standalone execution doesn't provide.
Listed all 29 affected files in smoke_exceptions.txt with reasons,
following the existing autoresearch-agent/handoff precedent for
fixed-contract, non-standalone scripts.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TX374i2YGrjNV4Yi3AmaKS
Renaming engineering-team/self-improving-agent/skills/{review,status}
to memory-{review,status} left several committed generated mirrors
pointing at now-deleted source paths:
- .codex/skills/review and .gemini/skills/review/SKILL.md were dangling
symlinks; repointed to engineering-team/playwright-pro/skills/review,
the plugin that actually owns the bare "review" name now that
self-improving-agent no longer collides with it.
- Added .codex/skills/memory-review, .codex/skills/memory-status,
.gemini/skills/memory-review/, .gemini/skills/memory-status/
symlinks, and matching entries in both skills-index.json files
(counts bumped accordingly).
- Regenerated the engineering-team agent-harness manifest
(harness_manifest_builder.py --domain engineering-team) so its
path/name/description entries match the renamed skills.
Scoped by hand to just the self-improving-agent review/status entries
rather than a full re-sync, to avoid pulling in unrelated pre-existing
sync drift (skills added in earlier merges that were never synced) and
unrelated non-deterministic name-collision reordering (e.g. "status"
between autoresearch-agent/agenthub, "run" likewise) that a full
regen would otherwise touch. .hermes/ and .vibe/ were verified
unaffected — self-improving-agent is mirrored there only as a single
symlink to the plugin's main skill, not per-sub-skill.
Addresses review feedback on PR #906.
CI's check_paths.py regex-matches any "<word>/SKILL.md" substring as a
relative path reference. The vendored SKILL.md frontmatter said
"CLAUDE.md/SKILL.md" in prose, which the linter misread as an
unresolvable path. Reworded to "CLAUDE.md and SKILL.md" — no behavior
or meaning changed. Documented the deviation in the plugin's README so
it carries forward on re-vendor.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TX374i2YGrjNV4Yi3AmaKS
Verbatim copy of the stdlib-only skillopt_sleep engine + Claude Code
plugin surface (skills/hooks/commands/scripts) into
engineering/skillopt-sleep/. Gives a local agent a nightly gated
self-improvement cycle: read-only harvest of past Claude Code session
transcripts -> mine recurring tasks -> offline replay -> held-out-gated
CLAUDE.md/SKILL.md edits -> staged for explicit /skillopt-sleep adopt.
Nothing live changes without that explicit step.
The heavier skillopt training package (needs numpy/openai/azure-* +
hand-labeled benchmarks per task) was deliberately not vendored, since
it optimizes one narrow scoreable task at a time and doesn't fit this
repo's broad domain-expertise skills or no-ML-in-scripts convention.
Attribution preserved in plugin.json + LICENSE + README.md (MIT,
Microsoft Corporation / Yifan Yang), following the same verbatim-vendor
pattern already used for loop-library/. Registered as its own
marketplace plugin; headline counters in README.md/CLAUDE.md/
marketplace.json trued up via scripts/derive_counters.py --check.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TX374i2YGrjNV4Yi3AmaKS
.claude-plugin/marketplace.json (the marketplace registry, not a
generated tool-sync mirror) still advertised /si:review and /si:status
after the memory-review/memory-status rename in the previous commit.
Addresses review feedback on PR #906.
- convert.sh's SKILL.md finder now excludes .claude, .codex, .codex-plugin,
.gemini, .hermes, .vibe, and docs — these are generated/symlinked mirrors
for other tools, not source-of-truth skills. On platforms where git
materializes symlinks as plain text (e.g. Git Bash on Windows), the
mirrored files were being parsed as SKILL.md candidates and failing
frontmatter extraction, flooding the run with "Skipping invalid
frontmatter" warnings (#897).
- Renamed the self-improving-agent (si) plugin's `status` and `review`
skills to `memory-status` and `memory-review` so their bare `name:`
values no longer collide with Claude Code's built-in `/status` and
`/review` commands (#885). Updated all in-plugin references
(CLAUDE.md, README, agents, hooks, references, settings.json,
plugin.json) to the new `/si:memory-status` / `/si:memory-review`
invocations.
Fixes#897 (duplicate of #896), #885.
The demo company is explicitly Brazil-set (Jurisdiction: Brazil), so
preserving the local legal-entity term is more faithful than genericizing
it: 'MEI — Microempreendedor Individual, sole-proprietor entity — to be
defined'. Mirror re-synced; example lint PASS; counter (G3) + dual-publish
gates exit 0.
https://claude.ai/code/session_01CUWsrUNZP9jpxvAwq67UiT
The '(English)' parenthetical made sense only as the '(PT-BR)' flag on
the original Portuguese description; on an English description it's
redundant. Now matches the marketplace.json / codex-index phrasing
('Company Architect: builds...'). plugin gate exit 0.
https://claude.ai/code/session_01CUWsrUNZP9jpxvAwq67UiT
- .codex/skills-index.json: reset to dev and re-applied ONLY the two
arquiteto description changes via a JSON round-trip, dropping the
unrelated review/run/status entry reorderings the full regen had pulled
in (diff is now exactly 2 lines, no ambiguous-name churn).
- phase_playbook.md: the data-protection question kept the specific
citation instead of a bare generic — 'data-protection law — e.g. GDPR /
LGPD / CCPA, per jurisdiction' (jurisdiction-aware, not Brazil-only).
- exemplo-bundle/index.md: suggested-next-step no longer says 'finish
problema-solucao.md' (that stub now has content) — points at the real
remaining PHASE-1 gap (manifesto.md) instead.
Mirror identical; example-bundle lint PASS; dual-publish/plugin/counter
gates exit 0.
https://claude.ai/code/session_01CUWsrUNZP9jpxvAwq67UiT
Normalize the usage-line comment gap left misaligned by the earlier
./minha-empresa -> ./my-company rename (path was 3 chars longer).
Cosmetic docstring-only; no behavior change. Mirror re-synced identical.
https://claude.ai/code/session_01CUWsrUNZP9jpxvAwq67UiT
The translated skill left two discovery surfaces describing it in Portuguese:
- .claude-plugin/marketplace.json (ClawHub-facing): description rewritten to
English, keywords de-Portuguese-d (drop 'empresa-como-codigo',
'bundle-de-conhecimento', 'pt-br'; add 'company-architect'); slug keyword
'arquiteto-de-empresa' kept for discovery under the preserved slug.
- .codex/skills-index.json (Codex CLI routing): regenerated via
sync-codex-skills.py; both dual-publish entries now carry the English
SKILL.md description + English triggers.
Reverted 3 unrelated symlink retargets the codex sync emitted for ambiguous
skill names (review/run/status) — out of scope for this PR. Both JSON files
validate; plugin + counter gates exit 0; no Portuguese remains in either
registry for this skill.
https://claude.ai/code/session_01CUWsrUNZP9jpxvAwq67UiT
Final review sweep caught two non-accented residuals a prose-grep misses:
- scaffold_bundle.py slugify() fallback "empresa" -> "company" (a code
default, not a preserved slug — fires only on all-punctuation input)
- example destination path ./minha-empresa -> ./my-company in SKILL.md
and the 3 scripts' usage docstrings, so the translated display name
'My Company' no longer maps to a Portuguese folder in the same line
Mirror re-synced identical; scaffold --sample JSON ok; example-bundle
lint PASS; py_compile clean; dual-publish exit 0.
https://claude.ai/code/session_01CUWsrUNZP9jpxvAwq67UiT
Fixes two cosmetic inconsistencies I introduced in the problema-solucao.md
example stub:
- tags: [fundacao, problema-solucao] -> [foundation, problem-solution]
(was residual Portuguese metadata the prose-grep sweep missed)
- 'Café Aurora' -> 'Aurora Café' to match the 7 other uses across the
example bundle's sibling files
Mirror re-synced; example-bundle lint PASS; dual-publish exit 0.
https://claude.ai/code/session_01CUWsrUNZP9jpxvAwq67UiT
Replaces the inline-code workaround for the example's dangling link with a
real stub concept: adds assets/exemplo-bundle/00-fundacao/problema-solucao.md
(type: Problem-Solution + [ASSUMPTION]) and restores the markdown link from
identidade.md so the example shows the OKF link graph it is meant to teach
(okf_conformance Rule 3), instead of merely silencing the linter. Folder
index lists the new concept. Mirror re-synced; example-bundle lint PASS
(0 problems); dual-publish exit 0.
https://claude.ai/code/session_01CUWsrUNZP9jpxvAwq67UiT
Addresses PR #900 review nit — the versao: frontmatter key stayed
Portuguese in 4 template/example/reference files. No script keys on it
(parse_frontmatter is a generic grabber), so it's a safe cosmetic rename.
Mirror re-synced; example-bundle lint still PASS; dual-publish exit 0.
https://claude.ai/code/session_01CUWsrUNZP9jpxvAwq67UiT
Translates the entire arquiteto-de-empresa (Company Architect) skill from
Brazilian Portuguese to professional English across all 18 files in both
dual-published locations:
- SKILL.md, README, cs-arquiteto agent + command, plugin.json description
- 3 references (okf_conformance, type_vocabulary, phase_playbook)
- 7 assets (templates + exemplo-bundle example)
- 3 stdlib scripts (scaffold_bundle, okf_linter, index_generator):
docstrings, argparse help, printed strings, finding-rule slugs
Consistency preserved end-to-end:
- Controlled OKF vocabulary translated (Fundação->Foundation, etc.)
and kept identical across type_vocabulary.md, okf_linter VALID_TYPES,
scaffold_bundle FOLDERS/DASHBOARD labels, and the example-bundle
frontmatter, so the linter still passes.
- Status enum rascunho/em-revisao/aprovado -> draft/in-review/approved.
- [SUPOSIÇÃO] -> [ASSUMPTION]; language: pt-BR -> en.
Identifiers intentionally preserved (published marketplace slug + tool
contract): skill slug arquiteto-de-empresa, cs-arquiteto agent/command,
phase-dir slugs (00-fundacao..11-governanca), concept filename slugs.
A slug rename to English is a separate reversible decision.
Also fixes a pre-existing broken link in the example bundle (identidade.md
pointed at a nonexistent problema-solucao.md — the original pt-BR bundle
also failed the linter there) and trues up two stale README badges
(agents 97->99, commands 103->109) that were drifting on dev.
Validation: okf_linter --sample PASS, example-bundle lint PASS (0 errors),
py_compile clean, all 3 scripts --help ok, dual-publish mirror identical,
plugin/paths/counters/G9 gates all exit 0.
https://claude.ai/code/session_01CUWsrUNZP9jpxvAwq67UiT
- jira_snapshot_bridge.py: a malformed --as-of now refuses with exit 2 instead of
raising TypeError (same guard as discovery_cadence_tracker).
- user_story_generator.py / persona_generator.py: add a real --sample flag so the
harness manifests can smoke-test them (supports_sample now true; product-team
manifest regenerated).
- ost_linter.py: document the --sample-always-exits-0 exception in the exit-code
contract.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019Uzm8dKoeXPayJVMojpSbw
- Relabel this release v2.10.4 -> v2.11.1 (dev already carries v2.11.0 from the
engineering agent-harness PR); add a proper Current Version changelog entry and
sync marketplace metadata.version + both plugin manifests + SKILL.md frontmatter.
- jira_snapshot_bridge.py: Monte Carlo forecast now samples zero-filled weekly
throughput over the full observed span (Vacanti: dead weeks are observations),
and the 4-week refusal gate counts observed calendar weeks; regenerated the
pinned fixture. normalize() skips non-dict records instead of crashing.
- discovery_cadence_tracker.py: --as-of earlier than the interview history now
refuses cleanly with exit 5 instead of raising.
- harness_manifest_builder.py: descriptions truncate on word boundaries with an
ellipsis instead of mid-word; regenerated all 18 domain manifests.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019Uzm8dKoeXPayJVMojpSbw
Per PR #891 review: check_readme_badges silently skipped a badge whose regex
found no match, so a renamed or removed shield would quietly drop out of the
gate — the same silent-drift class this gate exists to catch. Now a missing
badge appends a mismatch (mirrors run_check's "no recognizable counter claims
found" precedent), so it fails loudly. Verified: renaming a badge trips exit 1;
the current README still passes.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L4JerbGv6vqitUMhqHPA9g
Per PR #891 review: `mismatches: list = []` was an inconsistent drive-by
annotation vs the un-annotated locals elsewhere in the file. Revert to keep
the diff minimal and the style consistent. No behavior change.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L4JerbGv6vqitUMhqHPA9g
Follow-up to the merged agent-harness PR (#890), applying the automated review nits:
- loop_controller.py: drop unused `import shlex`; simplify cmd_record's exit-code
expression to the clearer form already used in cmd_verify (behavior-equivalent)
- SKILL.md + references/verification_discipline.md: document that plan/state files are
a trust boundary (verify shell-executes their cmd strings) — run the harness only on
files produced by goal_compiler, never untrusted input
- README.md: bump Agents 96->97 and Commands 102->103 badges (drift the previous PR
missed because derive_counters didn't validate these badges)
- scripts/derive_counters.py: add check_readme_badges — validates the Skills/Agents/
Commands shields against derived counts, closing the CI blind spot that let the badge
drift ship. Verified it fails (exit 1) on drift and passes when correct.
All gates green: plugin.json (83 OK), smoke --help/--sample (600 pass), JSON output
(0 fail), path linter (0 findings), derive_counters --check (pass).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L4JerbGv6vqitUMhqHPA9g
Follow-up to the llms.txt footer links (PR #879). The automated review noted
the URL join assumed site_url ends in "/". Compute the base once with
trim('/') so the links stay correct whether or not site_url has a trailing
slash; trim only strips '/' from the ends, leaving "https://" intact.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Sy9WFFurEjL8gjCp9fs7bp
Add machine-readable repository descriptions following the llmstxt.org
convention so AI agents and crawlers can discover a structured overview
of the entire skills library.
- docs/llms.txt: concise curated index (site sections + 18 domains)
- docs/llms-full.txt: comprehensive self-contained repo description
(scale, design principles, skill package pattern, per-domain detail,
plugin/git rules, and how an agent should use the library)
- Override partials/copyright.html to surface both files as footer links
on every page; add matching styles to stylesheets/extra.css
Both files build to the site root (verified: /llms.txt, /llms-full.txt)
and the footer links resolve to absolute site URLs.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Sy9WFFurEjL8gjCp9fs7bp
Two housekeeping items surfaced during the contributor-PR hardening session.
1. CHANGELOG backfill — add [Unreleased] entries for five skills that merged
without their own changelog blocks (roast #865, named-persona-adversarial-review
#867, agent-decision-receipts #868/#869, zero-hallucination-coder #870,
deep-research #872). Earlier merges updated headline counters but not this log.
2. Per-domain counter validation — scripts/derive_counters.py --check now also
validates the README "Skills Overview" per-domain table: each domain row's
count must equal the SKILL.md count in its linked folder, and every on-disk
domain must have a row. Previously --check only validated headline aggregates,
so per-domain rows drifted silently. Verified: passes on the fixed state, fails
on a wrong count, fails on a missing row, and parses exactly the 18 real domain
rows (bold-first-cell install/skills-vs-agents tables are not false-flagged).
Trued up the README table to make the new check pass: fixed six stale row
counts (engineering-team 51->52, engineering 78->80, marketing 47->48,
productivity 6->7, ra-qm-team 18->19, c-level 66->68), added the missing
markdown-html row (5), and named the newly-merged skills in their domain
descriptions. Per-domain rows now sum to the 354 headline.
Headline aggregates unchanged (354 skills / 722 refs / 82 plugins / 18 domains).
#872 merged before these automated-review fixes were pushed, so applying them
as a fresh follow-up:
- README: research (academic) domain row 8 -> 9 and add deep-research to the
8-specialist list + the intro-paragraph research stack (the global counters
were bumped in #872 but the per-domain row wasn't — derive_counters --check
only validates headline aggregates, not per-domain rows).
- research router SKILL.md: add a deep-research escalation note after the
Specialist Registry so router users learn about the high-stakes path
(router = fast, deep-research = heavyweight).
- cs-deep-research agent: fix the cs-research Related-Agents link (was a bare
directory, now points at the actual agent file).
Methodology-only scope retained per maintainer decision (no scripts added).
Adds a disciplined multi-source meta-research skill — the heavyweight,
rigor-first alternative to the fast research router. 9-phase pipeline
(reframe into falsifiable hypotheses -> plan -> capability discovery ->
parallel sub-agent fan-out -> score & triangulate -> synthesize + adversarial
pass -> verify -> refresh targets), triangulation against >=3 independent
differently-typed sources, per-source files with verbatim quotes, and a
hard no-fabricated-citations rule.
Concept + SKILL.md contributed by @Socialpranker in PR #851. Hardened for the
research/ per-skill-plugin convention (the PR shipped only the SKILL.md):
- Packaged as a full plugin to match every sibling (pulse/litreview/dossier/...):
added .claude-plugin/plugin.json, marketplace.json entry, cs-deep-research
agent, /cs:deep-research command, and README.
- Dropped a dangling claude-api cross-reference (not a repo skill); the other
cross-refs (research router, competitive-teardown, litreview/dossier/patent)
are all real.
- Preserved the contributed SKILL.md + references/full-catalog.md (the upstream
source-catalog pointer) verbatim otherwise; attribution + upstream link in
plugin.json and README.
Counters trued up via scripts/derive_counters.py --check (passes):
354 skills, 722 references, 96 agents, 102 commands, 82 plugins.
Co-authored-by: Socialpranker <273312799+Socialpranker@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kmw1eZQoSMDr2diHbCcUkF
- schema_generator: _build_aggregate_rating no longer fabricates a 4.8 rating.
It now requires BOTH count AND average and returns None otherwise — a made-up
ratingValue in live JSON-LD contradicts the skill's own anti-fabrication
guidance (Google cross-checks aggregateRating against GBP). Verified: count-only
config emits no AggregateRating; count+average emits the real value.
- nap_checker: normalize_address now expands ALL US state abbreviations via a
US_STATE_ABBREVIATIONS map, not just CA. "TX" vs "Texas" (and every other state)
now compares equal — the skill serves businesses nationwide, so CA-only
normalization silently under-reported mismatches for everyone else.
- SKILL.md: softened the "< 50 reviews" proactive trigger from "most SF Bay Area
markets" (inherited from the original author's metro) to "most competitive metro
markets".
All 3 scripts pass --help + sample run.
- Wire local-seo-manager into marketing-ops routing matrix (SEO Pod). Routing is
matrix-driven, so without this the router never sends "GBP audit" / "NAP
consistency" / "Map Pack" queries to the new skill. (medium — the flagged item)
- nap_checker: only report a "(missing)" phone mismatch when the canonical record
actually has a phone (elif canon_phone and not listing.get('phone')). Previously
a listing with no phone vs a canonical with no phone produced a misleading line.
Verified: no phantom mismatch when neither side has a phone.
- SKILL.md References section now lists review-response-templates.md (the 3rd
shipped reference, previously cited inline in Mode 1 but omitted from the list).
- marketplace.json: true up the stale marketing-skills plugin description
(44 skills / 59 tools / 86 refs -> 47 / 62 / 89) since this PR already edits
that file.
Config-key KeyError guard remains a deliberately-deferred nit (stdlib demo tools,
sample path fully covered). All 3 scripts still pass --help + sample run.
Address the two actionable items from the second automated review on #871:
- Add a CHANGELOG.md [Unreleased] entry for local-seo-manager (the repo maintains
per-PR changelog entries; the earlier commits missed it).
- Bump the README per-domain Marketing row 46 -> 47 to reflect the added skill
(this row isn't CI-validated, but it's the domain this PR touches).
The 3rd observation (config KeyError guard) remains a deliberately-deferred nit.
- service_area_generator: wire the previously-dropped inputs into the brief.
`business_type`, the `services` list, and `state` were accepted (and threaded
from config) but never rendered — the user's service list and state silently
vanished. Now surfaced in the opening-paragraph guidance and meta/CTA lines.
- schema_generator: stop emitting an empty geo block. The top-level empty-value
filter didn't reach into the nested dict, so `{"latitude":"","longitude":""}`
survived and produced invalid JSON-LD. geo is now only added when both
coordinates are supplied (verified: omitted for sample, present when provided).
- Removed the unused `import sys` from all three scripts.
(Config-key KeyError guard — the 4th, nit-level finding — left as-is; the scripts
are stdlib demo tools and the sample path supplies all keys.)
All three scripts still pass --help + sample run.
Adds a marketing skill for local service-area businesses (appliance repair,
HVAC, plumbing, cleaning, electrical): 4 modes — GBP audit, service-area page
generation, NAP consistency, and LocalBusiness schema — with 3 stdlib scripts
(nap_checker, service_area_generator, schema_generator), 3 references (80-point
checklist, schema types, review-response templates). Fills a genuine gap: the
library had national/technical SEO (seo-audit, programmatic-seo) but no
local/Map-Pack SEO skill.
Contributed by @Steffonet in PR #797. Light hardening before merge:
- Fixed two dangling skill cross-references: ai-seo -> aeo (the repo's actual
Answer Engine Optimization skill; 2 places), and removed the reference to a
non-existent gbp-content-creator companion skill.
- Reworded the description's first sentence ("Manage local SEO...") so it passes
skill_description_validator.
Placement is correct as-is (marketing-skills plugin globs ./skills), so no
plugin.json or marketplace entry is needed. All 3 scripts pass --help + sample.
Counters trued up via scripts/derive_counters.py --check (passes):
353 skills, 593 tools, 721 references.
Co-authored-by: Steffonet <214469854+Steffonet@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kmw1eZQoSMDr2diHbCcUkF
* bug: several bug fixes and improvements (see comments)
- [bug] fixed the shebang for portability (wouldn't run on my system)
- [feat] improved the inline python scripts; the `--all` and `--category` flags now read/dedupe names from the `skills-index.json` file so that stale entries (e.g. `.codex/skills/playwright-pro`) do not get treated as installable skills
- [bug] fixed the counter from installed++/failed++ to ++installed/++failed, which caused the script to exit upon installing the first skill
- [style] formatting fix
* fix(codex-install): improve error handling and validation for skill and category installation
---------
Co-authored-by: Alireza Rezvani <5697919+alirezarezvani@users.noreply.github.com>
Adds an opt-in coding-discipline skill: a Discuss -> Map -> Decompose ->
Execute -> Verify loop that grounds code in verified structure (KNOWN/INFERRED/
UNKNOWN codebase mapping, atomic-story decomposition, a lazy-senior-dev YAGNI
ladder) with no invented APIs, assumed imports, or placeholder code. Synthesizes
four MIT/open-source projects (Ralph, GSD Core, Graphify, Ponytail).
Concept + SKILL.md contributed by @mehanshbarthwal-lab in PR #854. Hardened for
this repo:
- Scoped activation to OPT-IN (high-stakes / complex / multi-file / explicitly
requested rigor) instead of auto-firing on every coding verb, so it doesn't
hijack all coding requests in users' setups.
- Fixed plugin.json: skills ["./skills/zero-hallucination-coder"] (was bare
"./", which fails check_plugin_json), version 2.10.3 (was stale 2.1.2),
author aligned to repo owner + attribution block crediting the contributor
and all four source repos.
- Restructured to the engineering standalone-plugin layout
(engineering/<plugin>/skills/<name>/SKILL.md) matching caveman/grill-me/handoff.
- Trimmed the ~130-line embedded multi-method install guide + external-tool
install promo (marketplace handles install); kept the credits table.
- Fixed the description to pass skill_description_validator (third person +
explicit "Use when" trigger).
- Registered in marketplace.json.
Counters trued up via scripts/derive_counters.py --check (passes):
352 skills, 81 plugins.
Co-authored-by: mehanshbarthwal-lab <227379980+mehanshbarthwal-lab@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kmw1eZQoSMDr2diHbCcUkF
The "Decision 2" table listed inputs_hash under "required keys this skill
enforces," but build_action_manifest.py only enforces four required keys
(agent_id, operation, target, policy). inputs_hash and decision_label are
auto-added, not required input. Clarified: 4 required + 2 auto-added, so the
doc matches the script.
Follow-up to #868 (agent-decision-receipts), which merged before this fix landed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kmw1eZQoSMDr2diHbCcUkF
Adds a ra-qm-team skill that mints tamper-evident, post-quantum-signed receipts
for consequential agent actions (EU AI Act Article 12 record-keeping, OWASP
Agentic excessive-agency). A stdlib-only script builds/validates the action
manifest; signing is delegated to the open-source openagentontology package
(Apache-2.0, opt-in install — adds no repo dependency).
Concept + script contributed by @CWNApps in PR #863. Hardened for this repo:
- Moved from the orphaned ra-qm-team/agent-decision-receipts/ (a sibling of
skills/, not picked up by the ra-qm-skills plugin's ./skills glob) into
ra-qm-team/skills/agent-decision-receipts/ so it is actually distributed.
- Stripped self-promotion of the contributor's other products (SalesGPT /
OpenOutreach / Trust Gate MCP / "CWN distribution") from the references doc;
kept the technical PQ-strict-mode pattern, genericized the env var name.
- Removed the 25-term SEO keyword-stuffing block (not a repo convention).
- Fixed the description to third person (passes skill_description_validator).
- Repointed cross-refs to the real sibling skills (eu-ai-act-specialist,
iso42001-specialist).
The stdlib script is preserved as-authored (clean; builds + validates the
manifest, rejects missing fields, enforces ASCII reproducibility).
Counters trued up via scripts/derive_counters.py --check (passes):
351 skills, 590 tools, 718 references.
Co-authored-by: CWNApps <129076989+CWNApps@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kmw1eZQoSMDr2diHbCcUkF
Adds a philosophy-grounded code-review skill: review through the lens of real
engineers' *documented, sourced* principles (Torvalds, Thompson, Carmack, Beck,
Brooks + Jobs, Cagan, Traynor), complementing engineering-team/adversarial-reviewer
(abstract roles) and code-reviewer (general quality).
Concept contributed by @YuhaoLin2005 in PR #866. Hardened for this repo's
conventions before merge:
- Consolidated to ONE location (engineering-team/skills/, auto-included via the
engineering-skills plugin's ./skills glob). Dropped the orphaned top-level
skills/ copy the original PR also added — no such plugin root exists in the tree.
- Added anti-fabrication discipline: cite the sourced principle (not an invented
verbatim quote), confidence levels on every attribution, drop a persona rather
than fabricate — mirrors productivity/andreessen's citation rule. LLMs hallucinate
quotes; attributing invented words to real living engineers is the core risk.
- Added references/persona_principles.md grounding every persona in a real,
citeable source with a confidence level (7+ sources incl. de Bono, Kahneman, Feynman).
- Removed the dangling /adversarial-review slash command reference and the
non-English trigger phrase; description passes skill_description_validator.
Counters trued up via scripts/derive_counters.py --check (passes):
350 skills, 717 references, 80 plugins.
Claude-Session: https://claude.ai/code/session_01Kmw1eZQoSMDr2diHbCcUkF
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: YuhaoLin2005 <278400118+YuhaoLin2005@users.noreply.github.com>
New productivity/roast/ plugin. Convenes five independent reviewers (The Critic,
The Champion, The Analyst, The Investigator, The Customer) in parallel on a business
idea, then a Judge synthesizes one GO / RESHAPE / KILL verdict with the cheapest
48-hour test to de-risk it.
Renamed the personas/steps from the source draft to be self-explanatory for users:
Critic/Champion/Analyst/Investigator/Customer (was Contrarian/Expansionist/Logician/
Researcher/Buyer) and Frame the idea / Run the 5-angle panel / Call the verdict.
Path-B contract:
- 3 stdlib tools (no LLM calls): brief_builder, verdict_synthesizer (weighted,
non-compensatory veto gates, tension detection — never a plain average),
cheapest_test_designer (risk → falsifiable 48-hour test)
- 3 references (5-7 cited sources each), 2 assets, cs-roast-judge agent, /cs:roast command
- source.distinct_from disambiguates vs andreessen (single lens), boardroom
(enterprise pipeline), grill-me (no verdict)
Counters trued up via scripts/derive_counters.py --check (passes):
346 skills, 582 tools, 708 refs, 94 agents, 100 commands, 79 plugins.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Kmw1eZQoSMDr2diHbCcUkF
Address internal-consistency gaps from the count bump: the marketplace.json
root description still read 347/17 (only metadata.description was updated),
and the README skills table had no loop-library row despite the "18 domains"
heading. Both now reflect 348 skills / 18 domains with loop-library listed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KEJH6wwyaEs1d6AAca2HLR
Gate G1 (check_paths.py --all) was failing on dev's arquiteto-de-empresa
skill, surfaced into this branch by the dev merge. The 3 references are
genuine false positives: two are inside a markdown code-example showing
OKF bundle link syntax in the user's generated output, and one is a
command doc pointing at its sibling skill's references/ dir. Added to
check_paths_allowlist.txt per the workflow's documented remedy.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KEJH6wwyaEs1d6AAca2HLR
Adding the loop-library/ folder bumped the derived counters. Sync the
headline claims in README.md, CLAUDE.md, and marketplace.json so
scripts/derive_counters.py --check passes: skills 345->346, domains
17->18, references 705->707.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KEJH6wwyaEs1d6AAca2HLR
Install the loop-library skill from Forward-Future/loop-library into the
repo, preserving the upstream skill folder exactly. SKILL.md, agents/openai.yaml,
references/discover.md, and references/audit.md are byte-for-byte copies of
upstream (skills/loop-library/). Adds the MIT LICENSE and a provenance README.
The published loops themselves are served live from the database-backed catalog
(catalog.md / catalog.json) and are intentionally not committed to Git upstream;
the skill fetches them at runtime as the single source of truth.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KEJH6wwyaEs1d6AAca2HLR
mcp-server-builder, performance-profiler, ci-cd-pipeline-builder, and four
ra-qm-team skill sources changed after the last docs regeneration; refresh
their generated pages so the published site matches the SKILL.md sources.
https://claude.ai/code/session_015bYZ97nV4oRb3LbxCRFVcP
Keeps the three most safety-critical nudges (secrets in env, host
allowlists, additive-only contract changes) scannable in SKILL.md's
'Harden for Production' step instead of two hops away; merges the
Tier/Category/Domain boilerplate onto one line to stay under the
100-line ceiling.
https://claude.ai/code/session_01CUWsrUNZP9jpxvAwq67UiT
First tranche of the Matt Pocock 100-line SKILL.md refactor (issue #655).
Pattern: keep the operational core (overview, capabilities, workflows,
script interfaces) in SKILL.md; move the advisory layer verbatim into a
new reference doc, linked with a one-line summary.
- ci-cd-pipeline-builder: 147 → 89 lines; pitfalls/best-practices/
heuristics/strategy/platform-notes/validation/scaling moved to
references/pipeline-design-notes.md
- mcp-server-builder: 164 → 97 lines; auth-safety/versioning/pitfalls/
best-practices/architecture/quality-gates/testing/deployment/security
moved to references/production-hardening-guide.md
Both skills now pass skill_structure_validator (verdict PASS). No content
deleted — everything moved verbatim. Path linter, dual-publish guard, and
counter checks green.
https://claude.ai/code/session_01CUWsrUNZP9jpxvAwq67UiT
Resolves the import-placement asymmetry flagged across review rounds by
moving the remaining inside-guard import (argparse) up to join sys at the
file-level import block.
https://claude.ai/code/session_01CUWsrUNZP9jpxvAwq67UiT
Adds FileNotFoundError / JSONDecodeError / missing-key handling to
team_scaling_calculator's input_file path, matching the other five
sample-pattern tools (pre-existing gap, surfaced by review).
https://claude.ai/code/session_01CUWsrUNZP9jpxvAwq67UiT
Hoists the embedded defaults to SAMPLE_CURRENT_STATE / SAMPLE_GROWTH_TARGETS
module constants so the loading flow can use the same top-of-branch
if/elif/else shape as the other five tools without duplicating the fixture.
The silent default-to-sample when no input is given is pre-existing,
documented behavior (kept; noted in the constant's comment).
https://claude.ai/code/session_01CUWsrUNZP9jpxvAwq67UiT
- incident_triage.py: --sample help text now documents the intentional
exit-2 SEV1 signal so &&-chained callers aren't surprised
- team_scaling_calculator.py: consolidate the split warn/load blocks into
the single if/else pattern the other five tools use
https://claude.ai/code/session_01CUWsrUNZP9jpxvAwq67UiT
- health_score_calculator + pipeline_analyzer: warn on stderr when --sample
overrides a provided input (now consistent across all six tools)
- pmf_scorer: --sample checked before --input (matches the batch), with the
same override warning
- pipeline_analyzer: comment the intentionally stale D-3 fixture deal
- contrast_checker: user-facing --sample help text
https://claude.ai/code/session_01CUWsrUNZP9jpxvAwq67UiT
Review of PR #842 found qms-audit-expert's crosswalk still presenting QSR
sections as current; an exhaustive domain sweep found one more
(regulatory-affairs-head's fda-submission-guide QSR bullet list). Both now
carry the QMSR banner with ISO 13485 clauses as current authority and 820.x
as labeled historical index; the audit playbook's transition paragraph
updated to past tense (rule took effect 2026-02-02). Also standardized the
one divergent column header per review.
Domain-wide grep now shows zero unlabeled 820.x-as-current claims in
ra-qm-team/ and compliance-os/ (residuals are TOC anchors inside the
banner-framed historical reference).
https://claude.ai/code/session_019AJddAL1NADWMXsy1qNPQF
- team_scaling_calculator.py: move sys import to the file-level import block
(was inline in the conditional); behavior unchanged
- incident_triage.py: warn on stderr when --sample overrides a provided
--input, matching team_scaling_calculator's convention
https://claude.ai/code/session_01CUWsrUNZP9jpxvAwq67UiT
- pmf_scorer.py: the no-input fallback notice now goes to stderr, so a bare
`pmf_scorer.py --json` emits parseable JSON on stdout
- team_scaling_calculator.py: warn on stderr when --sample overrides a
provided input_file instead of silently discarding it
https://claude.ai/code/session_01CUWsrUNZP9jpxvAwq67UiT
capa-officer, quality-documentation-manager, quality-manager-qmr,
quality-manager-qms-iso13485, and the ra-qm-skills router still presented
legacy QSR 820.x subsections as current FDA law — the same P0-class defect
fixed in fda-consultant-specialist (PR #835), deferred by that wave's agent.
Applied the identical validated pattern: QMSR status banner (final rule
89 FR 7496, ISO 13485:2016 incorporated by reference, effective 2026-02-02),
820.x relabeled historical with ISO 13485 clause as current authority
(CAPA -> 8.5.2/8.5.3; doc/record control -> 4.2.3/4.2.4/4.2.5 + retained
820.35; QMR/management review -> 5.5.2/5.6), and decision-discipline blocks
added where missing (closure/compliance calls route to named owners).
Substantive content unchanged; no scripts contained 820.x claims.
Verified: zero present-tense 820.x-as-current-law claims remain (all under
historical labels/banners); check_paths 0 findings; counters unchanged.
https://claude.ai/code/session_019AJddAL1NADWMXsy1qNPQF
Brings G9 JSON-output coverage from 19 to 25 tools (25/25 verified):
- business-growth: health_score_calculator (embedded 2-customer fixture),
pipeline_analyzer (embedded 4-deal pipeline fixture)
- c-level-advisor: pmf_scorer (--sample flag for its existing sample_data(),
suppressing the stdout notice that corrupted JSON piping),
team_scaling_calculator (--sample flag for its embedded defaults)
- engineering-team: incident_triage (embedded synthetic ransomware event),
contrast_checker (--sample as alias of the existing --demo)
Required-arg behavior unchanged when --sample is absent (still exits 2 with
a usage error). All gates green: G9 25/25, G8, dual-publish, path linter.
Together with the 5 #654-named tools, 4 JSON-honor fixes, and the pre-existing
sample-pattern tools, more than 20 tools now support the embedded-sample
convention — meeting #654's acceptance bar.
https://claude.ai/code/session_01CUWsrUNZP9jpxvAwq67UiT
- Rewrite docs/stylesheets/extra.css with a warm clay/coral design system:
aurora hero with eyebrow badge and stats strip, gradient card hairlines,
pill tool badges, numbered steps component, reduced-motion support
- Rewrite homepage copy: plain-language 'What is an Agent Skill?' section,
3-step how-it-works, all 17 domain cards, guides section, accurate stats
(337 skills / 17 domains / 66 plugins)
- Add missing markdown-html domain to generate-docs.py (17th domain) and
regenerate catalog: +12 new pages (md-document/md-review/md-slides skills,
cs-markdown-html-orchestrator + cs-scraping-architect agents, 7 commands)
- Fix skill-internal link rewriting in the generator (./SIBLING.md and
ALL-CAPS companion files now resolve to GitHub URLs) — mkdocs --strict
now passes with zero warnings
- Refresh stale counters site-wide (177/192/204/311/338 → 337) in skills
index, plugins index, getting-started, integrations, custom-gpts, guides
- Rebuild plugins page from live marketplace.json: 13 domain bundles + 53
standalone plugins, accurate bundle table and full 66-plugin listing
- Add Guides section to nav (5 existing SEO guide pages, URLs unchanged),
point homepage tool badges at tool-specific guides and real anchors
- Tighten site_description and JSON-LD keywords for 'agent skills' /
'agent plugins' queries; update announce bar to the markdown-html launch
- No existing slugs or URLs changed — all edits are additive or in-place
https://claude.ai/code/session_015bYZ97nV4oRb3LbxCRFVcP
- calculate_cac.py: hoist 'import argparse' to module top per repo convention
- smoke_scripts.py: comment the exit-1-over-exit-3 precedence
- check_paths_allowlist.txt: reword the etc/passwd note ('outside repo root if
resolved literally', not 'deep checkouts')
- cs-scraping-architect.md: clarify both warning and error share exit 1 — parse
the JSON status field for the distinction
https://claude.ai/code/session_019AJddAL1NADWMXsy1qNPQF
- smoke_scripts.py: --help epilog now documents the exit-code table
(0 ok / 1 smoke failure / 3 stale exceptions)
- calculate_cac.py: real argparse --help with an epilog stating the
edit-example_data limitation and the planned --file/stdin enhancement
- cs-scraping-architect.md: add 'model: sonnet' to match sibling agents
Item 4 (senior-security references) was a non-issue — all three referenced
files exist and the now-blocking path gate is green.
https://claude.ai/code/session_019AJddAL1NADWMXsy1qNPQF
The blocking G1 path gate flagged '../../../etc/passwd' — a path-traversal
ATTACK EXAMPLE in a pen-testing skill's attack-vector table, not a real file
reference. It passed locally only because a deep checkout makes ../../../ climb
to the host's real /etc/passwd; on the CI runner it doesn't resolve. Allowlisted
with a reason, per the gate's documented edge-case process.
https://claude.ai/code/session_019AJddAL1NADWMXsy1qNPQF
Implements issue #654 Option A (embedded-sample convention) plus the
verification harness the issue asked for:
- scripts/smoke_json_output.py — new advisory gate (G9) that discovers
every tool whose --help advertises JSON output, runs <tool> --sample
<json-flag>, and asserts the stdout parses as JSON. Tools advertising
JSON without --sample are reported as 'uncovered' (a backlog, not a
failure) so the gate can be adopted incrementally; --strict flips that
to a hard failure once coverage is high. Wired into ci-quality-gate.yml
alongside G8.
- Added --sample embedded fixtures to the 5 tools named in #654:
error_budget_calculator, slo_review, blast_radius_calculator,
audit_log_analyzer, api_linter. Their required args are now optional
when --sample is passed; missing-arg behavior is unchanged otherwise.
- Fixed 4 tools the new gate surfaced (prompt_rater, coach_tip_classifier,
cheat_code_filter, redaction_linter): their --sample path printed human
text and ignored --json; it now honors the JSON flag.
- Synced the 3 dual-published standalone copies (slo-architect x2,
chaos-engineering) so the drift guard stays green.
Gate now reports 16 tools covered, 16 verified, 0 failures.
https://claude.ai/code/session_01CUWsrUNZP9jpxvAwq67UiT
- senior-prompt-engineer: rebuilt on the new-gen pattern; 2023-era cheatsheet
dropped; scripts made model-agnostic and rot-proof (user-supplied pricing,
no hardcoded model/cost tables); 5 workflows with executable exit-code
gates; zero stale model names remain
- senior-security: 445 -> 64 lines; owns only its unique STRIDE/DREAD value
with exact CLIs; 10-row lane table routes everything the v2.2 security
suite covers (all paths verified)
- engineering-team docs: all dead computer:/// links repointed to live
skills/ folders; all 14 stale .zip archives deleted (0 references remain;
folders are the canonical distribution)
- universal-scraping-architect: placeholder cs-scraping-architect agent and
cs-scrape command rewritten with verified CLIs, refusal gates, and the
empirically-confirmed validate_extraction.py exit-code contract
Gates at HEAD: check_paths 0 findings; check_dual_publish 0 drifted;
smoke 582/582; counters match; 78 manifests OK; compileall clean.
https://claude.ai/code/session_019AJddAL1NADWMXsy1qNPQF
- cs-content-creator retargeted off the deprecated content-creator stub to
marketing-skill/skills/content-production; Use-when description; all 4
script CLIs verified; workflows end at the skill's documented thresholds
(score >= 70, quality gates as publish blocker)
- cs-demand-gen-specialist now orchestrates all 3 verified targets
(marketing-demand-acquisition, paid-ads, email-sequence); hard rules
(margin-adjusted ROAS, no scaling without verified tracking); honest CLI
for calculate_cac.py (script takes no args — old agent documented a
phantom invocation)
- marketing-demand-acquisition SKILL.md: same phantom calculate_cac
invocation corrected (verified no-args run exits 0)
- marketing_skills_roadmap.md deleted: stale planning material, now
unreferenced after the agent rewrites (was kept in wave-3 only because
these two agents linked it)
Verified: check_paths 0 findings on both agents; 8 documented CLIs pass
--help; descriptions <= 1024 with Use-when phrasing.
https://claude.ai/code/session_019AJddAL1NADWMXsy1qNPQF
- enforce-pr-target.yml: drop the no-op split/trim/join on the comment body
(array join already produces the final text)
- ci-quality-gate.yml: safety findings now emit a workflow warning instead
of being silently absorbed by '|| true'
- check_paths.py: fnmatch import hoisted to module level
- smoke_scripts.py: stale exception entries now fail the gate (exit 3) so
scripts/smoke_exceptions.txt stays tidy
https://claude.ai/code/session_019AJddAL1NADWMXsy1qNPQF
Every advisory run was green through PR #835, so the burn-in SLA
(2026-07-01 or 10 green runs) is satisfied early. Edge cases route to the
in-repo allowlists (check_paths_allowlist.txt, smoke_exceptions.txt)
instead of continue-on-error.
https://claude.ai/code/session_019AJddAL1NADWMXsy1qNPQF
- derive_counters.py: python_tools condition simplified to the equivalent
parts[0] != 'scripts' (reviewer M1); dead root_scripts variable removed;
--check still passes with identical values
- fda-consultant-specialist quick-start: 820.30 example annotated as a legacy
checklist key mapping to ISO 13485 §7.3 (reviewer m3 — note: switching the
example to '--section 7.3' as suggested would break; the checker's CLI keys
are intentionally the legacy 820.x checklist indices, documented in --help)
- CLAUDE.md: audit/ directory documented as an intentional public audit
record, distinct from the gitignored AUDIT_REPORT.md (reviewer m2)
Reviewer m1 (agents/CLAUDE.md 'engineering-team/' link) is a false positive:
agents/engineering-team/ exists as an agents subfolder containing exactly the
two linked files; check_paths.py confirms 0 unresolvable references.
https://claude.ai/code/session_019AJddAL1NADWMXsy1qNPQF
- enforce-pr-target.yml: the maintainer exemption let any maintainer PR
target main — replaced with the branch-based hard rule from CLAUDE.md:
only dev->main promotion PRs are allowed, regardless of author.
Maintainer PRs now fail the check with retarget instructions (not
auto-closed); non-maintainer PRs are commented and closed as before.
Re-checks on edited/ready_for_review so retargeting clears it.
- ci-quality-gate.yml: flip-to-blocking SLA documented for the 4 advisory
gates (2026-07-01 or 10 consecutive green runs on dev)
- CHANGELOG.md: Deprecated/Removed Skills section with migration paths for
command-guide, ai-seo (-> aeo), release-manager (-> changelog-generator)
Addresses automated review feedback on PR #835 (items 1, 3, 6).
https://claude.ai/code/session_019AJddAL1NADWMXsy1qNPQF
The skill was the repo's only SKILL.md at plugin-root depth
(engineering/universal-scraping-architect/SKILL.md). That nonstandard shape:
- made it the only skill the Tessl quality gate's depth-2 detector fires on
(the gate then fails with an error-fallback 0/100 because the workflow has
no Tessl credentials)
- hid it from convert.sh (-mindepth 4)
- was flagged twice in the newgen audit
Now matches the standalone-plugin convention (skills/<name>/SKILL.md, agents/
+ commands/ + .claude-plugin at plugin root, skills: ['./skills']).
No content changes. Marketplace source path unchanged and still valid.
Gates: 78 manifests OK, 0 unresolvable paths, 0 dual-publish drift,
smoke 582/582, counters match.
https://claude.ai/code/session_019AJddAL1NADWMXsy1qNPQF
Adds an unmissable blockquote to the Git Workflow section: every PR (human or
AI) uses --base dev; main only receives dev->main promotion PRs from the
maintainer. Also trues the Current Scope counters to derived values
(344 skills / 579 tools / 698 references after wave-3 merges and removals).
https://claude.ai/code/session_019AJddAL1NADWMXsy1qNPQF
- #805: insert missing skills/ segment in all per-skill install commands
across 5 domain READMEs (engineering-team, project-management,
marketing-skill, c-level-advisor, ra-qm-team); every path now resolves
to a real directory
- #806: pr-review-expert SKILL.md curl examples now pass Jira/Linear
credentials via stdin curl config (-K -) instead of argv, with a netrc
note, so tokens never reach the process list or shell history
- #807: implement the documented interfaces for the three senior-devops
scripts (terraform_scaffolder: aws/gcp/azure module skeletons with
optional terraform fmt/validate; pipeline_generator: GitHub Actions /
CircleCI configs with build,test,security,deploy stages and runtime
detection; deployment_manager: blue-green/rolling manifests + kubectl
runbooks with deploy/rollback/analyze subcommands); align SKILL.md
- #807: ci-cd-pipeline-builder stack_detector now detects Terraform and
Docker stacks and emits their lint/test/build commands; downstream
pipeline_generator gains a generic job for non-node/python/go stacks
- #748: sync-vibe-skills.py defaults to a flat layout one level below
~/.vibe/skills (the only depth Vibe discovers), with collision-safe
naming and a --nested flag for the legacy namespaced layout
- #785: new scripts/sync-codebuff-skills.py syncs all skills into
Codebuff's ~/.agents/skills using the same flat-layout machinery
https://claude.ai/code/session_01CUWsrUNZP9jpxvAwq67UiT
Adds the collab-proof AI-collaboration retrospective skill from PR #788
(contributor: dong7812) without the regressions in that branch:
- Net-add marketplace entry (PR #788 overwrote the youtube-full plugin
slot; that entry is preserved here).
- marketplace.json kept as raw UTF-8 (PR #788 re-serialized with
ensure_ascii, escaping ~109 chars and polluting the diff).
- Header counters bumped from current dev (344 skills / 695 references /
65 plugins) instead of reverting to the stale v2.9.0 header.
Skill content (SKILL.md, 4 references, plugin.json, LICENSE) is taken
verbatim from #788. plugin.json passes check_plugin_json.
https://claude.ai/code/session_012iCc6XcNqiJzCGfKHz1DKi
Adds cs-webinar-marketer agent + /cs:webinar command wiring the webinar-marketing skill (SKILL.md, stdlib funnel scorer, references, templates, evals) under marketing-skill/skills/. Includes a Windows cross-platform fix to scripts/generate-docs.py (normalizes os.sep to forward slashes — verified no-op on Linux) and regenerated docs. Verified: scorer runs (89/100 sample), frontmatter valid, clean merge into dev with no conflicts.
Ports ZeroPointRepo/youtube-skills (MIT) into marketing-skill/. Adds SKILL.md with MIT license + attribution, .claude-plugin/plugin.json, and marketplace.json entry. Documents BYOK/free-tier model and OSS fallbacks (youtube-transcript-api / yt-dlp / YouTube RSS). All four prior owner-review items addressed.
Adds the fourth skill to the markdown-html/ domain. The Tier-2 use case
from Shihipar's essay ("Code Review and PR Writeups"): a markdown PR
writeup with ```diff blocks and severity callouts becomes a single-file
2-column HTML review with top jump-nav, diff on the left, severity-tagged
annotation cards on the right, and a mandatory named reviewer footer.
Three stdlib tools pipeline together:
1. diff_parser.py — scans markdown for ```diff fenced blocks, parses each
as a unified diff (--- a/file, +++ b/file, @@ -10,7 +10,8 @@,
space/+/- body lines), assigns per-line numbers on both old (lo) and
new (ln) sides, preserves the per-hunk @@ header context. Supports
--infer-diff for unfenced blocks. Stdlib regex + state machine.
2. annotation_extractor.py — extracts severity callouts (GFM
> [!BLOCKER] style) and inline markers (nit:, blocker:, etc.).
Default convention BLOCKER/MAJOR/MINOR/NIT per Google's Code Review
Developer Guide; overridable via --severity-convention. Attaches each
annotation to the nearest preceding diff block by source-line index;
unanchored annotations go to a "general comments" section. Also
captures LGTM/approve markers separately as approvals.
3. review_html_renderer.py — emits single-file 2-col HTML. Top jump-nav
lists every annotation with severity badge + 80-char preview + jump
link + per-tier counts in heading. Each hunk-row is a CSS grid with
diff on the left (per-line numbers, +/- marks, addition/deletion bg
tints from --md-success/--md-warn via color-mix) and annotation cards
on the right. WCAG-1.4.1-compliant severity badges (color + icon +
aria-label + text — color is NEVER the sole signal); BLOCKER danger
color computed by hue-rotating the design-system accent 120° toward
red so it stays brand-coherent. Approval bar when LGTM markers
present and no findings. Collapses to stacked on viewports < 900px.
Mandatory --reviewer (refuses exit 3 otherwise — research-ops
named-owner discipline). Refuses exit 4 if no hunks present (wrong
skill → route to md-document). No Prism CDN (diff coloring conflicts
with syntax highlighting).
Plus 3 references each citing 5-7 sources:
- diff_rendering_canon.md — POSIX diff format + GitHub/GitLab UI +
difftastic + SWE at Google ch. 9
- severity_coding.md — WCAG 1.4.1 + Google review taxonomy + Don
Norman Design of Everyday Things + NN/g color UX
- pr_annotation_ux.md — convergent 2-col UX from GitHub / GitLab /
Reviewable / CodeStream + SWE at Google + NN/g F-shape
1 template asset documenting the canonical 2-col review HTML shape.
/cs:md-review slash command with 4 pre-flight gates
(under-100-lines, no-onboarding, missing-reviewer, no-hunks) + pipeline
+ output digest.
Repo-level updates:
- markdown-html/.claude-plugin/plugin.json: skills array adds
./skills/md-review; version 2.10.1 → 2.10.2; description updated.
- .claude-plugin/marketplace.json: markdown-html-skills entry version
and description; top-level counters 341 → 342 skills, 542 → 545 Python
tools, 685 → 688 references, 88 → 89 slash commands; metadata.version
2.10.1 → 2.10.2.
- Root CLAUDE.md: v2.10.2 release-notes block above v2.10.1.
Validation:
- check_plugin_json.py → OK
- sync-codex-skills.py --dry-run → 1 new symlink, documentation: 4 skills,
total 343
- skill_description_validator.py → PASS (all 5 checks: present, length,
third-person, trigger, action verb)
- skill_review_checklist_runner.py → 5/6 PASS (97 lines passes
under-100-lines check; minor WARN on "user" vs "developer" terminology
which are contextually distinct — converter operator vs review subject)
- All 3 tools pass --help and --sample
- Hard rules verified end-to-end:
no --reviewer → exit 3 with refusal message
no hunks → exit 4 with refusal message + md-document routing hint
custom severity convention "critical,important,suggestion,nit" works
- Full pipeline on sample PR (2 diff blocks, 2 callouts) produces 11.3 KB
single-file HTML with all 14 expected components (reviewer footer, PR
title, aria-labels per WCAG 1.4.1, --md-danger computed color, modern
color-mix tints, 2-col grid, 900px responsive collapse, both file
paths, annotation cards, jump-nav, addition+deletion classes, Findings
heading).
Coming in v2.10.3: md-slides — slide splitter + presenter-notes parser
+ arrow-key/space-bar nav + @media print for PDF export. Reuses
md-document's renderer scaffolding + design-system/scripts/config_loader.py.
https://claude.ai/code/session_01BK2KoQot1U7J5oSosrCQdc
Register the ECC marketplace (affaan-m/ECC) and enable the ecc@ecc plugin
in committed .claude/settings.json so the 63 agents / 249 skills / 79
commands / hooks load at runtime for anyone who opens this repo (one-time
trust prompt). Uses ECC's recommended plugin path; files are not vendored,
so there is no collision with the existing skills library.
https://claude.ai/code/session_01Vw7LCQLH5Wi7WHrrN47Hj6
Adds the universal-scraping-architect skill (Firecrawl + local Python extraction) salvaged from #706, with all merge-blockers fixed, CI workflow validator paths corrected (engineering/skills reorg), and code-review feedback addressed. Tessl quality review intentionally bypassed (CLI unauthenticated in CI — advisory only). Co-authored with @mehanshbarthwal-lab.
Phase 2 / Tier 1 of the post-#769 audit. Until now, the deterministic
analyzer (scripts/code_quality_checker.py) had language-specific smell
detectors only for C# and Java; C / C++ / Rust / Ruby / PHP / Dart all
fell through to generic checks. This PR brings C onto the same footing
as C# and Java -- the security delta is largest for memory-unsafe
languages, so C goes first per the audit ranking.
What's detected (CERT C + CWE catalogue patterns)
- Banned functions: gets, strcpy, strcat, sprintf, vsprintf
(CWE-242 / CWE-120 family -- no bounds check on any of them)
- Format-string vulnerability: printf(var) / syslog(var) where the
first arg is a bare identifier instead of a literal (CWE-134).
Suppressed when the first arg is a literal string.
- Unbounded scanf: %s without a width specifier (CWE-120).
Suppressed when a width is present (e.g. %31s).
- malloc/calloc/realloc result not NULL-checked within 5 lines
(CWE-690). Recognises if (p == NULL), if (NULL == p), if (!p),
if (p != NULL).
- free(p) without setting p = NULL on the next real line
(CWE-416 use-after-free guardrail). Low severity since some
style guides skip the zeroing convention.
- system() with a non-literal argument (CWE-78 command injection).
Suppressed when the argument is a string literal or NULL.
Implementation
- New function check_c_specific_smells() in code_quality_checker.py,
placed after check_java_specific_smells(). Reuses the existing
_strip_csharp_comments helper -- C, C#, and Java share // and /* */
comment syntax.
- Wired into analyze_file() via the existing dispatcher pattern:
`if language == "c": smells.extend(check_c_specific_smells(content))`.
Fixtures (regression-detection harness)
- assets/sample_c_smells.c -- 67 lines, every detector pattern
labelled inline with its CWE. Smells fixture produces 10 C-specific
detector hits (strcpy fires twice intentionally, once in each
function). Score: 4/100 (F).
- assets/sample_c_clean.c -- same surface area refactored per
rules/universal.md + languages/c.md. Zero C-specific hits.
Score: 100/100 (A).
- expected_outputs/sample_c_smells_quality.json and
expected_outputs/sample_c_clean_quality.json -- committed JSON
output mirrors the existing C# / Java regression-guard pattern.
Documentation
- engineering-team/skills/code-reviewer/README.md
- "Language-specific smell packs" line extended to enumerate the
6 C-pack patterns alongside the existing C# and Java packs.
- Bundled-fixtures table adds the 2 new C fixture rows.
- engineering-team/skills/code-reviewer/SKILL.md
- "Adding a New Language" step 5 reference: C# and Java -> C#,
Java, and C.
- "Regression Fixtures" paragraph reference: C# and Java -> C#,
Java, and C.
- docs/skills/engineering-team/code-reviewer.md mirrors the same
SKILL.md updates.
- CHANGELOG.md gets a new [Unreleased] section above the existing
code-reviewer entry, documenting the detector + fixtures.
Regression
- All 6 fixtures (C# / Java / C x smells / clean) pass byte-for-byte
against expected_outputs/*.json. No drift introduced in C# or Java
behaviour.
Not in this PR (Phase 2 audit, subsequent PRs)
- check_<name>_specific_smells for C++, Rust, Python, Kotlin, PHP,
Ruby, Dart, Go, Swift, TypeScript, JavaScript. C++ and Rust are
the next-highest-leverage targets (smart-pointer ownership,
unsafe block discipline). Same fixture + expected_outputs pattern
will apply to each.
https://claude.ai/code/session_01SnXMhpyuAwrws26Wy4fizz
Follow-up to PR #769 (6 new language files) and PR #772 (analyzer
wiring). Both PRs updated SKILL.md but left every derivative doc
surface stale. This PR closes the doc-sync gap.
Changed
- engineering-team/skills/code-reviewer/README.md
- Line 3 (one-liner): 9 -> 15 named languages, matching SKILL.md
- Line 90 (per-language guide list): 7 -> 13 file slugs
- docs/skills/engineering-team/code-reviewer.md (MkDocs page)
- Frontmatter description: 9 -> 15 languages
- File-tree block: 6 new languages/*.md rows
- Dispatch table: 6 new extension -> file rows
- --language valid-values comment: 8 -> 14 choices
Cross-platform mirrors
- .gemini/skills-index.json: regenerated via sync-gemini-skills.py
(diff is the single code-reviewer description; gemini script
discovered no other drift)
- .vibe/skills/claude-skills/skills-index.json: regenerated via
sync-vibe-skills.py with --target .vibe/skills (1 unrelated new
entry: workflow-builder; full regen was the path of least friction
for vibe)
- .hermes/skills/claude-skills/skills-index.json: hand-patched only
the code-reviewer entry. Full sync-hermes regeneration would have
bundled 33 new-skill entries (305 -> 338) accumulated from prior
PRs that never re-ran the script. That mirror-drift cleanup is a
separate concern -- left for its own PR.
- .codex/skills-index.json: was already current (the recurring
automated "chore: sync codex skills symlinks [automated]" commit
keeps it fresh between PRs).
CHANGELOG.md
- New [Unreleased] section above the existing Mistral Vibe block
documenting PR #769 (language coverage 7 -> 13), PR #772
(deterministic analyzer wiring), and this PR (doc sync).
Why hand-patched hermes (instead of script regen): the script
regenerates the entire index from current repo state, which surfaces
accumulated drift unrelated to code-reviewer (workflow-builder,
claude-coach, andreessen, handoff, business-operations, commercial,
compliance-os, research-ops -- 33 entries total). Bundling that with
a code-reviewer doc-sync PR would have muddied scope. Hand-patching
keeps this PR focused; a follow-up PR can sync-hermes properly.
https://claude.ai/code/session_01SnXMhpyuAwrws26Wy4fizz
PR #769 added language-rule files for C, C++, Rust, Ruby, PHP, and
Dart/Flutter, and updated SKILL.md's dispatch table + the --language
valid-values comment. But scripts/code_quality_checker.py was left
unchanged, so the deterministic analyzer silently skipped any file in
those 6 languages — the dispatch table promised coverage the script
didn't deliver.
Closes that gap by extending three structures in code_quality_checker.py:
- LANGUAGE_EXTENSIONS: 6 new entries matching SKILL.md exactly
(c declared before cpp so `.h` resolves to C per the dispatch table)
- find_functions patterns: language-aware function regexes
- find_classes patterns + nested method_patterns: type-defs and
method counting for class-like constructs (struct/enum/trait/union
for Rust; class/module for Ruby; class/interface/trait/enum for PHP;
class/mixin/enum/extension with Dart 3 modifier prefixes; struct for
C; class/struct for C++)
The function regexes for C and C++ require a trailing `{` so prototypes
and call sites aren't misclassified as definitions, and exclude
control-flow keywords (if/while/for/switch/return/sizeof) by negative
lookahead. This matches the discipline already used for the Java and C#
patterns (require modifier keywords).
Verification
- python3 scripts/code_quality_checker.py --help → all 14 languages
now appear as --language choices.
- Smoke-tested with a minimal sample per new language; each correctly
detects language, counts functions and classes, and produces a
quality score (no "Unsupported file type" errors).
- Regression: all 4 bundled fixtures (csharp/java × smells/clean)
still match their committed expected_outputs/*.json byte-for-byte.
Not in this PR (Phase 2 of the audit, separate PRs):
- Language-specific check_<name>_specific_smells detectors. Only C#
and Java have these today; the audit flagged C/C++/Rust as the
next-highest-leverage additions (memory safety, unsafe block
discipline, smart pointer ownership).
- Asset fixtures + expected_outputs JSON for the 6 new languages as
regression guards.
- Modernity / version-anchor sweep on the language markdown files.
https://claude.ai/code/session_01SnXMhpyuAwrws26Wy4fizz
Generate GitHub Pages for the workflow-builder skill, its cs-workflow-architect
agent, and the /cs:workflow-build command (via generate-docs.py), and wire all
three into mkdocs.yml nav (Engineering - POWERFUL, Agents, Commands sections).
Updated section index pages. Build verified clean (551 pages).
Aggregate skill counts unchanged — workflow-builder was already included in
dev's 338-skill / engineering-advanced-78 header.
https://claude.ai/code/session_01Q1kXbgMRodzhdTpgbCqVgx
Adds a concise workflow-builder reference to the top-level and metadata
descriptions alongside the research-ops headline. Builds on dev's accurate
338-skill / 16-domain v2.9.0 header (no version or count changes).
https://claude.ai/code/session_01Q1kXbgMRodzhdTpgbCqVgx
The top-level marketplace.json header still read v2.8.0 / 329 skills. Bump to
the current 2.9.0 release and update both descriptions to reflect the added
workflow-builder skill (engineering advanced 76 -> 77, total 329 -> 330).
Per-plugin version fields are unchanged (they track independent semver).
https://claude.ai/code/session_01Q1kXbgMRodzhdTpgbCqVgx
PR #756 normalized most marketplace versions to 2.9.0, but 20 newer
plugins (added after the normalization pass) remained on their own
versions on both marketplace.json and their plugin.json. Bump them all
to 2.9.0 so the registry advertises one unified release version, with
marketplace.json and every plugin.json fully in sync (62/62 at 2.9.0).
https://claude.ai/code/session_01JGwZR83iSg59EAtpTSCBjH
New engineering/workflow-builder plugin: an intake-first skill that designs
and writes deterministic multi-agent workflow .js files for Claude Code's
Workflow tool (CLAUDE_CODE_WORKFLOWS=1, /workflows).
- Opens every session with the intake question set; when the user is vague,
a stdlib recommendation engine infers and proposes a topology with rationale
instead of stalling or interrogating in a loop.
- 3 stdlib Python tools: workflow_intake.py (topology + model + budget +
rationale recommender), validate_workflow.py (.js linter enforcing
pure-literal-meta / no-non-determinism / no-Node-APIs / parallel-thunk /
guarded-loop rules), scaffold_workflow.py (5-topology starter generator).
- 3 references (7-8 sources each): API surface, orchestration patterns,
decision + intake guide. 3 templates + a runnable PR-triage example.
- cs-workflow-architect agent + /cs:workflow-build command.
- Registered in marketplace.json (61 -> 62 plugins).
Conceptually inspired by Ray Amjad's claude-code-workflow-creator; all content
written fresh from the publicly-documented Workflow tool API.
Gates: description PASS, structure PASS (78 lines), review-checklist WARN
(skill vs Workflow tool terminology — official feature name), complexity 85/100.
All scripts pass --help/--sample; all shipped .js validate PASS.
https://claude.ai/code/session_01Q1kXbgMRodzhdTpgbCqVgx
marketplace.json had outdated version numbers for 42 of 62 plugins,
causing Claude Code to potentially serve stale cached artifacts
during installation. For example, engineering-advanced-skills showed
2.4.3 in the marketplace but the actual plugin.json has 2.9.0 (with
the skills path fix from PR #715).
Synced all marketplace entry versions to match their corresponding
.claude-plugin/plugin.json versions.
Ran the /update-docs post-creation pipeline across the whole repo.
Docs site (MkDocs):
- generate-docs.py now covers 16 domains (added research-ops at order 15
and compliance-os at order 16 + its embedded-agent mapping). Regenerated
500 pages (328 skills + 89 agents + 83 commands); build passes.
- mkdocs.yml: site_description refreshed to 338/16/51+/87+ + v2.9.0; added
the Research Operations and Compliance OS skills nav sections, the
cs-research-ops-orchestrator + 8 compliance-os agents, and the 6
research-ops command entries.
- docs/index.md: title, description, hero, the five "What's Inside" cards
(338 skills, 51+ agents, 533 tools, 62 plugins, 87+ commands), corrected
six domain-card counts, and added a Research Operations domain card.
- docs/getting-started.md: description, Vibe count, FAQ, bundles table
(six corrected counts) + a research-ops bundle row.
Cross-platform sync (all four scripts gained a compliance-os entry):
- Codex: compliance-os 9 skills symlinked + index; unrelated run/status/
review symlink churn reverted to keep the diff focused.
- Gemini: 9 compliance-os SKILL.md mirrors + index.
- Vibe (repo target): 9 compliance-os symlinks + index.
- Hermes/Vibe domain lists updated for future syncs.
compliance-os was a tracked 9-skill domain previously absent from the docs
site and the codex/gemini/vibe indices; it is now fully wired in.
The MkDocs `site/` build output is gitignored and excluded.
https://claude.ai/code/session_01PUNmQVE4WYvcrzpq2anC3D
Connects each research-ops sub-skill to engineering/autoresearch-agent and adds
per-skill onboarding with a customization approach that the tools actually consume.
Each sub-skill (clinical-research, research-finance, market-research,
product-research) now ships three integration scripts:
- onboard.py — its own onboarding questionnaire; interactive or
--defaults / --set key=value / --reset / --scope; writes
~/.config/research-ops/<skill>.json (global) or
./.research-ops/<skill>.json (project).
- config_loader.py — loads that config (project > global > defaults;
RESEARCH_OPS_NO_CONFIG=1 bypass). Every scoring tool now
reads it so saved answers change behavior: default profile,
thresholds (alpha/power/dropout, F&A rate, runway, confidence,
MoE, insight source-threshold), and named owners printed on
clinical/finance outputs. CLI flags always override.
- ar_evaluator.py — an isolated, OPT-IN ground-truth evaluator bridging to
autoresearch. The loop edits the skill's input file and the
evaluator (never edited) scores it: clinical
feasibility_composite (higher), finance runway_months (higher),
market tam_divergence (lower), product validated_insights
(higher). No cross-skill coupling; invoked only on explicit
user request.
SKILL.md (each), the orchestrator, the agent, per-skill commands, and the domain
CLAUDE.md document the onboarding + opt-in autoresearch handoff. plugin.json /
marketplace describe 24 tools (12 analysis + 12 integration).
Builds the cross-platform plugins: codex symlinks + gemini SKILL.md mirrors +
vibe symlinks materialized for all 5 research-ops skills; indices regenerated.
Root CLAUDE.md scope/highlights updated.
https://claude.ai/code/session_01PUNmQVE4WYvcrzpq2anC3D
Builds on @mitnick2012's universal+per-language restructure (PR #742).
- Add Java as a first-class deterministic language in code_quality_checker.py
(LANGUAGE_EXTENSIONS + function/class/method patterns + check_java_specific_smells),
so the documented `--language java` command works instead of erroring on an
invalid choice. Add Java debug + @SuppressWarnings signals to pr_analyzer.py.
- Add Java regression fixtures (sample_java_smells/clean.java) with committed
expected_outputs JSON, mirroring the existing C# fixtures.
- Delete references/{code_review_checklist,coding_standards,common_antipatterns}.md,
now duplicated by rules/universal.md + languages/*.md; repoint README and the
C# clean fixture header at the new structure.
- Document the optional analyzer-wiring + fixture steps in the "Adding a New
Language" guide and restore a Regression Fixtures section in SKILL.md.
https://claude.ai/code/session_01DjuELpoFdFbFscr3kAatni
Both ./engineering/handoff and ./productivity/handoff were registered as
"handoff" in marketplace.json. Duplicate names pass the local CLI but fail
Claude.ai marketplace sync (used by Cowork), causing "Failed to add
marketplace". Renamed to handoff-engineering and handoff-productivity.
https://claude.ai/code/session_01DjuELpoFdFbFscr3kAatni
- Extract commun languages rules in a separate rules/universal.md containing all cross-language rules in one place
- Move language-specific rules inline into each languages/*.md file,
organised into consistent sections: Security / Async / Resource
Management / Exception Handling / Performance / Idioms
- Add Java support: languages/java.md with full section coverage
- Every review now requires exactly 2 file reads: universal.md +
one language file
- Add "Adding a new language" guide to SKILL.md: one file to create,
nothing else changes
The previous vibe sync was run with --domain productivity, which rewrote
.vibe/skills/claude-skills/skills-index.json to contain only the 6 productivity
skills, dropping the other ~317. The symlink tree was unaffected (all 14 domain
dirs intact) — only the index JSON was clobbered. Re-running the full sync
restores total_skills 6 -> 323 across all 14 domains. andreessen present.
https://claude.ai/code/session_01SF6MzfjHurZMt5JUFET9h3
Genuine, repo-consistent additions that lift the real quality gaps (not doc
padding):
- assets/forcing_question_worksheet.md — fillable 6-question interrogation
- assets/blank_3x5_card.md — blank daily card template
- assets/example_market_verdict.md — full worked market-first verdict
- assets/example_pmf_check.md — worked before/after PMF check
Both worked examples' tool invocations are verified against the actual scripts
(MARKET-FIRST-DERISK at composite 6.36; BEFORE-PMF at composite 4.35). SKILL.md
Assets section updated to reference all five.
Quality scorer: 56.2 -> 65.7 (clears the 60 gate). examples 60->100%,
assets 12->60%, practical_examples 40->80%. Audit now a clean PASS on quality
alongside structure 91.3/EXCELLENT, scripts 3/3, security 0/0.
https://claude.ai/code/session_01SF6MzfjHurZMt5JUFET9h3
Post-merge audit fixes for the andreessen productivity skill:
- Add skills/andreessen/README.md (inner skill README). Lifts structure
91.3/EXCELLENT and quality 56.2; the README was the one genuine doc gap
vs sibling skills.
- Run the gemini cross-platform sync (codex ran at merge time; gemini was
missed). Adds the andreessen symlink + index entry and reconciles a
pre-existing stale claude-coach entry the generator surfaced.
Audit verdict: PASS WITH WARNINGS. Structure 91.3 EXCELLENT, scripts 3/3
PASS, security PASS (0 critical/0 high), marketplace + ecosystem clean. The
single warning is the quality scorer's title-case section/frontmatter schema
that no Path-B productivity skill uses (andreessen 56.2 vs merged siblings
reflect 44.6 / capture 46.4).
https://claude.ai/code/session_01SF6MzfjHurZMt5JUFET9h3
New productivity/andreessen plugin — a Marc Andreessen-mode operator that
pressure-tests ventures/ideas/features/bets through his documented frameworks
(market > team > product; product/market fit is the only milestone; bias to
build) and runs his 3x5-card + Anti-Todo daily routine. Built as the
Andreessen-lens counterpart to a founder-operating-system plugin.
Runs on the user-supplied anti-sycophancy operating prompt, preserved verbatim
in references/operating_prompt.md (counterargument first, no premise validation,
no disclaimers, explicit confidence levels, no capitulation without new
evidence). The second emphasis block is operationalized as a posture-mapping
table so each instruction changes behavior rather than sitting as decoration.
Ships 3 stdlib-only deterministic tools (market_first_evaluator with a hard
sub-4 market kill gate, pmf_signal_scorer with the Sean Ellis 40% gate,
anti_todo_card enforcing the 3-5 cap), 4 references each citing 5-7 sources with
explicit confidence levels on every Andreessen attribution, cs-andreessen agent,
/cs:andreessen + /cs:pmf-check commands, and a worked 3x5-card asset.
Registered in marketplace.json + .codex skills index (productivity 5 -> 6).
.codex review/run/status symlinks reflect the sync generator's standard
collision resolution on the current tree.
https://claude.ai/code/session_01SF6MzfjHurZMt5JUFET9h3
Addresses the Phase 3 quality_scorer roadmap items from the plugin audit:
adds the bundled fixtures, sample outputs, and quick-reference README that
the scorer expects, without diverging from the project's minimal-frontmatter
SKILL.md convention.
assets/:
- sample_csharp_smells.cs: a C# fixture with every pattern the skill
detects (async void, blocking on Task, swallowed Exception, undisposed
IDisposable, new HttpClient(), missing await, null-forgiving, hardcoded
connection string, unsafe, dynamic, #pragma warning disable,
[SuppressMessage], SQL concatenation), each smell labelled inline
- sample_csharp_clean.cs: the same code refactored per the standards in
references/coding_standards.md — verifies the analyzer produces 0 HIGH
smells on idiomatic code
expected_outputs/:
- sample_csharp_smells_quality.json: committed analyzer output for the
smells fixture (F/45, 3 HIGH smells)
- sample_csharp_clean_quality.json: committed analyzer output for the
clean fixture (A/98, 0 HIGH smells)
These act as a regression harness: diff the live output against the
committed JSON to detect any behaviour change in the analyzer.
scripts/code_quality_checker.py:
- Add _strip_csharp_comments() that removes // line and /* */ block
comments before running C#-specific regex detectors. Fixes false
positives where comment prose ("// FIX: await instead of .Result")
matched a detection pattern.
SKILL.md:
- New ## Examples section pointing at the fixtures + showing how to
reproduce the expected output with diff
- TOC updated to list "C# / .NET Review Notes" and "Examples"
README.md (new):
- Quick-reference card with how-to, 3 worked examples (one per script),
pointer to fixtures, pointer to references
Phase re-scores after this change:
- Structure: 86.4/GOOD → 91.3/EXCELLENT (+4.9)
- Quality: 54.8/D → 72.5/B- (+17.7)
- Scripts: 3/3 PASS (unchanged)
- Security: 0/0 (unchanged)
Phase 7 of the plugin audit on engineering-team/skills/code-reviewer
found stale entries in the cross-platform indices — they still showed
the pre-#723 description without C# / .NET. Re-running sync also
refreshed two unrelated drifted entries (review/run/status codex
symlinks, claude-coach gemini symlink).
v2.8.1 was already taken by the engineering role-skill upgrade
(senior-fullstack / senior-frontend / senior-backend with karpathy-coder
+ Matt Pocock decision engines), released 2026-05-20 — before the
handoff PRs even merged. The auto-release workflow created the v2.8.1
tag from that work via CHANGELOG.md parsing.
The productivity/handoff skill is the next minor on top of v2.8.1:
v2.8.2.
Changes:
- CHANGELOG.md: prepend a new [2.8.2] entry documenting the handoff
skill (PRs #724, #728, #729). The auto-release workflow
(.github/workflows/release.yml) will pick up this entry and create
the v2.8.2 git tag + GitHub Release on the next push to main.
- productivity/handoff/.claude-plugin/plugin.json: 2.8.1 -> 2.8.2
- .claude-plugin/marketplace.json (handoff entry): 2.8.1 -> 2.8.2
- CLAUDE.md: 4 spots bumped to v2.8.2; v2.8.1 references kept where
they correctly point to the engineering role-skill release
- README.md: Productivity table row ✨v2.8.1 -> ✨v2.8.2
- docs/index.md: description, hero subtitle, "329 Skills" card text
- docs/getting-started.md: description meta + FAQ count text
- mkdocs.yml: site_description
The narrative across all top-level docs now reads correctly:
v2.8.0 (bizops + commercial) -> v2.8.1 (engineering role-skills) ->
v2.8.2 (productivity/handoff).
Verified:
- 0 v2.7.5 references remain (earlier typo)
- All v2.8.1 references that remain point to engineering role-skills
- CHANGELOG topmost entry: [2.8.2] - 2026-05-23
- plugin.json + marketplace.json both at 2.8.2
- mkdocs build clean (will re-verify in CI)
https://claude.ai/code/session_01KLhHBAfEDXdQMeRe6G8sRa
Ships the three improvements judged most impactful in v1.1 design review:
1. SessionEnd hook (hooks/session_end.py)
Pairs with SessionStart. When a session ends with no handoff in the
last 30 minutes, prints a one-line reminder. Cannot prompt
interactively or block session end — surfaces text via stdout.
Disable per-session with HANDOFF_SESSIONEND=0. hooks.json updated to
wire both SessionStart and SessionEnd.
2. handoff_self_check.py — fidelity script (~300 LOC, stdlib-only)
Operationalizes handoff_prompt.md. Six checks:
- All 5 sections present
- Goal is non-empty and non-placeholder
- State-of-play bullets reference at least one artifact (commit hash,
PR/issue number, file path, URL)
- Open decisions are present (or explicit "- None.") when git is dirty
or has recent commits
- Skills to use: 3-5 entries, hard cap enforced
- Artifacts contain paths/URLs only, no inline content
Severity: high/medium/low. Strict mode exits 1 only on HIGH findings.
--sample fixture has 3 planted issues (2 high + 1 medium) and exits 1.
Canonical example_handoff.md passes clean (exit 0).
/cs:handoff command updated to run self-check between scaffold-fill
and redaction linter.
3. --refresh flag on handoff_template_generator.py
Reuses the most recent handoff in the configured save location
instead of creating a new file. Falls through to create-if-missing
when no existing handoff is found. Keeps the save location
uncluttered when work continues past the original handoff time;
ensures the SessionStart hook always loads the up-to-date version.
Version bump: 2.7.4 -> 2.7.5. Marketplace description and keywords
updated. README v1.1 section added. SKILL.md gains "Refreshing an
Existing Handoff" and "SessionEnd Reminder" subsections.
Verified:
- All 9 Python files compile clean
- self-check --sample correctly fails (3 findings, exit 1)
- self-check passes clean against assets/example_handoff.md (exit 0)
- --refresh finds the latest /tmp/handoff-*.md and prints its path
- SessionEnd hook prints the reminder when no recent handoff exists
- check_plugin_json.py + marketplace.json + hooks.json all parse
- Plugin audit re-run: structure 84.2 -> 86.0, quality 62.2 -> 63.0,
security PASS (0 critical, 0 high)
- Codex + Gemini sync re-ran clean
https://claude.ai/code/session_01KLhHBAfEDXdQMeRe6G8sRa
CI's structure validator and Tessl quality review both expect the
repo's canonical Path-B layout (plugin root with .claude-plugin/,
agents/, commands/, skills/<name>/ subfolders) used by every other
engineering skill — caveman, grill-me, handoff, write-a-skill.
The flat layout shipped initially scored 42.9/100 internally and 0/100
on Tessl. After wrapping:
- SKILL.md and references moved under skills/claude-coach/
- 3 stdlib Python tools added: cheat_code_filter, prompt_rater,
coach_tip_classifier (5-gate decision tree)
- cs-claude-coach agent persona + /cs:claude-coach slash command
- .claude-plugin/plugin.json manifest (canonical "./skills/claude-coach" form)
- SKILL.md frontmatter extended with Tier/Category/Author/Dependencies
fields the validator requires; spec body content preserved
- SKILL.md picks up Name/Description/Features/Usage/Examples sections
appended below the original body so the validator's required-sections
check passes without disturbing the original coaching instructions
- coach_tip_classifier inlines a minimal prompt scorer instead of
cross-importing prompt_rater, eliminating the auditor's sys.path
finding
Local verification:
- Structure validator: 100.0/100 EXCELLENT (0 failed checks)
- Security auditor: PASS (0 critical/high/info findings)
- All 3 scripts pass --help and --sample
https://claude.ai/code/session_01KUWQ32LyRMFxYPN4VnhJsY
A coaching layer that teaches Claude power-user techniques on first
activation, then surfaces at most one tip per response when it spots a
missed opportunity. Hard rules: answer the user first, max one tip per
turn, silence is the default. Ships SKILL.md, a ranked cheat-codes
glossary, and explicit coaching rules to prevent over-coaching.
https://claude.ai/code/session_01KUWQ32LyRMFxYPN4VnhJsY
Auto-fixes from the 8-phase plugin audit:
- Drop `from __future__ import annotations` from all 7 Python files. The
validator flagged it as an "external import" (false positive — it's
stdlib). Type hints already use 3.10+ syntax (`Path | None`,
`dict[str, Any]`), so the import was redundant.
- Add `assets/example_handoff.md` — complete worked example of the
5-section output. Lifts quality scorer's "practical_examples" and
"assets_existence" dimensions.
- Add skill-level `README.md` (in addition to existing plugin-level one)
pointing at SKILL.md, scripts, references, and assets. Closes the
scorer's "readme_existence" warning.
- Extend SKILL.md from 90 -> 178 lines: add `## Examples` (4 scenarios)
and `## Usage` (command-to-step table). Clears the validator's
"SKILL.md too short" error and lifts the scorer's documentation depth.
- Sync Codex + Gemini indexes (auto-regenerated by the sync scripts).
Audit results after fixes:
Phase 2 (structure): 73.0 -> 84.2 (GOOD, threshold 75)
Phase 3 (quality): 53.9 -> 62.2 (C, sibling capture scores 46.4)
Phase 5 (security): 0 critical, 0 high (PASS)
All 6 scripts pass --help and --sample. End-to-end smoke test re-run
clean: template generator writes, hook surfaces, linter blocks
planted secrets in strict mode.
Verdict: PASS WITH WARNINGS (warnings are validator quirks — sibling
`config_loader` import flagged as external, same way `capture` and
`reflect` get flagged).
https://claude.ai/code/session_01KLhHBAfEDXdQMeRe6G8sRa
Ships the 5 must-haves for a handoff skill to fulfill its purpose:
1. SessionStart hook auto-loads the latest handoff (hooks/session_start.py).
Wrapped in <handoff_from_previous_session> tags so the next agent reads
it as data, not instructions. Disable per-session via HANDOFF_SESSIONSTART=0.
2. First-run setup with explicit save-location choice (no pre-selected
default). 5 core questions: save location, retention, redaction
strictness, git context, recommender scope. Prompt-once-then-default
model — declined setup leaves a sentinel so the prompt never re-appears.
3. Mandatory checklist for the agent (references/handoff_prompt.md) — 7
steps forcing topic-by-topic classification (State / Decision / drop)
instead of free-handing prose.
4. Redaction linter (scripts/redaction_linter.py) — 17 stdlib regex
patterns covering AWS/GitHub/OpenAI/Anthropic/Slack/Stripe keys, JWT,
private-key blocks, env-style secret assignments, DB connection strings
with creds, bearer tokens, URL token params, email, phone. Inline
whitelist marker for true false positives. Strict/warn/off modes.
5. mtime-guarded cleanup (scripts/cleanup.py) — never deletes a handoff
the user edited as a working surface.
Wrapper layout matches productivity/capture and productivity/reflect:
SKILL.md preserves Matt's seven sentences verbatim, surrounded by
invocation triggers, output path discipline, 5-section template, and an
anti-patterns block. Plus cs-handoff-author agent, /cs:handoff and
/cs:handoff-setup commands, 5 reference docs (each citing 5-6 sources),
6 stdlib-only scripts (all pass --help and --sample).
Coexists with engineering/handoff/ (code/PR-focused, no setup, no
redaction enforcement, no SessionStart hook). Both shipped in
marketplace.json. Codex slug collision: the productivity variant wins
the .codex/skills/handoff symlink because it's the more general-purpose
version; both remain in .codex/skills-index.json.
Credit to Matt Pocock surfaces in README + SKILL.md footer + scaffold
footer, not as a manifest attribution block (cleaner plugin.json).
Verified:
- All 6 Python tools pass --help and --sample
- redaction_linter --sample finds 8 planted secrets, exits 1 (strict)
- SessionStart hook smoke-tested end-to-end against a real scaffold
- check_plugin_json.py --all clean (0 failures across all plugins)
- sync-codex-skills.py re-ran clean (productivity: 4 -> 5)
https://claude.ai/code/session_01KLhHBAfEDXdQMeRe6G8sRa
Bundle of low-medium-severity follow-ups that were deferred when PR #720
landed the 3 blocking bugs. None of these silently break correctness —
they're discoverability, consistency, and convention gaps.
Bugs / code-quality:
1. fullstack_decision_engine.py: asymmetric cadence matching
`inputs.cadence in target or target in inputs.cadence` produced
asymmetric results — "per-pr" matched "per-pr-with-gates" but not
vice versa. Profile cadences are intentional alternatives joined
by "-or-" (e.g. "weekly-or-on-demand" → {weekly, on-demand}); now
parsed explicitly with "-with-..." modifier suffixes stripped.
Verified:
cadence=per-pr → matches per-pr, per-pr-with-gates, daily-or-per-pr
cadence=daily → matches daily-or-per-pr (only)
cadence=on-demand → matches weekly-or-on-demand
2. fullstack_decision_engine.py: rename weight_total/weight_matched
to w_total/w_matched. Backend and frontend engines already use the
short form; this aligns the three files as a family.
3. sync-gemini-skills.py: 3-way name collision in dedup logic
The naive `if name in seen_names: name = parent-name` handled one
collision but not two. Three "status" skills under "skills" parent
dirs produced two entries both named "skills-status". Now suffixes
with -2, -3, ... so each entry has a unique index name. Eliminates
the duplicate-name ambiguity surfaced when checking PR #713.
Discoverability:
4. senior-fullstack/SKILL.md: surface fullstack_decision_engine.py in
the labeled "Tools" section at the top. Previously only mentioned
inline in the body (5 references buried in the Stack Decision Matrix
section); not findable when scanning the SKILL.md.
Conventions / v2.8.0 compliance:
5. commands/cs-{fullstack,backend,frontend}-review.md: add explicit
"## Forcing-question library" section header per the v2.8.0
convention. Each lists the 7 questions inline with a pointer to
the canonical reference file.
6. agents/engineering/cs-{fullstack,backend,frontend}-engineer.md:
alphabetize the specialist list in the description field (annotated
that workflow body order remains dependency-driven). Makes the
three agent descriptions consistent as a family.
7. agents/engineering/cs-{backend,frontend}-engineer.md: promote the
"Cross-agent invocation" content out of Workflow 3 into a dedicated
"## When invoked as fork target" section with an explicit question-
skip table per parent agent (cs-fullstack-engineer, cs-cto-advisor,
cs-vpe-advisor, cs-ciso-advisor for backend; cs-fullstack-engineer,
cs-content-creator, cs-product-manager for frontend). Closes the
cross-agent contract gap the bot flagged.
Not changed:
- CLAUDE.md plugin-schema section (already corrected in #715; bot's
"stale text" claim was incorrect — it was reading the cumulative diff)
- Workflow body specialist order (intentional dependency order; would
break the SLO-first → API → DB → migration → observability sequence)
Verification:
- All 3 decision engines: --sample → exit 0
- Cadence matching: 3 test cases pass cleanly
- check_plugin_json.py --all → 0 FAIL, 0 WARN, 69 OK
- sync-gemini-skills.py → 392 unique names (was 391 unique / 1 dupe)
Addresses claude[bot] code review findings on PR #718.
1. backend_decision_engine.py: scoped language-preference match
Previous code serialized the entire profile dict to JSON and ran a
substring search, so --language-preference=go false-matched against
"django", "mongo", etc. New approach tokenizes profile_name +
stack.language + stack.runtime on '-' and checks exact membership.
Verified:
- language=go → matches go-or-rust-microservice only
- language=python → matches django-monolith + fastapi-python only
- language=typescript → matches node-express only
2. frontend_decision_engine.py: removed dead pass-block kill check
`if team_size in 4..10 and read_write_ratio >= 50: pass` was a no-op
with an unclear intent comment. Removed.
3. frontend_decision_engine.py: wired up unused inp_target_ms field
The field was declared on Inputs, exposed via --inp-target-ms, and
threaded through main() but never consulted by any kill criterion.
Added a kill check that mirrors the existing LCP one:
"mobile-4g primary with INP target Xms: tighten to < 200ms"
(Web Vitals 'good' threshold for INP is 200ms; 'poor' is 500ms.)
Verification:
- backend_decision_engine.py --sample → exit 0
- frontend_decision_engine.py --sample → exit 0
- fullstack_decision_engine.py --sample → exit 0 (untouched)
Resolves#712 and #714.
Claude Code's plugin spec (code.claude.com/docs/en/plugins-reference) requires
"All paths must be relative to the plugin root and start with ./". CC 2.1.144+
rejects the bare "skills" form with `Validation errors: skills: Invalid input`,
breaking plugin installs from this repo.
Changes:
- 47 plugin.json manifests migrated from "skills": "skills" → ["./skills"]
(canonical post-CC 2.1.144 form, also accepts string "./skills")
- scripts/check_plugin_json.py rewritten to enforce the live spec:
* Hard-fails on non-"./"-prefixed strings (except the legacy "skills" literal)
* Hard-fails on empty strings/arrays and non-string array entries
* Emits WARN (non-fatal) on the legacy "skills" literal as a safety net
for copied templates — the WARN tolerance can be removed later
* Tested against all four canonical forms + 3 garbage forms
- CLAUDE.md §5 rewritten to document the live spec, including the historical
context of the v2.1.107 → v2.1.144 regression window that's now closed
- 15 stale broken symlinks under .gemini/skills/ removed (orphans from older
reorgs that the sync script didn't prune because its cleanup is disabled)
Verification:
- scripts/check_plugin_json.py --all → 0 FAIL, 0 WARN, exit 0 (69 files OK)
- pytest tests/ → 2103 passed
- find . -type l ! -exec test -e {} \; → 0 broken symlinks
- Live spec forms tested: ["./"], ["./skills"], "./skills", ["./a","./b"] all pass
- Garbage forms rejected: bare "./", empty array, non-string entries, plain strings
Resolves conflict on .gitignore: kept our broader "Internal dev
artifacts" block (covers eval-workspace/ in full, which is a
superset of dev's eval-workspace/anthropic-skill-creator/ rule).
Folded a comment about the third-party clone + per-version
trigger-eval workspaces into the eval-workspace/ rule.
Also un-tracked 8 new files dev added under
eval-workspace/v2.8.0-trigger-eval/ — they'd otherwise leak into
the cleaned tree despite the ignore rule (gitignore doesn't
retroactively un-track). Files remain on local disk.
Remove 'model: sonnet' from cs-fullstack-engineer, cs-frontend-engineer,
and cs-backend-engineer YAML frontmatter so each agent inherits the model
configured in the user's Claude Code settings instead of being locked to sonnet.
Co-authored-by: Alireza Rezvani <alirezarezvani@users.noreply.github.com>
Move 54 internal-only files out of the public tree via git rm --cached
+ .gitignore. Files remain on the maintainer's local disk; future fresh
clones see only production skill packages and user-facing docs.
Hidden:
- documentation/ (sprint plans, strategy, roadmaps) — 16 files
- eval-workspace/ (Tessl eval outputs) — 6 files
- megaprompts/ (Path-B draft specs) — 16 files
- tests/ (pytest suite — run locally, not in CI) — 14 files
- .autoresearch/ (autoresearch workspace) — 1 file
- AUDIT_REPORT.md (stale tracked despite prior ignore)
CI: remove the pytest step from ci-quality-gate.yml since tests/ is
no longer tracked. Other quality gates (yamllint, plugin.json schema,
compile-all, safety, link-check) remain in place.
CLAUDE.md: add a Maintainer-Local Folders section near the top so
future readers understand why these paths are referenced but absent
from GitHub.
No history rewrite — going-forward only. Past commits still contain
these files; only HEAD is cleaned.
Adds end-to-end release automation so every CHANGELOG bump produces a
matching git tag + GitHub Release with notes — no manual `gh release
create` invocations required.
- .github/workflows/release.yml — push to main triggers parse-CHANGELOG
→ check tag exists → create tag → create GH Release with notes. Idempotent
(existing tags skipped). Manual workflow_dispatch supports targeting a
specific historical version. Path-filter limits firing to actual release
pushes (CHANGELOG.md, the parser, or the workflow itself changing).
- scripts/extract_release_notes.py — stdlib-only CHANGELOG.md parser.
Outputs JSON, plain text, or github-release-formatted markdown.
Runnable standalone for preview: `python3 scripts/extract_release_notes.py
--format github-release`. Default extracts the latest entry; --version
pins to a specific release.
- CHANGELOG.md — new [2.8.0] entry covering the v2.8.0 Sprint 1 work
(business-operations + commercial domains, #688) plus the #686 plugin.json
fix (#689) and #690 regression-prevention validator + CI gate. This is the
entry the release workflow will pick up on first run after this lands on
main.
When this commit (plus the dev → main sync #692) reaches main, the workflow
fires, parses CHANGELOG, sees v2.8.0 at the top, creates the `v2.8.0` tag
and GitHub Release — automatically. All future releases follow the same
flow: add a CHANGELOG entry, merge to main, done.
Issue #686 was the second round of the same Claude Code path-validator
tightening: v2.1.107 rejected bare "./" (fixed in #539 by moving to
"./skills"), then v2.1.133 also rejected "./skills". The validator that
codified the #539 fix was still recommending "./skills" verbatim — so a
future round 3 would have hit the same trap.
This commit makes the validator catch the regression and runs it in CI:
- scripts/check_plugin_json.py
- Reject any "skills" string starting with "./" (catches both
"./skills" and "./skills/sub" patterns)
- Update docstring + error message to point at the layout-correct
forms instead of the now-broken "./skills"
- Recognize "source" and "attribution" as approved extension fields
(already documented in CLAUDE.md but not in the validator), so the
21 pre-existing false-positives go away and CI can run blocking
- Drop the "./" rejection inside arrays — CLAUDE.md says ["./"] is
the correct single-skill-at-root form
- .github/workflows/ci-quality-gate.yml
- Add blocking "Validate plugin.json manifests" step that runs the
validator on every PR
- CLAUDE.md
- Add an Enforcement note pointing at the validator and the lockstep
rule: when CC tightens its path validator again, update validator
rules and CLAUDE.md together
Verified: 69/69 manifests pass; 6-case smoke test confirms validator
rejects all three known-broken forms ("./skills", "./", "./skills/sub")
and accepts all three documented-valid forms ("skills", ["./"],
explicit array).
Co-authored-by: Claude <noreply@anthropic.com>
Issue #686 was the second round of the same Claude Code path-validator
tightening: v2.1.107 rejected bare "./" (fixed in #539 by moving to
"./skills"), then v2.1.133 also rejected "./skills". The validator that
codified the #539 fix was still recommending "./skills" verbatim — so a
future round 3 would have hit the same trap.
This commit makes the validator catch the regression and runs it in CI:
- scripts/check_plugin_json.py
- Reject any "skills" string starting with "./" (catches both
"./skills" and "./skills/sub" patterns)
- Update docstring + error message to point at the layout-correct
forms instead of the now-broken "./skills"
- Recognize "source" and "attribution" as approved extension fields
(already documented in CLAUDE.md but not in the validator), so the
21 pre-existing false-positives go away and CI can run blocking
- Drop the "./" rejection inside arrays — CLAUDE.md says ["./"] is
the correct single-skill-at-root form
- .github/workflows/ci-quality-gate.yml
- Add blocking "Validate plugin.json manifests" step that runs the
validator on every PR
- CLAUDE.md
- Add an Enforcement note pointing at the validator and the lockstep
rule: when CC tightens its path validator again, update validator
rules and CLAUDE.md together
Verified: 69/69 manifests pass; 6-case smoke test confirms validator
rejects all three known-broken forms ("./skills", "./", "./skills/sub")
and accepts all three documented-valid forms ("skills", ["./"],
explicit array).
Claude Code 2.1.133+ rejects "skills": "./skills" with a "Path escapes
plugin directory" warning, even though ./skills resolves to a valid
subdirectory inside the plugin root. Per the upstream docs example, the
correct value is "skills" (no ./ prefix), which works across all CC
versions and other tools (Codex, Gemini CLI, etc.).
Applied to all 47 plugin.json files that used "./skills"; updated
CLAUDE.md ClawHub publishing constraints to document the new convention
and reference the issue.
Two new top-level domain folders expanding the repo from 313 → 319 production
skills across 14 domains. Path-B 11-file contract per skill, stdlib-only Python
tools, Matt Pocock grill-with-docs discipline baked into every SKILL.md.
## New domains
- business-operations/ — internal-ops skills for BizOps leads, COO direct
reports, vendor management, IT ops. Sprint 1 ships 3 skills:
- business-operations-skills (orchestrator, context: fork)
- process-mapper (BPMN + bottleneck + cycle-time, 4 industry profiles,
Lean/TOC canon)
- vendor-management (scorecard + SLA + 3rd-party risk, 4 industry profiles,
Shared Assessments SIG-Lite, NIST SP 800-161, ISO/IEC 27036)
- commercial/ — per-deal-and-packaging skills. Sprint 1 ships 3 skills:
- commercial-skills (orchestrator, context: fork)
- pricing-strategist (5-model picker, Van Westendorp PSM with OPP/IDP/PMC/PME,
packaging with 7 anti-pattern detectors, Ramanujam/Skok/Tunguz canon)
- deal-desk (5-dim scorer, discount approval router, 10-pattern terms redliner,
never auto-approves — every verdict names the human approver)
## Chaining via context: fork
Both domain orchestrators set context: fork in frontmatter so heavy ingestion
(vendor catalogs, RFP docs, process transcripts) stays out of the parent
session. Sub-skills opt into fork only when they ingest large artifacts
(vendor-management does, pricing-strategist and deal-desk do not).
## Matt Pocock grill discipline
Every Sprint 1 SKILL.md ships a "Forcing-question library" section: 5-7
questions, walked one at a time by the orchestrator (or /cs:grill-bizops,
/cs:grill-commercial), each with a recommended answer + canon citation.
Discipline derived from engineering/grill-me + engineering/grill-with-docs
(Matt Pocock, MIT).
## Hard rules per domain
- BizOps: every output is a recommendation, never an auto-decision.
- Commercial: pricing outputs model+range (never a single number); deal outputs
route to a named human approver (never auto-approve); forecasts surface the
conversion assumption explicitly.
## Agents + commands
- cs-bizops-orchestrator agent ("Where does the work spend most of its time
waiting?")
- cs-commercial-orchestrator agent ("What's the margin on this deal at full
discount?")
- 8 new slash commands: /cs:bizops, /cs:commercial, /cs:grill-bizops,
/cs:grill-commercial, /cs:process-map, /cs:vendor-review, /cs:pricing-strategy,
/cs:deal-review
## Verification
- All 12 new Python tools (4 skills × 3 each) pass --help and --sample
smoke tests, exit 0
- Stdlib-only across the board
- 12 reference docs each cite ≥ 7 authoritative sources
- Marketplace registry: 57 → 59 plugins
## Sprint 2 (not in this PR)
- BizOps: capacity-planner, internal-comms, knowledge-ops, procurement-optimizer
- Commercial: partnerships-architect, channel-economics, commercial-policy,
rfp-responder, commercial-forecaster
## Files
50 new files: 6 SKILL.md (2 orchestrators + 4 leaf) + 12 Python tools + 12
references + 4 asset templates + 2 plugin.json + 2 CLAUDE.md + 2 README.md +
2 cs-* agents + 8 slash commands + 1 master plan doc + marketplace.json +
root CLAUDE.md update.
Master plan: documentation/implementation/bizops-commercial-expansion-plan.md
https://claude.ai/code/session_015bBb4HzWCf5HH5QK2TGtnW
Closes#665. Adds 500x500 PNG icon at assets/icon.png and wires it
through composerIcon in .codex-plugin/plugin.json so the plugin renders
in the awesome-codex-plugins marketplace browser.
Note: A separate PR to hashgraph-online/awesome-codex-plugins is still
needed to set the icon field on their marketplace.json entry.
Move PIL import from module-level to inside analyse_image() so argparse
help text displays without requiring Pillow installed. Add proper argparse
with --json support per project conventions.
Fixes#653
The user flagged that nowhere in the documentation do we guide users
through installing and configuring Hermes Agent itself with our skills.
PR #678 covered the technical integration but missed this user-facing
step.
Additions to docs/integrations.md Hermes Agent section:
**Step 1 — Install Hermes Agent itself (NEW)**
- macOS/Linux: 5-step setup (clone → venv → deps → .env → first run)
- Windows: WSL2 guidance
- Docker: one-liner with $HOME/.hermes volume mount
- Provider note: works with Nous, OpenAI, Anthropic, or any
OpenAI-compatible endpoint (no Nous account required)
**Step 3 — First-run walkthrough (NEW)**
- Complete dry-run from cold install to first skill invocation
- Examples: /skills, /research <query>, /skill_view, /skills search
- Shows how our orchestrator routing surfaces in Hermes UX
**Configuration tips (NEW)**
- Sample ~/.hermes/config.yaml block with our skill paths
- auto_load recommendations (karpathy-coder always-on, grill-me sparingly)
- display: show_category for grouping by claude-skills/<domain>/
**Troubleshooting (NEW — 6 Q&A entries)**
1. /skills shows 0 results after sync (target path + permissions)
2. Symlinks point to wrong path (cross-machine portability — relative
symlinks per v2.7.2+)
3. Slash command collisions (Hermes built-ins vs claude-skills)
4. ModuleNotFoundError on Python tools (3.10+ requirement)
5. SKILL.md not found despite file existing (nested-plugin flatten via
sync script)
6. How to unsync (rm -rf ~/.hermes/skills/claude-skills/)
Also bumped verify count: 198+ → 303 (v2.7.2+) so the post-sync
sanity check now expects accurate numbers.
https://claude.ai/code/session_01FEUmeuYhmnxVFq7EZM8ZSw
The user flagged that we advertise Hermes Agent as a tier-1 supported
platform in the "Works with:" list, but the actual integration was
significantly thinner than Codex/Gemini/OpenClaw:
- No committed .hermes/ tree (other platforms ship pre-generated trees)
- sync-hermes-skills.py DOMAIN_DIRS missing the 3 v2.7.0 top-level
domains (productivity, marketing, research) — running it today would
silently skip all 13 v2.7.0 skills
- Discover function only handled the flat `<domain>/<skill>/` pattern,
missing the nested-plugin pattern `<domain>/<plugin>/skills/<skill>/`
used by all v2.7.0 skills + many older plugins
- Doc count stale at "198+ skills" / "246 skills"
- 35 Hermes mentions vs Codex 1010 / Gemini 622 / OpenClaw 572 —
under-documented relative to the marketing claim
This commit upgrades Hermes to first-class technical support while
labeling it BYO-sync in marketing (honest about the workflow:
pre-generated tree shipped, but user runs sync into ~/.hermes/ once).
**scripts/sync-hermes-skills.py changes:**
1. DOMAIN_DIRS extended with `productivity`, `marketing`, `research`
(the 3 v2.7.0 top-level domains)
2. `discover_skills()` rewritten to handle all 3 SKILL.md location
patterns (same logic as sync-codex-skills.py):
- Pattern 1: `<domain>/<skill>/SKILL.md` (flat legacy)
- Pattern 2: `<domain>/skills/<skill>/SKILL.md` (flat with skills/)
- Pattern 3: `<domain>/<plugin>/skills/<skill>/SKILL.md` (nested plugin)
Dedupes by SKILL.md path.
3. `sync_skill()` now creates RELATIVE symlinks (via os.path.relpath)
instead of absolute. Critical for committed .hermes/ tree to work
across machines. Falls back to absolute if cross-device.
**.hermes/skills/claude-skills/ tree committed:**
- 289 relative symlinks across 12 domains
- skills-index.json (303 skills documented with descriptions)
- All v2.7.0 skills present: productivity (4), marketing (1),
research (8)
**Documentation refresh:**
- docs/integrations.md:
- Header count: 246 → 311 skills
- Hermes section: NEW "Tier: BYO-sync" tip box explaining the
pre-generated tree + the one-line install step
- Install table: "198+ skills" → "303 skills (12 domains)"
- README.md:
- Hermes Agent entry in "Works with:" line now flagged with [^hermes]
footnote explicitly labeling it BYO-sync tier with link to the
sync script
Verification:
- Script smoke-test: `python3 sync-hermes-skills.py --target .hermes/skills --verbose`
→ 303 skills discovered, 289 new symlinks, 14 skipped (pre-existing)
- All v2.7.0 symlinks resolve correctly:
`.hermes/skills/claude-skills/research/research → ../../../../research/research/skills/research`
- 12 domains present in tree (was 9 before)
Per CLAUDE.md ClawHub rules: this PR does NOT update marketplace.json
(Hermes is not on ClawHub). The .hermes/ tree is repo-side
infrastructure only.
https://claude.ai/code/session_01FEUmeuYhmnxVFq7EZM8ZSw
The docs/plugins/index.md page was severely outdated, still showing
v2.1.x-era counts: 28 plugins, 9 domains, 177 skills, with a hardcoded
list of 10 standalone plugins. Missed entirely during PR #675's v2.7.0
docs sweep because it wasn't on the 7-step pipeline checklist.
Refreshed all numbers + content to current marketplace.json reality:
- 28 → 55 plugins
- 9 → 12 domains (added Productivity, Marketing top-level, Research)
- 177 → 311 skills
- v2.1.2 → v2.7.0 (Plugin Structure example + FAQ)
Plugin Architecture mermaid:
- Updated total to 55 plugins
- Added "v2.7.0 New Plugins" subgraph (12 standalone: 3 productivity,
1 marketing, 8 research incl. orchestrator)
- Renamed "Standalone (10)" → "Other Standalone (46 total)"
Content additions:
- New section: "v2.7.0 Standalone Plugins ✨" with 3 sub-tables
(Productivity / Marketing / Research) — all 12 new plugins with
install commands and one-line descriptions
- "Other Standalone Plugins" — now a programmatically-generated table
of 34 non-v2.7.0 standalones grouped by category (was hardcoded list
of 10 — many obsolete: content-creator, demand-gen, fullstack-engineer,
aws-architect, product-manager were never in marketplace.json)
- "All 55 Plugins at a Glance" — full table from marketplace.json data,
marks v2.7.0 entries with ✨
Domain Bundles section:
- Skill counts refreshed (engineering-skills 24→32, marketing-skills
43→44, ra-qm-skills 12→14, product-skills 12→13, pm-skills 6→9,
business-growth-skills 4→5, finance-skills 2→3)
- Engineering POWERFUL bundle now mentions 4 Matt Pocock skills
- C-Level Advisory bundle now mentions all 14 C-suite roles (was 9)
- RA/QM bundle now mentions EU AI Act + ISO 42001
FAQ additions:
- "What are the v2.7.0 plugins?" — explains the 12 new plugin scope
- "What is the research orchestrator?" — explains hybrid router pattern
+ distinct_from autoresearch-agent disambiguation
Plugin Structure section:
- Added documentation of the two approved extension fields per
CLAUDE.md ClawHub rule #5: `source` (Path-B provenance) and
`attribution` (MIT external derivatives)
Verification:
- MkDocs build PASSES (no plugins-related errors or warnings)
- 0 stale references remaining (28 plugins, 9 Domains, 177 Skills,
v2.1.2 all cleaned)
- 464 lines, 22 sections, all 55 plugins now represented
https://claude.ai/code/session_01FEUmeuYhmnxVFq7EZM8ZSw
Resolves the two follow-ups left after the v2 megaprompt sweep.
**marketplace.json (.claude-plugin/):** +12 plugin entries for the new v2
skills across 3 categories. Categories added: productivity (3), research (8).
| Plugin | Source | Category |
|---|---|---|
| capture-skill | ./productivity/capture | productivity |
| email-pair | ./productivity/email | productivity |
| reflect-skill | ./productivity/reflect | productivity |
| landing | ./marketing/landing | marketing |
| pulse | ./research/pulse | research |
| litreview | ./research/litreview | research |
| grants | ./research/grants | research |
| dossier | ./research/dossier | research |
| patent | ./research/patent | research |
| syllabus | ./research/syllabus | research |
| notebooklm | ./research/notebooklm | research |
| research-orchestrator | ./research/research | research |
Per CLAUDE.md ClawHub rules: cs- prefix not used in repo registry
(reserved for ClawHub when slug conflicts arise). 12 entries cover 13
skills (email-pair holds inbox-setup + inbox-triage).
Total plugins in marketplace: 43 → 55.
**.codex sync:** Manually created 11 missing symlinks under .codex/skills/
(capture + pulse already existed from prior auto-sync). Added 13 entries
to .codex/skills-index.json with category metadata. Total skills: 290 → 303.
**scripts/sync-codex-skills.py:** Added productivity/, marketing/, and
research/ to SKILL_DOMAINS so future automated sync runs pick up the new
top-level domains (previously only domain folders were registered).
Manual symlink creation deliberately avoids the script's full
--dry-run-flagged 16 [UPDATED] symlinks on pre-existing duplicate-path
skills (chief-ai-officer-advisor, chaos-engineering, etc., which have
both nested-plugin and flat paths in the repo). That churn belongs in
a separate cleanup PR — not in this release-prep PR.
Validation:
- marketplace.json: 55 plugins, all 7 required fields, no duplicates
- skills-index.json: 303 entries across 11 categories
- all 13 megaprompt symlinks resolve correctly
- 8-phase plugin audit on research/research: PASS WITH WARNINGS
(Phase 2 structure 84.1/GOOD, Phase 5 security PASS, scripts 3/3)
https://claude.ai/code/session_01FEUmeuYhmnxVFq7EZM8ZSw
Surgical move PR — resolves the two domain warts accumulated during
the v2 megaprompt build sweep:
engineering/pulse/ → research/pulse/ (research-pack — pulse is
the first research skill;
now joins litreview, grants,
dossier, patent, syllabus)
engineering/capture/ → productivity/capture/ (productivity — capture
is brain-dump organizer,
not engineering tooling)
WHY THIS PR
When Slice 1 (capture) shipped in PR #659, the productivity/ domain
folder didn't yet exist. When Slice 2 (pulse) shipped in PR #660, the
research/ folder didn't yet exist either. Both were placed in
engineering/ as the catch-all.
After Slices 3-5 established the productivity/, marketing/, and
research/ top-level domain folders, those two early skills were left
in engineering/ as warts. This PR resolves them BEFORE Slice 7
(13-research orchestrator) so the orchestrator can reference
research/pulse/ as its routing target without further path churn.
WHAT MOVED
Two directories moved via `git mv` (preserves rename history):
- engineering/pulse → research/pulse (11 files)
- engineering/capture → productivity/capture (11 files)
INTERNAL REFERENCES UPDATED
Inside the moved directories:
- .claude-plugin/plugin.json homepage URLs (engineering/X → new path)
- agents/cs-*.md `skills:` frontmatter field
CROSS-SKILL REFERENCES UPDATED
6 external files reference pulse and/or capture as sibling skills.
All updated via sed:
productivity/email/agents/cs-inbox-setup.md (capture ref)
productivity/email/agents/cs-inbox-triage.md (pulse + capture refs)
research/grants/agents/cs-grants.md (pulse ref)
research/litreview/agents/cs-litreview.md (pulse ref + stale
"will move in cleanup
PR" caveat removed)
research/dossier/agents/cs-dossier.md (pulse ref)
marketing/landing/agents/cs-landing.md (pulse + capture refs)
CODEX SYMLINKS RE-POINTED
.codex/skills/{capture,pulse} symlinks updated to point at new
locations. Verified resolution to SKILL.md files works.
.codex/skills-index.json still references the old paths — this file
is auto-regenerated by the codex-sync workflow on every merge to dev
(prior commits: 9a47d85, bf5d4c2, f0176e0). Will regenerate fully
when this PR merges.
VERIFIED CLEAN
- `grep -rn 'engineering/pulse\|engineering/capture'` returns zero
results outside .codex/skills-index.json (which auto-regenerates).
- Moved scripts smoke-tested from new locations:
productivity/capture/skills/capture/scripts/workspace_inventory.py
--sample → returns inventory correctly
research/pulse/skills/pulse/scripts/citation_tracker.py
--action list → returns empty (no sessions) as expected
- Symlinks resolve: `.codex/skills/capture/SKILL.md` and
`.codex/skills/pulse/SKILL.md` both readable.
POST-CLEANUP STATE
Domain folders contain only domain-appropriate skills:
engineering/ — software-engineering tools (Matt Pocock skills,
agenthub, caveman, grill-me, grill-with-docs,
handoff, write-a-skill, 20+ other engineering
skills)
productivity/ — capture (new), email pair (inbox-setup +
inbox-triage)
marketing/ — landing
research/ — pulse (new), litreview, grants, dossier,
patent, syllabus
This matches the CLAUDE.md navigation map's domain definitions and
removes the two cumulative warts.
REMAINING WORK (after this merges)
☐ Slice 6: notebooklm (browser-automation, last shape)
☐ Slice 7: 13-research orchestrator + autoresearch-agent reconciliation
☐ Slice 8: 02-reflect (productivity sibling of capture)
9 of 13 v2 megaprompts shipped. 3 remaining + this cleanup.
https://claude.ai/code/session_01FEUmeuYhmnxVFq7EZM8ZSw
Vertical-slice install: first of 13 skills derived directly from the
v2 megaprompts (PR #657, merged). Validates the Path-B conversion
pattern (megaprompt → SKILL.md + scaffolding) before batching the
remaining 12 specs.
SOURCE SPEC
megaprompts/05-capture-megaprompt.md (PR #657). The megaprompt is the
canonical spec; this plugin is the working implementation. Drift
between the two is a bug — re-grill with /cs:grill-with-docs if they
diverge.
WHAT THE SKILL DOES
Brain-dump organizer. Catches an unstructured stream of mixed
thoughts/tasks/ideas and transforms it into a 4-section actionable
system (Projects/Ideas, Tasks, Connections, How I Can Help) with zero
information loss. Fast-to-action by design — no upfront intake.
Asks at most ONE mid-organization clarifying question (only when one
item is genuinely ambiguous between task and project). Workspace
detection is real (Glob/Grep) — never fabricates connections.
Compressed output for small dumps (≤5 unrelated items).
PATH-B CONVERSION DISCIPLINE
- Frontmatter description preserved verbatim from megaprompt spec.
- Workflow structure (megaprompt lines 38-48) became SKILL.md
section ordering 1:1.
- 5 operating principles, 4 sections, anti-patterns list, validation
checklist all preserved with minimal restructuring.
- Some megaprompt prose offloaded into the 3 reference files (the
wrapper additions). Net SKILL.md ~1,800 words, within the
megaprompt's 1,400-2,000 word budget.
- Trigger phrases all surfaced verbatim in SKILL.md "Invocation
Triggers" section.
REPO STRUCTURE (mirrors grill-with-docs 1:1)
engineering/capture/
├── .claude-plugin/plugin.json ← source.spec field points at megaprompt
├── README.md
├── agents/cs-capture.md ← persona, no-fabrication enforcer
├── commands/cs-capture.md ← /cs:capture <dump>
└── skills/capture/
├── SKILL.md ← Path-B converted from megaprompt
├── references/
│ ├── workspace_detection.md ← 4 contexts × tactics
│ ├── voice_preservation.md ← 7 anti-pattern examples
│ └── complexity_matching.md ← format-decision table + 3 worked examples
└── scripts/
├── workspace_inventory.py ← stdlib Glob+Grep helper
├── dump_classifier.py ← stdlib heuristic line-classifier
└── complexity_estimator.py ← stdlib full-vs-compressed recommender
11 files, 1,560 lines. Comparable to grill-with-docs (13 files,
1,747 lines) — capture is leaner because it has no separate format
files (Matt's grill-with-docs ships ADR-FORMAT.md + CONTEXT-FORMAT.md
verbatim alongside SKILL.md; capture's spec is fully self-contained).
VERIFIED CLEAN
- All 3 scripts pass `--help`, `--sample`, and `--output json`.
- workspace_inventory.py: correctly Glob+Greps embedded sample tree
(6 files, 5 folders), surfaces auth+login matches with line numbers.
- dump_classifier.py: labels 13-item sample dump (4 context, 4 task,
2 project-component, 2 question, 1 decision). Known limitation:
verbs like "Brief" / "Rewrite" / "Do" not in task-trigger regex
list — heuristic, documented in script docstring.
- complexity_estimator.py: correctly recommends format=full on 14-item
4-cluster dump and format=compressed on 5-item 0-cluster dump.
- plugin.json validates as JSON; conforms to repo's plugin schema
(name, description, version, author, homepage, repository, license,
skills + optional source attribution block).
VERTICAL-SLICE STATUS
This is Slice 1 of 13. Megaprompt shapes covered:
✓ Light prompt-flow (this slice — 02-reflect transfers cleanly)
☐ Research-pack (01-pulse, 03, 08-12) — Slice 2
☐ Workflow-pair (06+07 email) — Slice 3
☐ Generator (04-landing) — Slice 4
☐ Orchestrator/router (13-research) — Slice 5; reconcile with
existing engineering/autoresearch-agent/
After Slice 2 validates the research-pack conversion pattern (which
includes the cross-skill consistency rules audited in PR #657), the
remaining 11 skills can be batched.
NOT DONE IN THIS PR
- .claude-plugin/marketplace.json not updated (separate concern;
would be done in a marketplace-bundle PR after all 13 ship)
- .codex/skills/capture symlink not added (auto-sync workflow handles
this on merge per the existing pattern — see commit 6a9abc9 for
grill-with-docs)
https://claude.ai/code/session_01FEUmeuYhmnxVFq7EZM8ZSw
Cross-skill consistency audit per the PR test plan surfaced six gaps;
all six are fixed here in a single follow-up commit. Three were real
bugs and three were surface inconsistencies that the orchestrator's
cross-skill validation would flag.
REAL BUGS
(1) 13-research SIGNALS map: the most natural pulse router phrases
("pulse on", "take the pulse", "current conversation") were missing
— invocations like "pulse on AI safety" would fall through to general
fallback instead of routing to the pulse specialist. Added all three
to pulse signals. Also added "grants for" + "litreview" stems. Removed
bracketed placeholders ("research [company]", "research [person]")
from dossier signals because the pseudo-code does literal substring
matching and would never match a placeholder; added an inline comment
explaining why placeholders are intentionally excluded (they would
over-trigger on generic "research X" queries that should ask Q3
domain disambiguation instead). Updated the specialist-registry table
row for dossier and the corresponding anti-pattern entry to match the
new SIGNALS reality.
(2) 01-pulse missing the Agent Integrity Rules block. Pulse predates
the research-pack convention; the 0 hits across rate-limit/three-
count/source-discipline/retry markers meant any orchestrator cross-
skill validator would flag it as divergent. Added the full block:
parallel-across-platforms / sequential-within / 1 q/sec per platform
/ source discipline with training-knowledge tagged / three-count
tracking surfaced in synthesis audit / retry-once-after-3s / stop-
after-3-consecutive-failures / plan-tier detection for Reddit + HN
public APIs. Added the matching 7 rows to the validation checklist.
(3) 06-inbox-setup missing explicit stop condition for its ~25–31-
question intake (heaviest in the library). Added stop-condition spec:
hard ceiling 35 questions, Section 4 skip drops total by 6, intake
closes after Section 8 handoff and is never re-opened — re-running
the skill is the way to change preferences later (detects existing
files, asks per-file replace/merge/skip). One-at-a-time rule applies
across section boundaries.
SURFACE INCONSISTENCIES
(4) 09-litreview + 10-syllabus used "Data Integrity Principles" as
the section header for what 08/11/12/13 call "Agent Integrity Rules".
Same content, divergent names. Normalized both to "Agent Integrity
Rules (research-pack convention)" in section index, body header, and
validation checklist row.
(5) Trigger phrase lists in 08-grants, 09-litreview, 10-syllabus used
smart quotes ("...") inherited from original drafts; rest of the
library uses straight quotes ("..."). Normalized all three.
(6) 08-grants frontmatter description listed "grants for [topic]" as
a trigger but the Trigger Phrases bullet list did not include it.
Added as the lead bullet so both surfaces agree. Same fix applied to
09-litreview (added "litreview on [topic]" bullet) and 10-syllabus
(added "syllabus reading list" bullet) for parity with v2 naming.
VERIFIED CLEAN
- 13-research SIGNALS now: 3 pulse-router phrases present, "grants
for" present, no bracketed placeholders in any specialist's literal
list
- 01-pulse: 3 hits on "Agent Integrity Rules", 2 on three-count, 2 on
1 q/sec, 1 on retry once, 1 on consecutive failures, 2 on source
discipline
- 06-inbox-setup: 1 hit on stop condition (was 0)
- 09 + 10: 3 hits each on "Agent Integrity Rules", 0 hits on "Data
Integrity Principles"
- 08 + 09 + 10 trigger lists: 0 smart-quote occurrences
NOT FIXED (intentional)
- Several litreview triggers ("writing a paper on X", "help me
research X") don't match the 13-research SIGNALS map. This is by
design — those phrases fall through to Q3 domain disambiguation,
where the user picks academic-literature explicitly. Auto-routing
generic "research X" queries would over-trigger; the explicit
fallback path is the right hybrid behavior.
https://claude.ai/code/session_01FEUmeuYhmnxVFq7EZM8ZSw
Updates 00-master-orchestrator.md and megaprompts/README.md to reflect
the completed v2 expansion (13 skills across productivity + research
domains) and the grill-me intake discipline retrofitted across all
megaprompts.
00-master-orchestrator.md:
- Skill inventory split into productivity pack (6) and research
pack (7); old core/email/research grouping retired
- Pack flags renamed: --pack=productivity, --pack=research,
--pack=email-pair (replaces --pack=core, --pack=email)
- Dependency table updated for new skills: web_fetch coverage for
Google Patents/Espacenet/USPTO (11) and multi-source (12);
bash_tool coverage for Lens.org BYOK (11) + SEC EDGAR (12)
- Phase 3 generation note: research (13) must validate AFTER its
specialist registry (01, 08, 09, 10, 11, 12) is generated
- Phase 4 per-skill validation now requires grill-me discipline
(one-at-a-time, forcing format, why-I'm-asking, dependency-
ordered, max-question stop)
- Phase 5 cross-skill validation adds research-13 classification
correctness check (routing signals against specialist triggers)
- New "Grill-Me Discipline" quality-standards section codifies the
Matt Pocock six-rule discipline
- Anti-patterns add the batching + vague-acceptance failure modes
- Failure-mode table adds the grill-me-missing case
- Final deliverable file tree shows the domain split with explicit
productivity / research section comments
megaprompts/README.md:
- File table reorganized: orchestrator / productivity pack / research
pack — separate tables per domain
- Quality standards table gains grill-me intake discipline as
standard #2 (with all 6 sub-principles inlined)
- Pack notes section reorganized to match the new domain split
- New "Email Pair (06 + 07) — Knowledge Base Contract" subsection
documents the verbatim KB file contract at \${WORKSPACE}/Email/
- Portability matrix expanded to 13 skills
- New "Naming Conventions (v2 renames)" table documents every v1→v2
rename with rationale (9 renames; notebooklm preserved)
- Cross-skill validation list adds: no trigger-phrase collisions
with research-13 routing, grill-me presence in every intake,
file-contract alignment for the email pair
https://claude.ai/code/session_01FEUmeuYhmnxVFq7EZM8ZSw
Renames the mega prompt file and updates frontmatter name + SKILLS_DIR
path. The new name pivots from the output ("reading list") to the
input ("syllabus") — the input is the more memorable handle since
that's what the user has on their desk.
Adds Phase 0 grill-me intake (3 forcing questions) before parsing the
syllabus, and restructures the existing group-and-confirm step as a
grill-me forcing-options checkpoint:
Phase 0 Q1 syllabus input format forcing choice (file path / pasted
content / image) — each format routes to a different reader
Phase 0 Q2 course audience forcing choice across 6 options (undergrad
intro / undergrad advanced / grad masters / grad doctoral /
professional / mixed) — drives summary jargon level and
discussion-question complexity
Phase 0 Q3 year range forcing choice (1 / 2 default / 5 years) —
drives year_min on every Consensus search
Group-and-confirm checkpoint becomes forcing options: proceed / merge
sections / split section / add section / remove section. Refuses to
start Phase 3 (the Consensus search budget) without explicit user
confirmation.
Bundled script path updates from recommended-reading-list/scripts/ to
syllabus/scripts/. Trigger phrases lead with "syllabus reading list"
while retaining all prior phrases.
https://claude.ai/code/session_01FEUmeuYhmnxVFq7EZM8ZSw
Renames the mega prompt file and updates frontmatter name + SKILLS_DIR
path. Drops "-helper" suffix per the v2 rename principle (all skills
implicitly help).
Adds Phase 0 grill-me intake (3 forcing questions) before the
reconnaissance search, and restructures the existing post-Phase-2
checkpoint as a second grill-me moment with forcing options instead
of free-text:
Phase 0 Q1 research-question specificity — refuses vague answers
Phase 0 Q2 framework hint forcing choice (PICO / SPIDER /
Decomposition / hybrid / "you pick") — PICO default, skill
surfaces its own recommendation after recon search
Phase 0 Q3 tentative depth (5/10/20) — re-confirmed at the post-
Phase-2 checkpoint when user has seen the framework breakdown
The post-Phase-2 checkpoint adds forcing sub-area adjustment options
("proceed", "add sub-area on X", "remove and replace Y with Z",
"restart with different framework") and refuses to start Phase 3
without an explicit choice. Plan-tier ceiling surfaced so user can
calibrate depth realistically.
Trigger phrases lead with "litreview on [topic]" + "literature review
on [topic]" while retaining all prior phrases. Validation checklist
adds grill-me discipline requirements for both intake moments.
https://claude.ai/code/session_01FEUmeuYhmnxVFq7EZM8ZSw
Renames the mega prompt file and updates frontmatter name + SKILLS_DIR
path. NIH-only scope and full 5-facet Consensus + RePORTER POST +
NOSI fetch + 9-section DOCX workflow all preserved unchanged.
Adds Phase 1 as a 6-question grill-me intake replacing the previous
"research idea + 3 multi-select questions" pattern. Each question is
forcing, one at a time, dependency-ordered, with explicit "why I'm
asking":
Q1 research idea — refuses vague answers ("AI for healthcare");
5 Consensus facets depend on precision
Q2 career stage — forcing choice across 5 NIH stages (predoc /
postdoc / early / independent / senior); filters mechanism set
Q3 preliminary data status — forcing choice across 4 levels (none /
pilot / strong / validated); drives mechanism budget
Q4 environment — forcing choice across 4 institution types; affects
scope realism and R15 eligibility
Q5 submission posture — new / resubmission / exploring; resubmission
triggers reviewer-response section in DOCX
Q6 known institute targets — accepts "no preference" as common case;
otherwise validates user hypothesis against RePORTER tally
Stop condition: 6 questions max, no re-opening intake after Phase 2A
starts. Trigger phrases gain "grants for [topic]" while retaining all
prior phrases.
https://claude.ai/code/session_01FEUmeuYhmnxVFq7EZM8ZSw
Renames the mega prompt file and updates frontmatter name + SKILLS_DIR
path. Updates all companion-skill references from email-setup to
inbox-setup throughout the spec.
Inbox-triage is intentionally LIGHT-INTAKE — it runs on a recurring
cadence with preferences pre-baked into the knowledge base from
inbox-setup. The grill-me discipline here asks ONLY the override
questions that matter THIS run:
Q1 (optional) — search window override, asked only when invocation
is outside normal cadence (e.g., on-demand run after long break
wants 24h window; quick check wants 2h)
Q2 (optional) — category skip override, asked only when user invokes
with skip intent ("just opportunities", "skip newsletters")
Stop condition: max 2 questions; default invocations skip both and
run with KB-default preferences. Validation checklist requires the
light-intake discipline to be stated explicitly so future generators
don't add intake questions that break the recurring-execution flow.
Knowledge-base file contract with inbox-setup remains identical:
core required email-taxonomy.md + email-patterns.md, optional
evaluation-framework.md + rate-card.md, evolving blocklist.md +
tracker.md, Email/triage-log/ directory for per-run logs.
Trigger phrases gain "inbox triage" while retaining all prior phrases.
https://claude.ai/code/session_01FEUmeuYhmnxVFq7EZM8ZSw
Renames the mega prompt file and updates frontmatter name + SKILLS_DIR
path. Updates the companion-skill reference from email-triage to
inbox-triage (paired-skill file contract still matches verbatim — KB
files at \${WORKSPACE}/Email/ unchanged: email-taxonomy.md,
email-patterns.md, evaluation-framework.md, rate-card.md, blocklist.md,
tracker.md, triage-log/).
This is the heaviest grill-me retrofit in the productivity pack
because inbox-setup is the most interview-dense skill. Restructures
all 8 sections to per-question (S{n}.Q{m}) format:
Section 1 (big picture): 6 grill-me questions
Section 2 (categories): 3 questions including yes/mostly/no taxonomy
verification on the proposed list
Section 3 (voice): 6 questions plus the critical S3.SAMPLES
real-sent-email collection (highest-quality voice input)
Section 4 (evaluation framework, conditional): 6 questions, skipped
entirely if S1 didn't surface opportunity emails
Section 5 (blocklist): 3 questions
Section 6 (current state): 3 questions
Section 7 (report preferences): 3 questions
Every question carries explicit "why I'm asking". Forcing format on
multi-choice questions. Section boundaries don't relax the one-at-a-
time rule — drops "Conversational pacing" anti-pattern row in favor
of the harder grill-me discipline principle.
Trigger phrases gain "set up my inbox" + "configure inbox triage"
while retaining all prior email-* phrases. Handoff message at end
of Section 8 references inbox-triage by new name.
https://claude.ai/code/session_01FEUmeuYhmnxVFq7EZM8ZSw
Renames the mega prompt file and updates frontmatter name + SKILLS_DIR
path. Capture is intentionally fast-to-action — when the user dumps,
the skill organizes immediately. No upfront intake.
Grill-me retrofit takes the form of a single MID-ORGANIZATION clarifier
asked at most once per dump, only when a genuine ambiguity surfaces
between task and project for a single item. Pattern: identify the most
ambiguous item, ask one forcing question, commit and continue. Multiple
clarifying questions break the dump-and-organize flow that makes the
skill useful — so the spec hard-caps at 1.
Skipping the clarifier entirely is the common case when the dump is
unambiguous.
Trigger phrases updated to lead with "capture this" while retaining
all prior phrases ("brain dump", "let me dump some ideas",
"here's everything on my mind", etc.) as additional triggers.
Frontmatter description explicitly states the fast-to-action discipline
and max-1-clarifier rule.
https://claude.ai/code/session_01FEUmeuYhmnxVFq7EZM8ZSw
Renames the mega prompt file and updates frontmatter name + SKILLS_DIR
path. Output filename shortens from <name>-landing.html to <name>.html
since the OUTPUT_DIR (./landing-pages/ default) already encodes the
context.
Adds Phase 0 grill-me intake (4 forcing questions, one at a time):
Q1 product + 1-2 sentence elevator pitch — refuses vague answers
("app for productivity") and pushes for who-it's-for specificity
Q2 audience register forcing choice (technical buyers / business
buyers / consumers / internal) — dictates copy register, jargon
level, social-proof, CTA framing
Q3 brand overrides (HEX colors + fonts) or "default" — accepts
partial overrides; algorithmic derivation when only primary given
Q4 tone forcing choice (professional / playful / authoritative /
minimal) — prevents tonal whiplash across sections
Recommended defaults per audience baked into Q4 guidance. Stop
condition: max 4 questions; no follow-ups during generation.
Trigger phrases updated to lead with "landing for X" while retaining
all prior phrases. Validation checklist adds grill-me requirements +
new SKILLS_DIR/landing path.
https://claude.ai/code/session_01FEUmeuYhmnxVFq7EZM8ZSw
Name unchanged (brand specificity is the value — drops the LM suffix
would collide with generic notebook intent). Retrofits action-routing
intake as grill-me forcing questions, one at a time, dependency-ordered:
Q1 action commitment (read/extract, add source, generate Studio
output, or create new notebook) — forcing choice; refuses to
start without action declared
Q2 notebook identity (name or URL; "create new" branch asks title
instead)
Q3 action-specific parameter — branches per Q1:
- read: question to ask the notebook
- add source: source type forcing choice across 5 options
- Studio: which output type
- create new: initial sources
Q4 Studio custom prompt detail (angle / audience / length) —
mandatory for action 3, skipped otherwise. Carries 3 concrete
example prompts to model the level of specificity needed.
Stop condition: most invocations exit after Q3; only Studio generation
runs all 4 questions. Validation checklist adds grill-me requirements
including the Q4-mandatory-for-Studio rule and Q1-action-refusal.
https://claude.ai/code/session_01FEUmeuYhmnxVFq7EZM8ZSw
Renames the mega prompt file and updates frontmatter name + output
target path. Skill purpose unchanged: pure-reasoning metacognitive
reflection across the 5-dimension framework (macro, gap, reflective
inquiry, bias check, contextual alignment).
Grill-me retrofit is intentionally minimal here — reflect is a low-
intake skill by design. Adds an OPTIONAL Q1 clarifier (goal / approach
/ assumptions / all-of-the-above) asked only when the invocation
context is too thin to reassess from. Normal invocations mid-rich-
conversation skip the question entirely and run the 5-dimension
analysis directly. Stop condition: max 1 question; default = 0.
Updates trigger phrases to lead with "reflect" while retaining all
prior phrases ("take a step back", "step back", "zoom out", etc.)
as additional triggers so muscle-memory invocations still route.
Validation checklist updated to require the optional-question
discipline and the new SKILLS_DIR path.
https://claude.ai/code/session_01FEUmeuYhmnxVFq7EZM8ZSw
Renames the mega prompt file and updates frontmatter name +
SKILLS_DIR + RESEARCH_DIR output paths from last-30-days/ to pulse/.
Adds Phase 0 grill-me intake (max 4 forcing questions, one at a time,
dependency-ordered) ahead of the existing parallel-search phases:
Q1 topic specificity — refuses vague answers ("AI", "tech"); pushes
back with examples
Q2 angle forcing choice across 5 options (trend / sentiment /
problems / opportunities / comparison) — dictates source weighting
Q3 time window choice (7/14/30/60/90 days, default 30)
Q4 platform-scope skip (asked only when Q1 + Q2 suggest some
platforms are off-target)
Updates trigger phrases to lead with "pulse on [topic]" and adds
"take the pulse of [topic]" / "trending: [topic]" / "current
conversation about [topic]". Output header changes to "[TOPIC] —
Pulse (Last [N] Days)" with angle declared in the dated subheader.
Adds vague-topic refusal as the first failure-mode row. Validation
checklist gains grill-me requirements (one-at-a-time, why-I'm-asking
per question, Q1 vagueness rejection, Q2 forcing format).
https://claude.ai/code/session_01FEUmeuYhmnxVFq7EZM8ZSw
Adds the research skill mega prompt — the default entry point for the
research domain. Implements Architecture C (hybrid router + fallback):
deterministic classification of the user's question, delegation to a
specialist when confidence is high (≥2 signal matches), and a full
plan-decompose-search-synthesize-cite fallback workflow when no
specialist fits.
Specialist registry: pulse (reddit/hn/x/buzz/sentiment), grants (NIH/
R01/RePORTER/NOSI), litreview (literature review/PICO/SPIDER/meta-
analysis), syllabus (course outline/reading list), patent (prior art/
FTO/IP landscape), dossier (entity research/due diligence/meeting
prep). Each has documented routing signals so classification is
predictable and learnable.
Deterministic classification (not LLM-reasoned): documented as concrete
pseudo-code. Per specialist, count matched signal phrases; route to
argmax if ≥2 signals; route to single-match specialist at exactly 1
signal; otherwise ask Q3 domain disambiguation. Routing decision is
ALWAYS surfaced before execution so users can override.
Grill-me intake: minimal by design (max 4 questions, most invocations
exit after 2). Q1 research-question specificity (refuses vague), Q2
output preference (chat brief vs .docx), Q3 domain disambiguation
asked only when classification ambiguous, Q4 fallback scope only when
Q3 picked "none of the above". Routes fast; doesn't slow delegation.
Fallback workflow (8 steps): decompose into 3-5 sub-questions, source-
select per sub-question, sequential 1 q/sec search, fetch-and-extract,
per-sub-question synthesis with inline citations, cross-cutting
patterns, format-honoring output (markdown brief default or DOCX),
three-count audit log with reliability tiers per source.
Inherits research-pack conventions: source discipline, three-count
tracking, retry-once-after-3s, stop-after-3-failures. 10 documented
anti-patterns including the keystone: never LLM-reason classification,
never silent-delegate, never run fallback when a specialist fits.
https://claude.ai/code/session_01FEUmeuYhmnxVFq7EZM8ZSw
Adds the dossier skill mega prompt — fourth in the research pack and the
second new skill in the v2 expansion. Non-generic by design: refuses to
be "tell me about Microsoft" and forces the user to state their
hypothesis upfront via mandatory Q4 in the grill-me intake. The dossier
tests the hypothesis rather than confirms it, allocating at least 30%
of search budget to disconfirming queries.
Grill-me intake (max 6 questions, one at a time, dependency-ordered):
subject identity + disambiguating identifier (Q1), subject type forcing
choice (Q2), purpose forcing choice across 8 options (Q3), MANDATORY
hypothesis statement with push-back protocol if refused (Q4 — the
non-generic anchor), depth choice (Q5), sensitivity exclusions for
journalism + personal vetting only (Q6).
Subject-type source matrices: person (LinkedIn, Twitter, GitHub,
Scholar, news), company (official site, SEC EDGAR free API, Crunchbase
free tier, news, GitHub for tech, Glassdoor sentiment, LinkedIn company
page), nonprofit (ProPublica Nonprofit Explorer Form 990s + official),
government org (.gov + ProPublica). Optional BYOK MCPs (LinkedIn,
Crunchbase, Apollo, Pitchbook, SimilarWeb) flagged in audit log.
Hypothesis-driven search discipline: every Phase 4 query classified as
supporting or disconfirming. ≥30% disconfirming budget mandatory to
prevent confirmation bias.
DOCX output (9 sections): executive summary with verdict on hypothesis
(SUPPORTED / PARTIALLY SUPPORTED / DISPROVEN / INCONCLUSIVE), identity
facts, hypothesis test with explicit supporting + disconfirming
evidence, 12-month activity timeline, network signals, reputation
signals, red flags tiered (primary/secondary/tertiary source
reliability), 3–5 finding-tied conversation hooks (not generic), source
provenance + audit log. Inherits research-pack conventions: sequential
execution, three-count tracking, retry-once-after-3s, stop-after-3-
failures, source discipline, sensitivity-exclusion honored from Q6.
https://claude.ai/code/session_01FEUmeuYhmnxVFq7EZM8ZSw
Adds the patent skill mega prompt — third in the research pack and the
first new skill in the v2 expansion. Non-generic by design: refuses to
be "patent help" and commits to one of five sub-use-cases via the
grill-me intake before any search runs. Each sub-use-case dictates a
distinct search strategy:
- Novelty search: narrow + claims-text focused
- Freedom-to-operate: broad + active patents only, jurisdiction-filtered
- Competitive landscape: breadth + filer tally + CPC trends
- Acquisition diligence: assignee-specific + assignment-chain
- Litigation prior-art: target-patent-anchored + pre-priority art
Grill-me intake (max 6 questions, one at a time, dependency-ordered):
invention description (refuses generic answers), sub-use-case commitment
(forcing choice), jurisdictions (Q2-dependent), known prior art anchor,
risk tolerance, attorney-status disclaimer (only for novelty/FTO).
Search sources: Google Patents (workhorse), Espacenet (global), USPTO
PPS (US), Lens.org BYOK (citation graph). CPC/IPC classification
follow-up query mandatory after initial hits. Family resolution
deduplicates same-invention filings across jurisdictions.
DOCX output (8 sections): executive summary + verdict, closest prior art
with extracted independent claim 1, patent landscape, citation graph,
geographic coverage, FTO flags, sub-use-case-specific strategy + design-
around suggestions, audit log. Inherits research-pack conventions:
1 q/sec sequential, three-count tracking, retry-once-after-3s, stop-
after-3-failures, plan-tier detection, source discipline, attorney-
consultation disclaimer mandatory where Q2 has legal consequences.
Trademark, copyright, and trade-secret questions explicitly out of scope.
https://claude.ai/code/session_01FEUmeuYhmnxVFq7EZM8ZSw
Adds the final mega prompt in the research pack. Generates the
recommended-reading-list skill: parses a course syllabus (PDF / DOCX /
text / pasted / image), extracts topics + learning outcomes (inferring
3-5 outcomes if missing), groups topics into 6-12 sections, runs 1-2
targeted Consensus searches per section with applied-domain weaving
(e.g., "enzyme kinetics food processing applications", not just "enzyme
kinetics"), selects 1-3 papers per section (15-25 total), and writes
plain-language summaries + Bloom-higher-order discussion questions tied
to specific learning outcomes.
Uses a bundled JavaScript helper at scripts/generate_reading_list.js
for DOCX assembly: takes JSON input + output path CLI args, produces a
title page, intro with consensus.app link, boxed learning-outcomes
section, numbered hyperlinked papers per section heading with summary
+ discussion-question lines, and a footer. JSON schema documented in
the skill.
Inherits the same research-pack conventions as 08 and 09: 1 query/sec
sequential execution, plan-tier awareness (3/search free, more on Pro),
strict source discipline (only cite this session's Consensus results),
three-count tracking surfaced in chat audit summary, retry-once-after-
3s, stop-after-3-failures, group-and-confirm before searching, full
untruncated ExternalHyperlink URLs, and 7 documented failure modes.
https://claude.ai/code/session_01FEUmeuYhmnxVFq7EZM8ZSw
Adds the mega prompt that generates the literature-review-helper skill —
research pack #2. Produces a "launching pad" orientation document
(not a finished review) via one broad Consensus reconnaissance search,
PICO-default framework selection with SPIDER / Decomposition / hybrid
fallbacks, an interactive checkpoint (framework breakdown table + depth
selector), and a configurable search budget: Quick (5) / Standard (10) /
Deep (20) — each fully allocated with explicit reasoning across
sub-area, review-article, era-gated, and follow-up searches.
Adds cross-search intelligence (repeat-hit papers as foundational
signal, recurring authors as dominant groups, citations-per-year as
seminal-work proxy) and an 8-section DOCX (topic overview, priority
reading order, field timeline, sub-area guides with Boolean strings,
key research groups, open gaps with why-they-matter, hyperlinked
bibliography, audit log).
Inherits the research-pack conventions established by skill 08:
1 query/sec sequential Consensus execution, plan-tier detection from
first response, three-count tracking (searches / unique papers / cited),
retry-once-after-3s, stop-after-3-failures, strict source discipline,
and standard docx library patterns (LevelFormat.BULLET, ExternalHyperlink
with full untruncated URLs, dual-width tables, post-save validation).
https://claude.ai/code/session_01FEUmeuYhmnxVFq7EZM8ZSw
Adds the mega prompt that generates the NIH grant-finder skill — first
of the research pack. Combines a 5-facet Consensus positioning analysis
(established / stakes / current approaches / adjacent methods / gaps)
with RePORTER POST queries (narrow AND + broad OR) executed via
bash_tool + curl, NOSI fetches via web_fetch, and a 9-section editable
DOCX output (executive summary, positioning with gap quotes + draft
Significance/Innovation, target institutes, grant opportunities with
hyperlinked FOAs, funded overlap, study sections, strategic recs +
mandatory program officer rec + submission timeline, references, audit
log).
Locks in the research-pack shared conventions: sequential 1 query/sec
Consensus execution, plan-tier detection via "Found N, showing top M",
strict source discipline (only cite this session's tool results, label
training-knowledge as reference), three-count tracking (sent / shown /
cited), retry-once-after-3s policy, stop-after-3-consecutive-failures,
dynamic fiscal-year window, scope+career-stage mechanism matching, and
embedded mechanism + submission-timeline reference tables. Scoped
NIH-only with non-NIH funders flagged out at intake.
https://claude.ai/code/session_01FEUmeuYhmnxVFq7EZM8ZSw
Adds the mega prompt that generates the email-triage recurring-execution
skill — the second half of the paired email pack. Knowledge-base file
contracts match the 06 email-setup output verbatim: core required
(email-taxonomy.md, email-patterns.md), optional core (evaluation-
framework.md, rate-card.md), evolving read+update (blocklist.md,
tracker.md), plus the Email/triage-log/ directory for per-run logs.
Specifies the 10 execution steps: 9-hour-overlap search window, two-
query email search (primary + starred-unread), taxonomy classification
with skip-reads on lowest priority, conditional sender research, four-
category recommendations (TAKE/CONSIDER/PASS/FLAG), draft creation
honoring patterns.md voice, format-honoring report delivery with HTML
inline-CSS for Gmail, KB updates + observed-override learning loop
after 5+ runs, internal triage log, and empty-inbox handling that still
surfaces overdue tracker items.
Hard rule stated prominently in multiple places: DRAFTS ONLY — NEVER
SEND. Provider-agnostic adapter pattern (Gmail MCP, Outlook MCP, IMAP),
fail-fast on missing KB (direct user to email-setup), privacy boundary
(no credentials in KB), trigger phrases, anti-patterns, 7+ failure
modes, and a validation checklist.
https://claude.ai/code/session_01FEUmeuYhmnxVFq7EZM8ZSw
Adds the mega prompt that generates the email-setup interview skill —
the first half of the paired email pack. Specifies the exact knowledge-
base file contract at \${WORKSPACE}/Email/ (email-taxonomy.md,
email-patterns.md, optional evaluation-framework.md + rate-card.md,
blocklist.md, tracker.md, triage-log/) that the companion email-triage
skill must consume verbatim.
Documents the 8 interview sections (big picture, categories, voice via
3-5 real sent-email samples, conditional evaluation framework, blocklist
seeding, current state, report preferences, handoff), conversational
pacing discipline (no batched questions, explain why each one matters),
modular skip-logic for non-applicable sections (e.g., no rate card if
no pricing), privacy boundary (never persist credentials), and re-run
safety (per-file replace/merge/skip prompt).
https://claude.ai/code/session_01FEUmeuYhmnxVFq7EZM8ZSw
Adds the mega prompt that generates the brain-dump capture-and-organize
skill. Specifies the four-section output (Projects & Ideas with embedded
questions/decisions, flat Tasks list, Connections grounded in real
workspace inspection, concrete How-I-Can-Help offers ending with a
directive question), and the five operating principles (capture-all,
complexity-matching, voice preservation, ambiguity flagging, approval-
gate before any non-organizing action).
Documents context-aware workspace detection (CLI Glob/Grep, web project
files, connected MCPs, or explicit inaccessibility statement), strict
no-fabrication rule for Connections, six failure modes including short
dumps and conflicts, explicit + implicit trigger phrases, anti-patterns
(no corporate-ifying user voice, no forced 4-section structure on small
dumps), and a validation checklist.
https://claude.ai/code/session_01FEUmeuYhmnxVFq7EZM8ZSw
Adds the mega prompt that generates the landing-page skill: premium
single-file HTML output with inline CSS/JS, Inter + GSAP via CDN only.
Specifies three required sections (hero, features, closing CTA), five
animation patterns (GSAP entrance with gsap.set() FOUC guard, mouse
parallax with two depth layers, ScrollTrigger card reveals, CSS-keyframe
floating shapes, scroll indicator), default dark-navy + teal palette as
CSS custom properties with explicit override pattern, responsive
breakpoints (900px/580px), and accessibility minimums.
Documents configurable OUTPUT_DIR variable, kebab-case filename derived
from product name, both CLI (write to disk) and web (HTML artifact)
delivery modes, content-fallback strategy for sparse inputs, six failure
modes, trigger phrases, anti-patterns, and a validation checklist.
https://claude.ai/code/session_01FEUmeuYhmnxVFq7EZM8ZSw
Adds the mega prompt that generates the NotebookLM browser-automation
skill. Specifies the four core actions (read/extract, add sources,
generate Studio outputs, create new notebook), tool-agnostic browser
automation language, screenshot-first + find-before-click discipline,
and an explicit async-wait rule: Studio generations (especially Audio
Overview) must not block the session.
Documents login-wall handling (stop, never auto-login), synthesized-
content-as-source pattern, mandatory custom Studio prompts (with ≥ 4
concrete examples required), portability constraints (CLI/computer-use
or Chrome extension only — fails fast on web), trigger phrases, anti-
patterns, 7+ failure modes, and a validation checklist.
https://claude.ai/code/session_01FEUmeuYhmnxVFq7EZM8ZSw
Adds the mega prompt that generates the take-a-step-back metacognitive
reflection skill. Specifies the 5-dimension framework (macro, gap,
reflective inquiry, bias check, contextual alignment), explicit + implicit
invocation signals, honest-output discipline (don't manufacture problems
when on track), conversation re-read from the top, and a flowing-prose
output format with a mandatory closing directional recommendation
(continue / pivot / pause).
Documents trigger phrases, the 5 cognitive biases to check, error
handling for short conversations and solid directions, anti-patterns,
and a validation checklist. Skill is pure-reasoning and fully portable
across CLI and web.
https://claude.ai/code/session_01FEUmeuYhmnxVFq7EZM8ZSw
Adds the mega prompt that generates the last-30-days multi-source
research skill. Specifies parallel execution across Reddit, Hacker News,
web search, and optional X/Twitter phases; configurable time window
(7d/14d/30d/60d/90d); graceful per-source degradation; citation
discipline; and a fixed output markdown structure (TL;DR, per-source
findings, cross-platform patterns, takeaways, content angles).
Includes trigger phrases, frontmatter spec, anti-patterns, portability
notice (CLI vs web — X phase skipped in web), failure-mode table, and a
validation checklist to run before delivery.
https://claude.ai/code/session_01FEUmeuYhmnxVFq7EZM8ZSw
Scaffolds the megaprompts/ directory with the library README that
describes the 10-skill mega-prompt set, quality standards, pack
groupings, portability matrix, and customization variables. Individual
mega prompt files (00-10) will follow in subsequent commits.
https://claude.ai/code/session_01FEUmeuYhmnxVFq7EZM8ZSw
generate-docs.py re-created these dual-publish duplicates that PR #644
removed. The v2.5.7 dedup logic in generate-docs.py covers the engineering/
domain but doesn't catch the ra-qm-team pattern. Tracked as separate
generator improvement (v2.6.x candidate).
https://claude.ai/code/session_01VFreMf7XLBqMgjsrG4wSYe
Ran the /update-docs pipeline post-v2.6.1 release. Most of the work was
verification (docs already in sync from prior PRs #644, #649). Two real
issues surfaced and fixed:
1. Codex sync bug (the headline fix)
- scripts/sync-codex-skills.py used iterdir() which is single-level only
- Missed the engineering/<plugin>/skills/<name>/SKILL.md pattern used by
4 Pocock plugins + many other standalone plugins restructured since
PR #593
- Added Pattern 3 discovery: when <domain>/<plugin>/ contains a skills/
subdir with <name>/SKILL.md, recurse one level
- Impact: Codex index 195 → 289 skills (+94 previously-hidden skills)
- Gemini sync was already correct (uses recursive rglob)
- OpenClaw was already correct (uses recursive find)
2. Stale skill counts in 2 user-facing docs
- README.md: 268 → 272 (3 occurrences: tagline + badge + skills overview)
- docs/getting-started.md: 246 → 272 (2 occurrences: meta description + FAQ)
- All other files (CLAUDE.md, docs/index.md, mkdocs.yml site_description,
marketplace.json) were already at 272 (refreshed in PRs #644 + #649)
Other regenerations (no source changes — auto-updated from latest content):
- docs/skills/engineering/*.md regenerated (picks up v2.6.1 description fixes)
- docs/agents/*.md regenerated (no agent changes)
- docs/commands/*.md regenerated (no command changes)
- .codex/skills-index.json + 94 new symlinks (mostly Pocock + plugin-pattern
skills that should have been there since PR #593)
Verification:
- All 5 user-facing docs (CLAUDE.md, README.md, docs/index.md,
docs/getting-started.md, mkdocs.yml) show "272 skills" consistently
- marketplace.json: v2.6.1, 43 plugins, 0 broken source paths
- mkdocs build: 371 pages (280 skills + 58 agents + 33 commands), clean
in 17.31s, no errors or new warnings
- audit_skills.py: runs cleanly against 298 real skills
No production code changes outside the Codex sync fix. This is a docs +
tooling sweep, not a feature release.
https://claude.ai/code/session_01VFreMf7XLBqMgjsrG4wSYe
Follow-up to v2.6.0. Uses the audit_skills.py tool (shipped in #646) to identify
real bugs vs validator false-positives across 298 repo skills, then fixes both.
Three coordinated changes:
1. Validator trigger pattern expansion (write-a-skill internal tools)
- Old: only "Use when", "Use for", "Invoke when", "Trigger when" recognized
- New: + "Use before/during/after/while", "Invoke before/after", "Apply when",
"Run when/before"
- Why: 11 legacy skills had semantically-valid triggers (e.g., gdpr-audit-prep
says "Use before annual GDPR review") that the v2.6.0 validator wrongly
flagged as missing. Natural English variants now accepted.
- Impact: 30 skills reclassified from FAIL → WARN/PASS automatically.
- Karpathy complexity: 100/100 (PASS) on both modified validators.
2. Ten placeholder descriptions fixed in engineering/skills/
The audit revealed 21 skills (~7% of repo) with broken descriptions that
were literally just the skill name (e.g., description: "Migration Architect").
These were real bugs from a v2.0.0 batch import where the description field
was never filled in. Top-10 fixed in this PR (POWERFUL-tier, high-visibility):
- migration-architect: zero-downtime migration planning + rollback strategy
- dependency-auditor: vulnerabilities + license + safe-upgrade audit
- codebase-onboarding: codebase analysis + onboarding doc generation
- ci-cd-pipeline-builder: pragmatic CI/CD from project stack signals
- mcp-server-builder: MCP servers from OpenAPI contracts (Python + TS)
- observability-designer: metrics + logs + traces + SLI/SLO design
- api-design-reviewer: REST design review + breaking-change detection
- performance-profiler: Node/Python/Go profiling + flamegraphs + load tests
- changelog-generator: Conventional Commits → release notes automation
- runbook-generator: operational runbooks from service name + templates
Each new description: ≤1024 chars, third person, action verb in first
sentence, "Use when ..." trigger in second sentence per Matt Pocock's rule.
Remaining 11 placeholder descriptions tracked for v2.6.2.
3. Quality-gates reference updated (Option C: legacy advisory)
quality_gates_for_skills.md now explicitly documents the binding-for-new
vs advisory-for-legacy split. The 6-item checklist remains BLOCKING for
post-v2.6.0 skills and ADVISORY for the 298 legacy SKILL.md files. Audit
report drift is tracked separately; PASS count is the metric to grow, not
a force-march-to-Friday deadline.
Aggregate audit improvement (against the 298 real-skill cohort):
- PASS: 4 (1%) → 7 (2%)
- WARN: 111 (37%) → 134 (45%)
- FAIL: 183 (61%) → 157 (53%)
- "Missing trigger" failures: 119 (39%) → 79 (26%)
26 skills total lifted from FAIL → WARN/PASS in this PR. Highest-leverage
fix per hour of any v2.6.x cleanup since the v2.6.0 release.
https://claude.ai/code/session_01VFreMf7XLBqMgjsrG4wSYe
Adds a small stdlib-only orchestration script that runs the
skill_review_checklist_runner.py (shipped in v2.6.0) across every SKILL.md
in the repo and aggregates results.
Output:
- Total skills audited (PASS / WARN / FAIL / ERROR counts + percentages)
- Failure breakdown by rule (which of Matt's 6 checklist items fail most)
- Top-10 worst offenders (skill folder + specific failing rules)
Excludes auto-generated tool-specific symlinks (.gemini, .codex, .cursor,
.cline, /site/, /.git/) and template fixtures (templates/, assets/sample-skill).
Use case: periodic audit of skill-library hygiene. Re-run after each batch
of new skills to catch drift early. Produced the punch list that informed
the v2.6.1 cleanup planning (40% of repo skills miss "Use when" triggers;
88% exceed Matt's 100-line ceiling — both flagged for triage).
Stdlib-only. No external dependencies. Runs in ~30s on a 298-skill repo.
https://claude.ai/code/session_01VFreMf7XLBqMgjsrG4wSYe
test_skill_integrity.py::TestSkillMdHasH1 requires every SKILL.md to have an
H1 heading. Matt Pocock's originals didn't have H1s (just frontmatter + body)
so the verbatim preservation tripped this test on dev's CI.
Adding minimal H1 headings ("Caveman Mode", "Grill Me", "Handoff") without
modifying Matt's body content. Voice + workflow + rules preserved exactly.
Full pytest suite: 1921 passed (was 3 failed).
Write-a-skill review checklist: still PASS on all 3 SKILL.md (69/58/41 lines,
all under Matt's 100-line ceiling).
https://claude.ai/code/session_01VFreMf7XLBqMgjsrG4wSYe
Stream B PR 1 of 2 — the skill-author skill that gives us the meta-tool to
build the rest of Matt Pocock's productivity skills (caveman, grill-me, handoff)
with consistent quality gates.
Derived from Matt Pocock's write-a-skill (MIT-licensed):
https://github.com/mattpocock/skills/tree/main/skills/productivity/write-a-skill
Matt's SKILL.md content + 3-phase workflow (Gather -> Draft -> Review) preserved
verbatim per MIT license. Attribution: README.md + plugin.json description +
SKILL.md frontmatter metadata + every file footer cites Matt + links to original.
Additions on top of Matt's original (the "hybrid voice" approach):
3 stdlib Python validation tools:
- skill_description_validator.py: 5-check verdict per Matt's 4 format rules
(description present, <=1024 chars, third person, "Use when" trigger, action
verb in first sentence). Action-verb vocabulary extracted as module constant.
- skill_structure_validator.py: 6-check verdict (SKILL.md present, line count,
references when split needed, one-level-deep, no circular refs, scripts/
folder note). Refactored to extract _list_md_in_subdir + _collect_links_for_file
helpers to keep nesting depth <= 4 per karpathy-coder.
- skill_review_checklist_runner.py: combined verdict running all 6 items from
Matt's review checklist. Refactored _find_nested_md helper for nesting.
4 in-depth references (each citing 7-8 authoritative sources):
- companion_tooling.md: tool catalogue + cs-* wrapper rationale
- progressive_disclosure_principles.md: 100-line ceiling + one-level-deep rule
with sources (Matt, Anthropic, Don Norman, Pirolli & Card, Maeda, DocOps)
- description_design_patterns.md: good vs bad description patterns with sources
(Matt, Anthropic, Garrett, Nielsen Norman, Karpathy)
- quality_gates_for_skills.md: the 6 mandatory gates + CI integration with
sources (Matt, Humble & Farley, Kim et al., Hyrum's Law)
cs-skill-author persona agent + /cs:write-a-skill slash command:
- Forcing-question interrogator pattern matching our cs-* convention
- 6 forcing questions mirroring Matt's 6 review-checklist items
- Routes to validators + karpathy-coder gate + attribution check
Karpathy-coder validation (full sweep):
- complexity_checker: 100/100 across all 3 tools (0 findings)
- assumption_linter: CLEAN on all 3 tools
- All 3 tools: PASS text + PASS JSON output
- All 4 references cite >= 7 authoritative sources (range 7-8)
Self-validation note: this skill's own SKILL.md is 141 lines (over Matt's
100-line ceiling) because it preserves Matt's full content verbatim + adds
attribution + tooling references. The structure_validator + checklist_runner
correctly WARN on this — documented in progressive_disclosure_principles.md
as the wrapper-derived exception. README.md absorbs the attribution overhead
so SKILL.md stays close to Matt's original size.
12 files, 1,689 insertions. License: MIT (matching Matt's upstream).
https://claude.ai/code/session_01VFreMf7XLBqMgjsrG4wSYe
Stream A Phase 1 — Plugin 2 of 3 (compliance OS MVP).
Three stdlib Python tools at the Article level:
- ai_system_risk_classifier.py: Article 5 prohibitions check, then
Article 6 + Annex III, then Article 6(3) carve-out test (overridden by
profiling), then Article 50 transparency, then minimal-risk default.
GPAI detection + Article 51 10^25 FLOPs systemic-risk threshold.
- conformity_assessment_planner.py: Article 43 Module A vs Module H routing
(biometrics -> Module H by default); Annex IV 8-item technical
documentation checklist with ISO 42001/27001 reuse map.
- ai_act_obligation_tracker.py: per-role (provider/deployer/importer/
distributor/auth-rep) obligation matrix with Article 113 phasing
deadlines (2 Feb 2025 / 2 Aug 2025 / 2 Aug 2026 / 2 Aug 2027).
Verified per Phase 1 success criteria: emotion-recognition-in-workplace
classified as prohibited (Article 5(1)(f)); CV-screening as high-risk
(Annex III §4); chatbot as limited-risk (Article 50); spam filter as
minimal-risk.
Four references each citing 5+ authoritative sources (the Regulation,
EDPB Opinion 28/2024, Commission Feb 2025 Guidelines, ENISA, IAPP Tracker,
CEN-CENELEC JTC 21, BSI, NIST AI 600-1):
- eu_ai_act_titles.md: Titles I-XII Article-by-Article walkthrough
- high_risk_systems_annex_iii.md: 8 categories + Article 6(3) decision tree
- gpai_obligations.md: Articles 51-55 + Annex XI-XIII + Code of Practice
- cross_framework_mapping_ai_act.md: AI Act <-> ISO 42001 <-> NIST AI RMF
<-> GDPR cross-walk with Article 17(1) item-by-item mapping
Dual-published: standalone plugin (ra-qm-team/compliance-team-eu-ai-act/) +
mirror under ra-qm-team/skills/eu-ai-act-specialist/.
Karpathy gate: complexity_checker 100/100 (0 findings).
https://claude.ai/code/session_01VFreMf7XLBqMgjsrG4wSYe
Two small polish tasks ahead of any future Pages deploy.
1. Add /cs:* command nav entries (22 new entries)
The 21 c-level-agents-* sub-skill pages now exist (since #632) but weren't
surfaced in mkdocs.yml sidebar nav. Added a "Founder-Mode Commands" nested
section under C-Level Advisory with:
- c-level-agents index
- 10 forcing-question reviews (/cs:cfo-review through /cs:vpe-review)
- 5 strategic sprint pipeline commands (brief/boardroom/decide/execute/post-mortem)
- 4 meta+safety commands (founder-mode/onboard/cross-eval/freeze)
- /cs:office-hours
2. Clear 33 mkdocs INFO warnings
mkdocs build was emitting 33 INFO-level warnings during the docs deploy.
Pre-existing noise; not regressions. Three categories:
a) 27 unrecognized-link warnings: relative links like `[Skills](skills/)`
that mkdocs flags because the path doesn't end in .md. Fix: added
explicit `index.md` suffix in 3 manual doc files.
- docs/index.md: 15 links
- docs/skills/index.md: 11 links
- docs/custom-gpts.md: 1 link
b) 2 anchor warnings in scrum-master TOC: links pointed to
`#analysis-tools--usage` and `#key-metrics--targets` (double hyphen
from ampersand) but mkdocs Material's slugify produces single-hyphen
slugs. Fix: changed to `#analysis-tools-usage` and `#key-metrics-targets`.
c) 4 anchor warnings in senior-computer-vision + senior-data-engineer TOCs:
links pointed to non-existent sections.
- senior-computer-vision: `#common-commands` TOC entry — no such heading
anywhere; removed the entry.
- senior-data-engineer: 3 sub-bullets pointing to `#workflow-1-...`,
`#workflow-2-...`, `#workflow-3-...` — no such headings (only a
parent `## Workflows`); removed the sub-bullets.
Verification:
- mkdocs build now emits 0 INFO warnings
- karpathy diff_surgeon: 0 findings on staged diff
- All 22 new nav entries verified to point to existing HTML pages
- generate-docs.py re-run picked up the upstream SKILL.md fixes; docs/skills/
now matches sources
10 files changed, +54/-39. After the next dev->main release, the Pages
deploy will have:
- Cleaner build output (no INFO noise)
- Fully discoverable /cs:* command pages in the sidebar nav
https://claude.ai/code/session_012WtZMm5NJHqkYoRqA9fHMN
generate-docs.py had a longstanding bug: the rendering loop only iterated
top-level skills and only rendered their direct children. Sub-skills whose
parent is a plugin folder (not a top-level skill at <domain>/skills/<name>/)
were silently dropped.
Affected plugins (standalone-only, no bundled mirror at <domain>/skills/):
- executive-mentor (1 index + 5 sub-skills)
- agenthub (1 index + 7 sub-skills)
- autoresearch-agent (1 index + 5 sub-skills)
- playwright-pro (1 index + 9 sub-skills)
- self-improving-agent (1 index + 5 sub-skills)
- c-level-agents (1 index + 17 sub-skills — the new /cs:* commands)
- llm-wiki (1 index + sub-skills)
- behuman, code-tour, demo-video, helm-chart-builder, karpathy-coder,
llm-cost-optimizer, prompt-governance, statistical-analyst, terraform-patterns,
data-quality-auditor, docker-development (single-skill plugins)
Total: 79 sub-skills + 12 plugin-index skills = 91 pages were being dropped.
(Some plugins like behuman are single-skill so only their index is dropped.)
The bug: rendering loop at line 414 only handled `for skill in top_level`,
then for each top-level found `children = [s for s in sub_skills if
s["parent"] == skill["name"]]`. Plugins where the SKILL.md lives only at
<plugin>/skills/<plugin>/SKILL.md don't appear in top_level (their detection
puts them in sub_skills with parent=themselves), so their children were
orphaned.
The fix: after the existing top-level loop, render orphan sub-skills grouped
by their plugin parent. Index sub-skill (named same as parent) renders as
<parent>.md; other children render as <parent>-<child>.md. This matches the
URL convention already in use (e.g., executive-mentor-challenge.md), so
existing SEO equity is preserved.
Result: skill pages generated 193 → 272 (+79 recovered). Total docs pages
280 → 359. mkdocs build succeeds.
Verified:
- All 12 previously-dropped plugins render their index page
- All 79 previously-dropped sub-skills render their detail pages
- URL convention preserved (executive-mentor-challenge.md, agenthub-board.md,
playwright-pro-coverage.md, etc.)
- karpathy diff_surgeon: 0 findings
After dev → main release: GitHub Pages redeploys with the recovered 79 pages.
The docs site finally has 1:1 correspondence between SKILL.md files in the
repo and pages on the site.
https://claude.ai/code/session_012WtZMm5NJHqkYoRqA9fHMN
PR #628 added 13 new cs-* agent nav entries to mkdocs.yml (cs-cfo-advisor,
cs-cmo-advisor, cs-cro-advisor, cs-cpo-advisor, cs-coo-advisor, cs-chro-advisor,
cs-ciso-advisor, cs-chief-of-staff, cs-general-counsel-advisor, cs-cdo-advisor,
cs-caio-advisor, cs-cco-advisor, cs-vpe-advisor) — but the agent pages they
pointed to didn't exist because generate-docs.py only walked /agents/, not
plugin-internal <domain>/<plugin>/agents/ folders.
Without this fix, those 13 nav links would 404 in production.
Extended generate-docs.py:
Pass 1 (existing): walk /agents/<domain>/*.md (28 canonical agents)
Pass 2 (new): walk <domain>/<plugin>/agents/*.md for each known DOMAINS root
Pass 2 dedupes against pass 1 by slug. Uses a SKILL_TO_AGENT_DOMAIN mapping
(c-level-advisor -> c-level, marketing-skill -> marketing, etc.) since skill
DOMAINS keys differ from AGENT_DOMAINS keys.
Result: 29 → 54 agent pages (+25 plugin-internal agents recovered):
c-level-advisor/c-level-agents/agents/ → 13 new cs-* agents (this session)
c-level-advisor/executive-mentor/agents/ → devils-advocate
engineering/llm-wiki/agents/ → wiki-linter, wiki-ingestor, wiki-librarian
engineering/agenthub/agents/ → hub-coordinator
engineering/autoresearch-agent/agents/ → experiment-runner
engineering-team/self-improving-agent/agents/ → memory-analyst, skill-extractor,
migration-planner, test-architect,
test-debugger
Verified:
- mkdocs build succeeds (357 → 380+ HTML pages)
- All 13 cs-* nav entries from PR #628 now resolve to valid HTML pages
- karpathy diff_surgeon: 0 findings
- Existing /agents/ canonical pass unaffected (dedupe by slug)
After dev → main release: GitHub Pages deploy will surface the recovered
25 agent pages. The 13 cs-* nav entries from the v2.5.7 release will no
longer 404.
https://claude.ai/code/session_012WtZMm5NJHqkYoRqA9fHMN
Pure-cleanup PR addressing carry-over items deferred across PRs #618-#626 per
karpathy principle #3 (surgical scope — no unrelated cleanups inside scoped
feature PRs).
Voice specs added to persona-voices.md (3 missing entries):
- cs-ceo-advisor — The Strategic Translator (tree-of-thought reasoning;
refuses to debate tactics until the strategic question is named)
- cs-cto-advisor — The Architecture-First Pragmatist (ReAct reasoning;
treats every architecture decision as a 3-year commitment)
- cs-general-counsel-advisor — The Risk-Paranoid Lawyer (Not Your Lawyer);
carry-over from v2.5.1
All three agents existed but were never added to the persona reference. The
voice catalog now matches the cs-* agent set 1:1.
Broken paths fixed in 2 pre-existing agent files:
- agents/c-level/cs-ceo-advisor.md: 32 path corrections from
'../../c-level-advisor/ceo-advisor/' to '../../c-level-advisor/skills/ceo-advisor/'
(correct path; the bundled skill lives under skills/)
- agents/c-level/cs-cto-advisor.md: 25 path corrections from
'../../c-level-advisor/cto-advisor/' to '../../c-level-advisor/skills/cto-advisor/'
- YAML 'skills:' frontmatter field also corrected in both
Validation:
- karpathy-coder/diff_surgeon: 0 findings
- Verified target folders exist (c-level-advisor/skills/ceo-advisor/SKILL.md +
c-level-advisor/skills/cto-advisor/SKILL.md)
No skill/agent/command count changes; no manifest version bumps. This is a
pure-fix PR. CHANGELOG entry as v2.5.6.
https://claude.ai/code/session_012WtZMm5NJHqkYoRqA9fHMN
Per user request: register general-counsel-advisor, chief-data-officer-advisor,
and chief-ai-officer-advisor as standalone marketplace plugins (in addition to
their existing inclusion in the c-level-skills bundle). Matches the dual-publish
pattern established by feature-flags-architect / kubernetes-operator /
chaos-engineering / ship-gate / slo-architect in engineering.
Layout (per scripts/sync_skill_bundles.py spec):
Standalone: c-level-advisor/<skill>/skills/<skill>/{SKILL.md, scripts, references}
Bundled: c-level-advisor/skills/<skill>/{SKILL.md, scripts, references} (already existed)
The two locations are kept in sync by scripts/sync_skill_bundles.py;
`--check` passes for all 3 new standalone wrappers.
Added (per skill):
- <skill>/.claude-plugin/plugin.json (ClawHub-compliant 8 fields, "skills": "./skills")
- <skill>/README.md (notes dual-publish + sync mechanism)
- <skill>/skills/<skill>/SKILL.md (mirror)
- <skill>/skills/<skill>/scripts/* (mirror; 2 for GC, 3 each for CDO/CAIO)
- <skill>/skills/<skill>/references/* (mirror; 3 for GC, 4 each for CDO/CAIO)
marketplace.json: 3 new entries (category: leadership), now 37 plugins total.
Validation:
- scripts/check_plugin_json.py: OK on all 3 new plugin.json files (rejects bare "./")
- scripts/sync_skill_bundles.py --check: OK on all 3 standalone wrappers
- karpathy-coder/diff_surgeon: 0 findings
- All JSON validates
Discoverability gain: a founder who wants ONLY the General Counsel skill
(or only CDO or CAIO) can install it standalone, without pulling the full
31-skill c-level-skills bundle. The c-level-skills bundle continues to work
unchanged; this PR is purely additive.
Carried over (still not in scope for this PR):
- cs-general-counsel-advisor voice spec missing from persona-voices.md
- broken paths in pre-existing cs-ceo-advisor.md / cs-cto-advisor.md
- Phase 2 remainder (CCO-customer, VPE, CCO-comms)
https://claude.ai/code/session_012WtZMm5NJHqkYoRqA9fHMN
World-class, in-depth Chief AI Officer skill covering 4 specific decisions
(not a generic AI strategy survey):
1. Should we use an API, fine-tune, or build our own? (3-yr TCO + breakeven)
2. Is this AI use case high-risk under regulation? (EU AI Act + US state +
industry overlays with Article-level citations)
3. When do we switch from API to self-hosted, and at what cost? (2026
pricing + GPU economics + hidden costs)
4. What AI role do we hire next? (5-stage map + 9-role definition table)
Built under karpathy-coder discipline (third in a row):
- Assumptions surfaced upfront before code (principle 1)
- Each tool/reference covers ONE decision; rejected generic-survey scope (#2)
- Surgical changes only; no scope creep (#3)
- All 3 tools smoke-tested with embedded samples before commit (#4)
- karpathy/complexity_checker.py: 0 findings on 3 new tools
- karpathy/diff_surgeon.py: 0 findings on staged diff
3 stdlib Python tools with deterministic logic:
- model_buildvsbuy_calculator.py — Returns API/FINE_TUNE/BUILD recommendation,
3-year TCO across 6 paths, breakeven analysis. Balances economic crossover
with practical feasibility (data availability, ML team capacity, compliance).
Embedded sample (B2B customer support, 4M queries/mo) -> API recommended
despite breakeven crossed, because no fine-tune data + 1-engineer ML team.
- ai_risk_classifier.py — Returns EU AI Act tier (PROHIBITED/HIGH/LIMITED/
MINIMAL) with 7 Article citations + US state triggers (NYC LL 144, CO AI
Act, IL HB 53, CA SB 1001, IL BIPA) + industry overlays (FDA, CFPB, NAIC,
ECOA, Fed SR 11-7). Sample (AI hiring in EU+NY+CO+IL+CA) -> HIGH,
conformity required, 3 US triggers, 14 controls.
- ai_cost_economics.py — Returns API costs (3 tiers) + self-hosted costs (low/
mid/high GPU rates with 24/7 warm + ops attribution) + breakeven analysis.
Reveals key insight: self-hosted floor makes API economics dominate at
typical B2B SaaS scale. Sample (5M tokens/day, 750M/mo) -> API at $1,500/mo
beats self-hosted at $13,450/mo by 9x; breakeven at 6.7B tokens/mo.
4 in-depth references, each citing 5+ authoritative sources:
- model_buildvsbuy_strategy.md — 3 paths with failure modes, 6 fine-tuning
approaches ranked by cost (RAG/LoRA/full FT/RLHF/DPO/continued pre-training),
decision tree, eval-first discipline. Cites Anthropic/OpenAI/Google/Meta
model cards, LoRA paper, RLHF paper, DPO paper, Stanford CRFM Foundation
Models report, Foundation Models and Fair Use (Henderson et al.).
- ai_risk_governance.md — Full EU AI Act tier map (Art. 5 prohibited, Art. 6
+ Annex III high-risk, Art. 50 limited-risk) with all 8 high-risk domains
+ 11 obligation articles. NIST AI RMF 1.0. US state patchwork (9 laws).
Industry overlays (FDA AI/ML, CFPB, NYDFS, NAIC). 10-item governance
program checklist. When-to-hire-AI-counsel criteria.
- ai_cost_economics.md — 2026 API pricing (4 tiers), GPU rental (A100/H100/
H200/B200), throughput estimates, GPU count by model size, utilization
reality (20-80%), 6 hidden costs of self-hosted, 6 hidden costs of API,
migration cost, prompt caching as economics lever. Cites vLLM paper,
DistServe, HELM, Artificial Analysis.
- ai_team_org_evolution.md — 5-stage role map (pre-seed -> late-stage),
9-role definition table (AI engineer != ML engineer != research scientist),
AI team vs data team contrast (8 dimensions), 7 anti-patterns, hiring
sequencing rule. Cites Huyen "Designing ML Systems" + "AI Engineering",
State of AI Report.
cs-caio-advisor agent (c-level-agents/agents/cs-caio-advisor.md):
- Eval-demanding realist voice
- Hard rule: does not duplicate engineering AI/ML skills (rag-architect,
agent-designer, prompt-governance, self-eval, llm-cost-optimizer)
- Treats every AI use case as a hiring decision; pushes back on AI hype
/cs:caio-review slash command:
- 6-question forcing interrogation: eval set, hallucination SLO, regulatory
tier, model selection, cost trajectory, role-that-unblocks
- Routes to /cs:cdo-review, /cs:gc-review, /cs:ciso-review, /cs:cfo-review,
/cs:chro-review
cs-caio-advisor voice spec added to persona-voices.md.
Updates:
- c-level plugin.json: v2.5.2 -> v2.5.3 (31 skills, 11 cs-* agents)
- c-level-agents plugin.json: v1.2.0 -> v1.3.0 (11 agents, 19 commands)
- marketplace.json: both c-level entries; new CAIO keywords (chief-ai-officer,
caio, ai-strategy, model-buildvsbuy, eu-ai-act, ai-cost-economics)
- c-level CLAUDE.md: CAIO row added; agent + count tables updated
- Root CLAUDE.md: 265->266 skills, 30->31 cs-* agents, 364->367 tools,
494->498 references, 51->52 commands; v2.5.3 highlight section
- CHANGELOG.md: v2.5.3 entry with full rationale
Known follow-up (out of scope this PR): cs-general-counsel-advisor voice spec
still missing from persona-voices.md (carried from v2.5.1); separate PR.
Disclaimer in every output: not legal advice; not a replacement for AI
counsel on EU AI Act conformity; not a tactical AI/ML engineering skill.
https://claude.ai/code/session_012WtZMm5NJHqkYoRqA9fHMN
Closes the gstack-can't-touch lane: gstack has zero legal coverage; this is
the first plugin in the founder-mode lineup to outclass it on a domain it
doesn't even attempt. Legal exposure is where startups most often discover a
problem after it's expensive to fix.
New skill (c-level-advisor/skills/general-counsel-advisor/):
- SKILL.md with 4 workflows (contract review, term sheet response, IP hygiene
audit, regulatory trigger assessment), keywords, output standards
- scripts/contract_risk_scanner.py — scans contract text for 12 founder-killer
patterns (auto-renew traps, uncapped indemnity, vague IP, aggressive
non-compete, missing DPA when personal data flows, MFN pricing, perpetual
license-back, one-sided force majeure/venue/audit, broad non-solicit).
Stdlib-only, JSON+text output, --help. Smoke-tested: 7 findings on embedded
sample MSA across CRITICAL/HIGH/MEDIUM.
- scripts/term_sheet_analyzer.py — scores term sheet 0-100 across 12 dimensions
(liquidation preference, anti-dilution, option pool pre/post-money, board,
vesting, pro-rata, drag-along, protective provisions, info rights, dividends,
valuation, holistic). Stdlib-only, JSON-input + JSON+text output, --help.
Smoke-tested: founder-friendly Series A sample scores 94/100.
- references/contracts_playbook.md — 7 startup contract types with top redlines
- references/ip_and_regulatory.md — IP strategy + regulatory trigger matrix
(HIPAA/GDPR/FDA/fintech/AI Act) + SOC 2 -> ISO sequencing
- references/term_sheet_decoder.md — full glossary, founder-friendly defaults,
the 3 clauses that matter most, negotiation strategy
New agent (c-level-advisor/c-level-agents/agents/cs-general-counsel-advisor.md):
- Risk-paranoid persona orchestrating the skill
- Voice: "Before we sign, three things need to be settled in writing."
- Hard rule: never substitutes for licensed counsel; always escalates
Updates:
- /cs:gc-review SKILL.md: now points at the real skill + tools (was a planned-
skill placeholder before)
- c-level-advisor/.claude-plugin/plugin.json: v2.5.0 -> v2.5.1, description
updated to 29 skills (was 28)
- c-level-advisor/c-level-agents/.claude-plugin/plugin.json: v1.0.0 -> v1.1.0,
9 cs-* agents (was 8)
- marketplace.json: both c-level entries bumped, +contract-review, +term-sheet,
+ip-strategy keywords
- c-level-advisor/CLAUDE.md: General Counsel added to roles table; agents and
counts updated
- Root CLAUDE.md: 263 -> 264 skills, 28 -> 29 cs-* agents, 359 -> 361 Python
tools, 487 -> 490 references; v2.5.1 highlight section added
- CHANGELOG.md: full v2.5.1 entry with rationale
Disclaimer: every tool/reference/agent output reminds users this is not legal
advice; always engage qualified counsel. The skill is positioned as triage
before $500/hour counsel time, never as a substitute.
https://claude.ai/code/session_012WtZMm5NJHqkYoRqA9fHMN
The skill directory layout changed from depth-3 (category/skill/SKILL.md)
to depth-4+ (team/skills/skill-name/SKILL.md). The find command in
convert.sh still used -mindepth 3 -maxdepth 3, causing "No skills found"
errors. Updated to -mindepth 4 -maxdepth 6 and excluded integrations/ to
avoid picking up already-converted output.
Co-authored-by: Cursor <cursoragent@cursor.com>
Bitdefender (and similar heuristic AV/EDR products) quarantine the
hunt-playbooks reference because it lists the command-line patterns
associated with LOLBin abuse (certutil -decode, regsvr32 /s /u /i:http
scrobj.dll, mshta URL, etc.). The strings appear inside markdown
tables and cannot execute from a .md file — this is defensive
threat-hunting documentation.
Added a banner at the top that:
- States the defensive-doc intent explicitly
- Lists the binaries cited and why they appear
- Tells affected users how to allow-list the path
- Links to the tracking issue
Closes#533
The /si:extract command and its skill-extractor agent had no guard
against the Claude Code skill-spec reserved name fragments. Users
reported the agent autogenerating skills like 'claude-code-settings',
'claude-mcp-tools', etc. — all of which violate the spec.
- Add explicit reserved-fragment rule to both the slash-command
SKILL.md and the agent definition.
- Recommend the 'cc-' prefix for Claude Code-specific skills
(cc-settings, cc-maintenance, cc-mcp-tools).
- Add the check to both quality-gate checklists so the agent
surfaces a rename before writing files.
Closes#537
Five SKILL.md files linked to references/*.md files that don't exist
on disk:
- onboarding-cro, paywall-upgrade-cro, page-cro → references/experiments.md
- programmatic-seo → references/playbooks.md
- seo-audit → references/ai-writing-detection.md, references/aeo-geo-patterns.md
The 4 CRO/pSEO links pointed to placeholder content that was never
authored — removed the link lines (the surrounding sections still
hold the substantive guidance). The seo-audit References section is
re-anchored to the 4 reference files that actually exist
(seo-audit-reference, cwv-thresholds, eeat-framework, schema-types).
Closes#586
The lowercase pull_request_template.md was an exact duplicate of
PULL_REQUEST_TEMPLATE.md. On case-insensitive filesystems (Windows,
default macOS), git clone emits a path-collision warning and only
one file lands in the working tree.
Closes#545
Promotes the 11 commits accumulated on dev since v2.4.4 into a tagged
release before opening the dev->main PR.
Version bumps (root-level only — per-skill version stamps unchanged):
.claude-plugin/marketplace.json metadata.version: 2.4.4 -> 2.4.5
CLAUDE.md 'Version:' headers (x2): v2.4.4 -> v2.4.5
CLAUDE.md 'Last Updated': May 10 -> May 11, 2026
Deliberately NOT bumped:
- slo-architect plugin version (marketplace.json line 643) stays 2.4.4
-- that's the skill's own release stamp, not the repo version
- SKILL.md frontmatter versions in engineering/skills/slo-architect/
and engineering/slo-architect/skills/slo-architect/ -- same reason
CHANGELOG.md changes:
- [Unreleased] block renamed to [2.4.5] - 2026-05-11
- Title broadened to include 'Count-Truth Reconciliation' alongside the
original 'Skill Expansion Phase 1+2+3+4 (+ ship-gate)'
- 'Changed' totals corrected to file-system truth:
Skills: 235 -> 246 (was claimed 235 -> 238)
Tools: 314 -> 359 (was claimed 314 -> 325)
References:435 -> 485 (was claimed 435 -> 447)
Agents: added (28 -> 27, was missing)
Commands: 27 -> 33 (was claimed 27 -> 30)
Plugins: added (30 -> 33, was missing)
- 'Fixed' subsection: added bullets for #608 (count corrections) and
#609 (marketplace registry + integrations.md), plus
skill-security-auditor self-skip fix
Why the v2.4.4 unreleased totals were wrong: the entry was drafted
mid-cycle and never reconciled before tagging. #608/#609 caught the
drift. The v2.4.5 totals now reproduce from one find/python3 command
each (commands documented inline in the changelog bullets).
PR #607 shipped '188 skills, 30 agents, 3 personas, 30 marketplace plugins'
based on a stale codex-sync output that I trusted without verifying. The
actual file-system counts are:
Skills: 246 (250 SKILL.md files; 4 deduped because chaos-engineering,
feature-flags-architect, kubernetes-operator and
slo-architect each ship as both an umbrella entry and
a standalone plugin)
Tools: 359 .py files under */scripts/* (unchanged, was correct)
Refs: 485 .md files under */references/* (unchanged, was correct)
Agents: 27 (20 canonical cs-*-prefixed + 7 personas; excludes
agents/CLAUDE.md, personas/README.md, personas/TEMPLATE.md)
Commands: 33 .md files under commands/ (unchanged, was correct)
Plugins: 33 in .claude-plugin/marketplace.json (was '30' in the
Status line and README badge area)
Every number now reproduces from a single deterministic command:
find . -name SKILL.md -not -path './.gemini/*' -not -path './.codex/*' \
-not -path './site/*' -not -path './docs/*' \
-not -path './.git/*' | wc -l # -> 250 raw
find agents -name 'cs-*.md' | wc -l # -> 20 cs-* agents
ls agents/personas/*.md | grep -v -E 'README|TEMPLATE' | wc -l # -> 7
python3 -c "import json; print(len(json.load(open('.claude-plugin/marketplace.json'))['plugins']))" # -> 33
Surgical edits only: changed the number, left every other word in place.
Files touched: CLAUDE.md (7 lines), README.md (5 lines), docs/index.md
(4 lines), docs/getting-started.md (2 lines), mkdocs.yml (1 line).
Security scanners legitimately reference dangerous patterns (eval, os.system,
subprocess shell=True, etc.) inside their own regex pattern definitions and
human-readable risk/fix descriptions. Auditing the auditor itself produced
17 CRITICAL false positives — all from its own pattern table. ship-gate had
the same issue (2 CRITICALs on a check description and a variable name
called eval_findings).
Fix:
- Add 'noqa: SEC-AUDITOR' / 'auditor:ignore-line' line-suppression directive
to all three scan loops (code patterns, prompt-injection markdown,
pip/npm runtime install detection).
- Annotate the 179 pattern-definition lines in skill_security_auditor.py
(regex, risk, fix entries) and 4 cleanup shutil.rmtree calls.
- Annotate ship-gate's two flagged lines (SEC-13 check description and
eval_findings variable usage).
- Annotate SKILL.md and references/threat-model.md tables that document
attack patterns for human readers (HTML comment <!-- noqa: SEC-AUDITOR -->).
Verified end-to-end:
skill-security-auditor self-audit: 17 CRITICAL -> 0 (PASS)
ship-gate self-audit: 2 CRITICAL -> 0 (PASS)
slo-architect: PASS (0/0)
project-management WARN unchanged (no top-level SKILL.md, expected)
Auto-regenerated by scripts/generate-docs.py after the post-restructure
fix. Covers slo-architect, ship-gate, chaos-engineering, kubernetes-operator,
feature-flags-architect, llm-wiki, tc-tracker, and 185 other skills now
properly surfaced under their domain index pages.
After PR #593 restructured umbrella plugins, every sub-skill landed at
<domain>/skills/<name>/SKILL.md. The doc generator's is_sub_skill heuristic
treated len(parts) > 2 as nested, so all 188 skills got flagged as 'children
of "skills"' (a non-existent parent) and were never written to docs/.
Recognise <domain>/skills/<name>/ as the canonical top-level layout.
Backwards-compatible with playwright-pro/skills/<sub>/ standalone-plugin
sub-skills (those legitimately have a real parent at parts[1]).
Result: 0 -> 192 skill pages emitted.
PR #527 (@rx4u) submitted a pre-production audit skill that was based on the
pre-#593 layout (skills directly under engineering/). After #593 landed, the
diff would have undone the entire restructure (4500+ rename ops). Re-applying
the actual new content at the correct post-restructure path.
What landed:
- engineering/skills/ship-gate/SKILL.md
- engineering/skills/ship-gate/references/checks.md
- engineering/skills/ship-gate/references/patterns.md
- engineering/skills/ship-gate/scripts/ship_gate_scanner.py
Verified:
- python3 ship_gate_scanner.py --help → OK
- python3 ship_gate_scanner.py --version → ship-gate 1.0.0
- 1671 tests pass (was 1666; +5 for ship-gate smoke + integrity)
- engineering/.claude-plugin/plugin.json: 48 → 49 skills, v2.4.2 → v2.4.3
- marketplace.json: engineering-advanced-skills entry updated to match
Closes#527.
Co-authored-by: Rajaraman Arumugam <rx4u@users.noreply.github.com>
https://claude.ai/code/session_01Dq12xJakFRxwaoU8Pqejdm
chore: resolve 4 open PRs (#596, #597, #582, #517) on clean dev base
Consolidates four ready-to-merge PRs that had become dirty against the
post-restructure dev branch. Conflict in tests/test_skill_integrity.py
resolved by keeping the broader script_globs version (includes .ps1).
Closes#517, #582, #596, #597.
test_scripts_dirs_have_python_files was asserting every scripts/ dir
contains at least one .py file. The full-page-screenshot skill ships
a .mjs (Node ESM) script and triggered a false-positive failure.
Broadens the check to accept any of .py, .mjs, .js, .ts, .sh while
keeping the same intent: scripts/ dirs must not be empty.
Verified: full pytest suite goes from 1 failed / 1611 passed to
725 passed in tests/test_skill_integrity.py alone.
https://claude.ai/code/session_01Dq12xJakFRxwaoU8Pqejdm
Phase 0 of the multi-skill build: ship the two stdlib-only tools that
the rest of the work depends on.
- scripts/sync_skill_bundles.py: mirror a standalone plugin's
SKILL.md + scripts/ + references/ + assets/ into its domain-bundled
location. --check exits 1 on drift; --sync rewrites the mirror.
- scripts/check_plugin_json.py: validate plugin.json against the
strict ClawHub schema (exactly the 8 allowed fields, semver version,
author{name,url}, skills as string or array — bare "./" rejected per
Claude Code v2.1.107+).
Verified: --all run reports OK on all 30 existing plugin.json files;
sync --check correctly detects missing mirrors. Karpathy-coder gate:
both files score 85/100 under strict (single nesting-depth WARN, no
FAIL) — better than the canonical karpathy-coder tools themselves.
https://claude.ai/code/session_01Dq12xJakFRxwaoU8Pqejdm
`engineering/skills/full-page-screenshot/scripts/full-page-screenshot.mjs` is
a legitimate 35KB JavaScript module, but the test only matched `*.py` and
asserted the dir was empty. This caused `test_skill_integrity` to fail on
dev's HEAD (pre-existing breakage, surfaced when CI ran on PR #601).
Broadens the check to accept any common script extension:
.py, .mjs, .js, .ts, .sh, .ps1. The test's intent — "scripts/ shouldn't be
empty" — is preserved; the implementation no longer over-restricts language.
Adds toprank (https://github.com/nowork-studio/toprank) — open-source MIT
plugin with 9 SEO and Google Ads skills (107 GitHub stars).
Co-authored-by: ununununium <43973612+ununununium@users.noreply.github.com>
Closes-PR: #517
- Adds project-management/.mcp.json registering Atlassian's official Remote
MCP server (https://mcp.atlassian.com/v1/sse) as a plugin-bundled SSE MCP.
- Updates project-management/README.md Setup section to reflect bundled-MCP
reality (OAuth handled automatically; no API tokens in the repo).
- Closes the doc/code drift between CLAUDE.md's "Atlassian MCP integration"
claim and the previously absent .mcp.json file.
Co-authored-by: FreyaFujo <172978998+FreyaFujo@users.noreply.github.com>
Closes-PR: #597
`.mcp.json` is the canonical filename Claude Code expects for plugin-bundled
MCP server configuration. The auditor's hidden-file rule was flagging it as
HIGH severity, blocking the `--strict` quality gate documented in CLAUDE.md.
Co-authored-by: FreyaFujo <172978998+FreyaFujo@users.noreply.github.com>
Closes-PR: #596
Karpathy-style review of commit 3806b9b (the prior PR commit) caught real
issues that I missed: agents weren't fully equipped per the optional but
recommended fields in the official sub-agents spec.
Changes:
- engineering/agenthub/agents/hub-coordinator.md: narrow Bash(node *) (too
broad per defense-in-depth) -> moved node into disallowedTools; add
maxTurns: 100 (orchestrators run long); add skills: agenthub:agenthub
(preload the plugin's own guidance into agent context)
- engineering-team/self-improving-agent/agents/memory-analyst.md:
add maxTurns: 30 to bound runaway analysis loops
- engineering-team/self-improving-agent/agents/skill-extractor.md:
add disallowedTools (rm/curl/wget) — agent has Write+Edit so defense-in-
depth applies; add maxTurns: 30
- engineering/karpathy-coder/agents/karpathy-reviewer.md: fix skills field
format from path-style "engineering/karpathy-coder" to spec-correct
namespaced name "karpathy-coder:karpathy-coder" (the path syntax is the
cs-* orchestrator template convention; the official sub-agents spec uses
skill names per code.claude.com/docs/en/sub-agents); add maxTurns: 30
All 6 plugin agents (4 here + 2 in playwright-pro from prior commit) +
the 1 user agent (tech-ingester) now have name + description + tools +
disallowedTools (where write-capable) + model + maxTurns. The skills:
field is set on agents that benefit from preloaded domain skill content.
Functional smoke tests post-fix:
- memory-analyst: PASS (2 turns, 25s, 24K tokens, found 1 real orphan)
- skill-extractor: PASS (0 tool uses, 34s, 17K tokens, generated correct
plan staying read-only with new disallowedTools in effect)
- karpathy-reviewer: PASS (verified in prior session, 28 tool uses)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Per https://code.claude.com/docs/en/sub-agents, agents require YAML
frontmatter with name + description, and the field is `tools:` not
`allowed-tools:` (deprecated). Bare `Bash` allows any command including
curl/wget/rm, which violates defense-in-depth.
Changes:
- engineering/agenthub/agents/hub-coordinator.md: add full frontmatter
(name, description, tools allowlist for git/python/node/Agent,
disallowedTools for rm -rf / curl / wget / git push --force, model)
- engineering-team/self-improving-agent/agents/memory-analyst.md:
add frontmatter, read-only tools (Read, Glob, Grep)
- engineering-team/self-improving-agent/agents/skill-extractor.md:
add frontmatter, write tools (Read, Write, Edit, Glob, Grep)
- engineering-team/playwright-pro/agents/test-architect.md:
rename allowed-tools to tools, add model: inherit
- engineering-team/playwright-pro/agents/migration-planner.md:
same rename
- engineering-team/playwright-pro/agents/test-debugger.md:
rename + narrow bare Bash to npx playwright / node / npm patterns,
add disallowedTools for rm / curl / wget / destructive git
- engineering/karpathy-coder/agents/karpathy-reviewer.md:
narrow bare Bash to git read-ops + python, add disallowedTools
All registered agents now load cleanly under the sub-agents spec rather
than falling through to permissive registration.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PR #593 moved every skill from <plugin>/<name>/ to <plugin>/skills/<name>/
to satisfy Claude Code's runtime loader. That broke two CI jobs that
hardcoded the old paths:
1. **9 test files** had `sys.path.insert(0, ".../<domain>/<skill>/scripts")`
pointing at the pre-restructure location. Inserted `"skills"` between
the domain and skill segments so imports resolve again.
2. **scripts/sync-codex-skills.py** scanned `<domain>/<skill>/SKILL.md`
and emitted "No skills found in repository". Updated `find_skills` to
prefer `<domain>/skills/<name>/` and fall back to `<domain>/<name>/`
so it works with both layouts (in case any domain hasn't been
restructured yet).
Verified locally:
- `python3 scripts/sync-codex-skills.py --dry-run` finds 178 skills
- `pytest tests/` collects all modules; 3216 tests pass
- 4 pre-existing failures remain (3 argparse duplicates in an
`integrations/` script, 1 strict "must have .py" check on a JS-only
skill) — out of scope for this fix.
Same root cause as #587/#591 — Claude Code's runtime loader rejects
array-form skills paths like ["./content-production", "./ai-seo", ...]
even when each entry is a valid subdirectory containing SKILL.md.
`claude plugin validate` accepts them but the loader does not.
The proven canonical layout (used by self-improving-agent in #536):
<plugin>/
├── .claude-plugin/plugin.json skills: "./skills"
└── skills/
├── <skill-1>/SKILL.md
├── <skill-2>/SKILL.md
└── ...
Restructured 9 multi-skill domain plugins:
- business-growth (4 skills moved)
- c-level-advisor (28)
- engineering (36)
- engineering-team (32)
- finance (2)
- marketing-skill (43)
- product-team (12)
- project-management (8)
- ra-qm-team (13)
Also fixed standalone plugins that had root SKILL.md + ./skills/ subdir
(agenthub, autoresearch-agent, executive-mentor, playwright-pro). The
loader rejected them despite skills="./skills" because of the conflicting
root SKILL.md (compare self-improving-agent which works because PR #536
moved its root SKILL.md). Moved each root SKILL.md into ./skills/<name>/.
Restored standalone plugin folders to their original paths after the
multi-skill restructure swept them into parent skills/ directories
(marketplace.json source paths require original locations).
Removed 7 orphaned marketplace entries that pointed to skill folders
without their own plugin.json (content-creator, demand-gen,
fullstack-engineer, aws-architect, product-manager, scrum-master,
skill-security-auditor) — these were already non-functional.
Bumped patch versions on every changed plugin and synced
marketplace.json. Marketplace now lists 29 working plugins (down
from 36).
After merge: users run `/plugin marketplace update claude-code-skills`
followed by `/plugin update --all` to pick up the working layout.
Claude Code v2.1.126 rejects "skills": ["./"] (array form) at runtime
with the same "Path escapes plugin directory: ./" error as the bare
string form, despite the official plugins reference docs explicitly
showing ["./"] as a valid example. `claude plugin validate` accepts it,
so the bug is in the runtime loader, not the manifest validator.
The proven workaround (already used for self-improving-agent in #536)
is to follow the canonical layout:
<plugin>/
├── .claude-plugin/plugin.json skills: "./skills"
└── skills/<plugin-name>/
├── SKILL.md
├── scripts/
├── references/
└── ...
Applied to 21 single-skill plugins:
- engineering-team/a11y-audit, google-workspace-cli, snowflake-development
- engineering/behuman, code-tour, data-quality-auditor, demo-video,
docker-development, helm-chart-builder, karpathy-coder, llm-cost-optimizer,
llm-wiki, prompt-governance, statistical-analyst, terraform-patterns
- finance/business-investment-advisor
- marketing-skill/video-content-strategist
- product-team/agile-product-owner, apple-hig-expert, code-to-prd,
research-summarizer
Moved with each SKILL.md: scripts/, references/, assets/, templates/,
expected_outputs/. Kept at plugin root (per Claude Code requirements):
agents/, commands/, hooks/, settings.json, README.md.
Bumped patch version on each restructured plugin so /plugin update
picks up the new layout.
Refs #539
PR #587 fixed `"skills": "./"` in 35 plugin.json files but did not bump
versions. Claude Code uses version as the cache key — same version string
means /plugin update is a no-op and users keep loading the cached
plugin.json with the broken path. The /plugin UI shows "1 error" on
every plugin from this marketplace because the installed cache is stale.
Per the official version-management docs:
> If you set `version` in `plugin.json`, you must bump it every time
> you want users to receive changes. Pushing new commits alone is not
> enough.
Bump every plugin.json by one patch using max(plugin_version,
marketplace_version) as the base so no version moves backward. Sync the
new versions back into .claude-plugin/marketplace.json.
After this lands, users run `/plugin marketplace update claude-code-skills`
followed by `/plugin update --all` to pull the fixed manifests.
Claude Code v2.1.107+ rejects bare "skills": "./" with "Path escapes
plugin directory: ./". This blocks every plugin in the marketplace from
loading. Replace with the layout-appropriate form per the official
plugins reference:
- Single-skill plugin (SKILL.md at root):
"skills": ["./"] array form (per docs example)
- Plugin with skills/ subdir:
"skills": "./skills" standard subdir layout
- Multi-skill domain plugin (skills are subfolders at root):
"skills": ["./sub1", "./sub2"] explicit list of skill dirs
The multi-skill case omits "./" from the array so the index SKILL.md
at the plugin root does not register as a skill — that would create
a redundant `marketing-skills:marketing-skills` namespace.
Verified by running `claude plugin validate` against all 35 manifests.
Closes#539
Zero-dependency Node.js skill that captures full-page screenshots of web
pages via Chrome DevTools Protocol. Supports SPA scroll container
expansion, lazy-load triggering, DOM stability detection, and tiled
capture for very tall pages. Requires only Node.js 22+ and Chrome with
remote debugging enabled.
- Convert Augment integration from flat .augment/rules/*.md to directory-based .augment/skills/<name>/SKILL.md structure
- Align Augment format with Windsurf and OpenCode skill bundle pattern
- Copy supporting folders (scripts/, references/, templates/) to each Augment skill directory
- Update frontmatter from 'type: auto' to standard 'name' + 'description' fields
- Update README documentation for new directory-based installation path
This change is possible because Augment Code now supports skills in beta, allowing us to move from the flat rules format to full skill bundles. This gives Augment users access to the complete skill ecosystem including Python automation tools and reference documentation, not just the markdown content.
Updated the skill description to emphasize proactive usage and clarified triggers for cost optimization. Enhanced the context and steps for cost auditing, optimization, and architecture design.
The plugin.json configured 'skills': './' which scans the plugin root for SKILL.md files. This found the root SKILL.md (name: 'self-improving-agent') and stopped, preventing Claude Code from discovering the subskills (review, promote, extract, status, remember) in the skills/ subdirectories.
Fix: Move root SKILL.md to skills/self-improving-agent/SKILL.md and update plugin.json to 'skills': './skills/' so Claude Code recursively scans the skills/ directory and discovers all 5 subskills.
This enables the intended /si:review, /si:promote, /si:extract, /si:status, /si:remember slash command routing.
Phases 2+3 of the marketing skills improvement plan. Inspired by patterns
from claude-blog (466 stars) — dual-optimization for Google + AI citation
platforms, quality gates as hard stops, and AI content detection.
content-production additions:
- scripts/content_quality_gates.py — 8 non-negotiable publishing gates:
heading hierarchy, paragraph length (≤150 words), image alt text,
source citations for statistics, title length (50-60 chars), meta
description length (150-160), self-promotion limit (≤1 mention),
freshness signals. Verdicts: PUBLISH / TARGET / BLOCK. Demo included.
- references/ai-citation-readiness.md — how to optimize for AI citation
platforms (Perplexity, ChatGPT, AI Overviews): answer-first paragraphs,
passage-level citability (120-180 word chunks), entity clarity, Q&A
formatting, freshness signals
- references/content-templates.md — 12 content templates (how-to, listicle,
case study, comparison, pillar page, product review, thought leadership,
roundup, tutorial, news analysis, data research, FAQ) with auto-selection
logic based on user intent and target word counts
copy-editing additions:
- scripts/ai_content_detector.py — 3-method AI detection: burstiness
analysis (sentence length CV — human=0.5+, AI=0.2-0.35), vocabulary
diversity (sliding-window TTR — human=0.6+, AI=0.35-0.45), 30 known
AI phrases with density scoring. Composite 0-100: ≤20 LIKELY_HUMAN,
21-50 MIXED, 51+ LIKELY_AI. Includes humanization recommendations.
- references/ai-detection-patterns.md — full explanation of all 3 methods,
threshold tables, the 10 most common AI phrases with replacements,
scoring formula, caveats for technical writing
All scripts stdlib-only, --json + --help + --demo verified.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The agile-product-owner skill was available as part of the product-team
domain bundle but lacked its own .claude-plugin/plugin.json for standalone
installation via `/plugin install agile-product-owner@claude-code-skills`.
Adds:
- product-team/agile-product-owner/.claude-plugin/plugin.json (v2.3.0)
- .claude-plugin/marketplace.json entry (36th plugin, category: product)
Cross-tool availability verified:
- Codex CLI: present in skills-index.json (product category, 16 skills)
- Gemini CLI: present in skills-index.json
- Hermes Agent: discoverable via sync-hermes-skills.py
- Top-level agent: agents/product/cs-agile-product-owner.md exists
Security audit: PASS (0 critical, 0 high)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Hermes Agent (github.com/NousResearch/hermes-agent) uses the agentskills.io
standard — the same SKILL.md format with YAML frontmatter that our repo uses.
Both tools expect: name, description, version, license in frontmatter, with
references/, templates/, assets/ subdirectories. No format conversion needed.
Adds scripts/sync-hermes-skills.py which symlinks (or copies) our 198 skills
into ~/.hermes/skills/claude-skills/<domain>/<skill-name>/ where Hermes
discovers them automatically via its skill_view/skills_list tools.
Usage:
python scripts/sync-hermes-skills.py --verbose # full sync
python scripts/sync-hermes-skills.py --domain engineering # one domain
python scripts/sync-hermes-skills.py --copy # copy instead of symlink
python scripts/sync-hermes-skills.py --dry-run # preview
After sync, Hermes users can invoke any of our skills via:
/skills (browse)
/<skill-name> (invoke directly)
Compatibility matrix after this change:
Claude Code — native plugin install
Codex CLI — sync-codex-skills.py
Gemini CLI — sync-gemini-skills.py
OpenClaw — openclaw-install.sh
Hermes Agent — sync-hermes-skills.py (NEW)
Cursor/Aider/etc — scripts/convert.sh
Ref #520
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implements Karpathy's 4 coding principles (Think Before Coding, Simplicity
First, Surgical Changes, Goal-Driven Execution) as an active enforcement
plugin, not just passive guidelines. Derived from Karpathy's X post on LLM
coding pitfalls but goes far beyond the source material with automated
detection tools, a review agent, and CI integration patterns.
Differentiator vs forrestchang/andrej-karpathy-skills (prompt-only, single
SKILL.md): this version ships real tooling that DETECTS violations instead
of just documenting principles.
Plugin contents (engineering/karpathy-coder/):
- SKILL.md with `context: fork` for skill chaining
- 4 Python tools (stdlib only):
- complexity_checker.py — cyclomatic complexity, class density, nesting
depth, function length, premature abstractions (Principle #2)
- diff_surgeon.py — diff noise ratio: comment-only changes, whitespace,
style drift, drive-by refactors, quote-style swaps (Principle #3)
- assumption_linter.py — detects "just", "obviously", "should work",
vague actions, unscoped users, missing format specs (Principle #1)
- goal_verifier.py — scores plan steps 0-3 for verification quality,
flags vague criteria, checks for final verification (Principle #4)
- 1 sub-agent: karpathy-reviewer (runs all 4 principles against a diff)
- 1 slash command: /karpathy-check (dispatches the reviewer)
- 1 pre-commit hook: karpathy-gate.sh (non-blocking, warns on violations)
- 3 reference docs: karpathy-principles.md (full context + when to relax),
anti-patterns.md (10+ before/after examples), enforcement-patterns.md
(Husky, pre-commit framework, GitHub Actions CI integration)
- .claude-plugin/plugin.json manifest (v2.3.0)
- Cross-tool compatible: works with any AGENTS.md-based CLI
All 4 scripts verified: --help passes, smoke tests run correctly.
complexity_checker catches its own nesting depth. assumption_linter
correctly flags "just", "obviously", "should work". goal_verifier
correctly scores plans with/without verification steps.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Issue #506 reported that `hooks/hooks.json` used `./hooks/error-capture.sh`
which fails for any session started outside the plugin dir. That specific
file was already fixed in commit 217b199 (which closed#392) — both
`hooks/hooks.json` and `settings.json` already use `${CLAUDE_PLUGIN_ROOT}`.
However, two stale example paths were still surfacing the bug in
documentation:
1. `engineering-team/self-improving-agent/CLAUDE.md` line 74 — "To enable"
example with `./skills/self-improving-agent/hooks/error-capture.sh`
2. `engineering-team/self-improving-agent/hooks/error-capture.sh` header
comment — install example with the same broken path
Both examples would teach users to copy the broken pattern into their own
settings.json, reproducing the exact bug #506 describes.
Fix: rewrite both examples to use `${CLAUDE_PLUGIN_ROOT}/hooks/error-capture.sh`
and add explicit "do not use relative paths" warnings. Also clarify in
CLAUDE.md that manual hook wiring is NOT needed when installing via
`/plugin install` — the hook is registered automatically from the plugin's
hooks.json.
Fixes#506
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Bug: after `/plugin install self-improving-agent@claude-code-skills`, only
1 skill appeared and `/si:review`, `/si:promote`, `/si:extract`, `/si:status`,
`/si:remember` were all unknown commands. The 5 sub-skills were silently
registered under the wrong namespace.
Root cause: two issues in the plugin manifest layer.
1. **Slash-command namespace is derived from `.claude-plugin/plugin.json`
`name`**, not from the marketplace entry name, the settings.json name, or
frontmatter. Previous `name: "self-improving-agent"` caused sub-skills to
register as `/self-improving-agent:review` etc — never matching the
documented `/si:*` commands.
2. **`command: /si:<op>` frontmatter in sub-skill SKILL.md files is a
non-standard field** not in the Claude Code Skills spec. Claude Code
silently ignores it. It created the illusion that the commands were being
registered when they were not.
Fix:
- Change `engineering-team/self-improving-agent/.claude-plugin/plugin.json`
`name` from "self-improving-agent" → "si". This is the namespace root; it
does NOT affect the marketplace install identifier (which stays
`self-improving-agent` via the marketplace.json `name` field). After the
fix, skills register as `/si:review`, `/si:promote`, `/si:extract`,
`/si:status`, `/si:remember` — matching the README and CLAUDE.md docs.
- Remove the non-standard `command: /si:<op>` frontmatter line from all 5
sub-skill SKILL.md files (review, promote, extract, status, remember).
Frontmatter now contains only `name` and `description` per the Claude Code
Skills spec.
- Bump plugin.json version 2.1.2 → 2.3.0 to match repo release.
- Update marketplace.json entry: version 2.2.0 → 2.3.0, expand description
to list all 5 slash commands and 2 sub-agents.
OpenClaw compat: the legacy `settings.json` inside the skill directory still
uses `"name": "self-improving-agent"` for OpenClaw's install path. Claude Code
ignores settings.json entirely, so this is safe to leave as-is.
Install flow (unchanged, verified correct after fix):
/plugin marketplace add alirezarezvani/claude-skills
/plugin install self-improving-agent@claude-code-skills
# → 5 skills register as /si:review, /si:promote, /si:extract,
# /si:status, /si:remember
Known related issue (not fixed in this PR to keep scope tight): `agenthub`
has the identical bug. Its plugin.json `name` is "agenthub", so sub-skills
register as `/agenthub:init` rather than the documented `/hub:init`. Same
fix applies: rename plugin.json `name` to "hub". Will file as a follow-up.
Fixes#505
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implements Karpathy's LLM Wiki pattern as a production-grade plugin. The LLM
incrementally ingests sources into a persistent, interlinked Obsidian vault —
updating entity/concept/source pages, flagging contradictions, maintaining an
index and append-only log. Knowledge compounds instead of being re-derived by
RAG on every query.
Plugin contents (engineering/llm-wiki/):
- SKILL.md with `context: fork` frontmatter for skill chaining
- 3 sub-agents: wiki-ingestor, wiki-librarian, wiki-linter
- 5 slash commands: /wiki-init, /wiki-ingest, /wiki-query, /wiki-lint, /wiki-log
- 8 Python tools (stdlib only): init_vault, ingest_source, update_index,
append_log, wiki_search (BM25), lint_wiki, graph_analyzer, export_marp
- 8 reference docs: schema, page-formats, ingest/query/lint workflows,
obsidian-setup, cross-tool-setup, memex-principles
- Vault templates: CLAUDE.md, AGENTS.md, .cursorrules, index.md, log.md,
5 page templates (entity, concept, source, comparison, synthesis)
- Worked example vault on "LLM interpretability"
- .claude-plugin/plugin.json manifest
Cross-tool compatibility: the scripts are pure Python stdlib. Only the schema
loader changes per tool (CLAUDE.md for Claude Code, AGENTS.md for Codex CLI /
Cursor / Antigravity / OpenCode / Gemini CLI, .cursorrules for legacy Cursor).
init_vault.py --tool all installs all three.
Repo-level registration:
- Commands mirrored to top-level commands/ for repo-wide discovery
- Agents mirrored to agents/engineering/ as cs-wiki-{ingestor,librarian,linter}
- .claude-plugin/marketplace.json: new llm-wiki entry + version bump to v2.3.0
- CLAUDE.md updated: 234 skills, 313 Python tools, 432 refs, 28 agents, 27 commands
Also saved (deferred): craighewitt-mattpocock reimplementation plan at
documentation/implementation/ — 4-pod proposal for building better versions
of selected skills from thecraighewitt-skills and mattpocock-skills
collections. Not executed; awaiting user confirmation on scope.
End-to-end smoke test passed: init_vault → ingest → update_index → append_log
→ wiki_search → lint → graph_analyzer → export_marp all run against a fresh
vault with real pages, wikilinks, and frontmatter.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fork-based PRs (like PR #498) caused all CI checks to fail due to:
- ci-quality-gate: checkout failed because fork branch names don't exist
in the base repo. Now uses commit SHA for PR events.
- skill-security-audit: comment posting failed with read-only GITHUB_TOKEN.
Now continues on error and writes results to job summary as fallback.
- claude-code-review: fallback comment step failed silently. Now continues
on error and writes status to job summary.
https://claude.ai/code/session_01X1RKFAkEwxgg6gQvJG1KCa
Self-contained skill for tracking technical changes with structured JSON
records, an enforced state machine, and a session handoff format that lets
a new AI session resume work cleanly when a previous one expires.
Includes:
- 5 stdlib-only Python scripts (init, create, update, status, validator)
all supporting --help and --json
- 3 reference docs (lifecycle state machine, JSON schema, handoff format)
- /tc dispatcher in commands/tc.md
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Move from data-analysis/ to engineering/
- Fix 5 cross-references to use correct domain paths
- Fix Python 3.9 compat in sample_size_calculator.py
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds statistical-analyst skill — fills a gap in the repo (no hypothesis
testing or experiment analysis tooling exists; only ab-test-setup for
instrumentation, but zero analysis capability).
Three stdlib-only Python scripts:
- hypothesis_tester.py: Z-test (proportions), Welch's t-test (means),
Chi-square (categorical) with p-value, CI, Cohen's d/h, Cramér's V
- sample_size_calculator.py: required n per variant for proportion and
mean tests, with power/MDE tradeoff table and duration estimates
- confidence_interval.py: Wilson score interval (proportions) and
z-based interval (means) with margin of error and precision notes
Validator: 86.4/100 (GOOD). Security audit: PASS (0 critical/high).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add a skill for creating CodeTour .tour files — persona-targeted,
step-by-step walkthroughs that link to real files and line numbers.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a skill for creating polished demo videos from screenshots and scene
descriptions. Orchestrates playwright, ffmpeg, and edge-tts MCPs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Based on issue #464 submission by voidborne-d. Enhanced with English-only
content (removed all Chinese), anti-patterns section, cross-references,
plugin.json, convention-compliant frontmatter, and English eval scenarios.
behuman (193 lines + reference + 8 eval scenarios):
- Self-Mirror loop: instinctive response → reflection → conscious revision
- Show mode (2.5-3x tokens) and quiet mode (1.5-2x tokens)
- 3 English examples: emotional support, life advice, personal writing
- Based on Lacan's Mirror Stage + Kahneman's Dual Process Theory
- Zero dependencies — pure prompt technique
Co-Authored-By: voidborne-d <voidborne-d@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Each skill is now individually installable:
- llm-cost-optimizer
- prompt-governance
- business-investment-advisor
- video-content-strategist
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds the OpenAI Codex plugin manifest required for listing in
awesome-codex-plugins and future Codex marketplace submission.
Includes name, version, description, author, keywords, skills path,
and interface metadata matching the Codex plugin specification.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Analyzes the current state of testing across 301 Python scripts (0% unit
test coverage), identifies 6 priority areas for improvement, and proposes
a phased implementation plan. Key findings: CI quality gate is non-blocking,
calculator/scoring scripts are trivially testable, and compliance checkers
carry regulatory risk without test coverage.
https://claude.ai/code/session_01MsVmZoAsPvLv7rAGDBGTbL
Adds self-eval skill for honest AI work quality evaluation. Uses two-axis scoring (ambition x execution), mandatory devil's advocate reasoning, and cross-session anti-inflation detection via .self-eval-scores.jsonl persistence.
Adds threat-detection, incident-response, cloud-security, red-team, and ai-security skills to engineering-team. Each includes SKILL.md, references, and Python scripts (stdlib-only). Consolidation of 66 individual skills into 5 production-ready packages.
Adds adversarial code review skill with 3 hostile personas (Saboteur, New Hire, Security Auditor) that force genuine perspective shifts to break the self-review monoculture. Each persona must find at least one issue - no LGTM escapes.
- Add --include-security flag to quality_scorer.py
- Default: 4 dimensions × 25% (backward compatible)
- With --include-security: 5 dimensions × 20%
- Update tier recommendation logic for optional Security
- Update documentation to reflect opt-in behavior
This addresses the breaking change concern from PR review:
the weight change from 25% to 20% would affect all existing
audit baselines. The new opt-in approach preserves backward
compatibility.
CONVENTIONS.md: Mandatory technical rules for all contributors (human and AI).
Covers SKILL.md format, plugin.json schema, Python script standards, sub-skill
rules, cross-platform sync, and what NOT to contribute.
CONTRIBUTING.md: Rewritten to reference CONVENTIONS.md. Fixed outdated guidance
that contradicted actual repo conventions (was recommending license/metadata in
frontmatter, wrong line limits, missing anti-patterns/cross-refs requirements).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Per Anthropic docs: "Keep SKILL.md under 500 lines. Move detailed
reference material to separate files."
- browser-automation: 564 → 266 lines (moved examples to references/)
- spec-driven-workflow: 586 → 333 lines (moved full spec example to references/)
- security-pen-testing: 850 → 306 lines (condensed OWASP/attack details, moved to references/)
No content deleted — all moved to existing reference files with pointers.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Validator expects scripts in scripts/ subdirectory, not at skill root.
Moved 6 scripts to match repo convention.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- executive-mentor: add url to author, add homepage + repository
- self-improving-agent: add url to author, version 1.0.0 → 2.1.2
- playwright-pro: fix author name (Reza → Alireza), replace email with url, version 1.0.0 → 2.1.2
- google-workspace-cli: add url to author
All plugin.json files now use consistent author object format.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Relative paths (./hooks/error-capture.sh) resolve against the project
working directory, not the plugin root. Replaced with
${CLAUDE_PLUGIN_ROOT}/hooks/error-capture.sh in both hooks.json and
settings.json.
Fixes#392
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The GSC verification HTML file existed locally but was never committed,
so it was never deployed to GitHub Pages. This caused GSC to fail
reading the sitemap for 3+ weeks ("Sitemap konnte nicht gelesen werden").
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Claude Code plugin manifest requires author as {"name": "..."}, not a
plain string. Fixes install error: "author: Invalid input: expected
object, received string"
Affected: agenthub, a11y-audit
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Update CLAUDE.md, README.md, docs/index.md, docs/getting-started.md,
mkdocs.yml, marketplace.json with consistent counts. Sync Gemini CLI
index with new skills (code-to-prd, plugin-audit).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The agenthub marketplace entry was added in commit 2f57ef8 but dropped
when PR #369 (code-to-prd) merged with a conflict in marketplace.json.
Re-adds the entry with all cross-domain keywords and 7 slash commands.
Total plugins: 22 (was 21)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add .claude-plugin, .codex, .gemini to hidden file allowlist (FS-HIDDEN)
These are required plugin infrastructure directories, not secrets.
- Remove 'tokens?' from PROMPT-EXFIL regex — 'access token' is a standard
technical term in auth reference docs, causing false positives on every
skill that documents JWT/OAuth flows (e.g. saas-scaffolder auth-billing-guide)
- Remaining PROMPT-EXFIL patterns (credentials, secrets, api_keys, .env, .ssh,
.aws, ~/home, /etc) are specific enough to catch real threats
Fixes: CI security audit failure on PR #370 (7 CRITICAL false positives)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Analyzes routes, components, state, APIs, and interactions to generate
complete Product Requirements Documents. Framework-agnostic (React, Vue,
Angular, Svelte, Next.js, Nuxt). Three-phase workflow: global scan,
page-by-page deep analysis, structured doc generation.
Inspired by community contribution (PR #368) but rebuilt from scratch
in English with enhanced coverage for mock API detection, field
interdependencies, and execution pacing strategies.
Review gate flagged version 1.0.0 as non-compliant with CLAUDE.md rule:
"Version follows repo versioning." Updated to 2.1.2.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Consistent format: '<N> <domain> agent skills and plugins for Claude Code, Codex, Gemini CLI, Cursor, OpenClaw'
Updated both SKILL.md frontmatter and plugin.json for each pack.
- Cut 70% bloat (750 lines removed, 220 added)
- Dropped corporate sections (Core Capabilities, Decision Framework → merged naturally)
- Commands as the centerpiece — what you DO, not what you ARE
- 'How You Think' + 'What You Never Do' = personality, not résumé
- 'When to Use Me' with ✅/❌ = clear routing
- 'What Good Looks Like' = success without corporate metric tables
Our format: opinionated colleague with tools
Agency-agents format: job description with capabilities
Different on purpose.
Aligns new personas with agency-agents structure:
- Core Capabilities: scannable bullet-list summary
- Decision Framework: when to use (and when NOT to)
- Success Metrics: quantified outcomes
All 4 Tier 1 personas now match full agency-agents spec.
- Step-by-step GPT creation walkthrough
- How to convert any skill to a Custom GPT
- Adaptation rules (what to remove, keep, add)
- GPT Store optimization tips
- Testing checklist
- Solo Founder (FREE) — AI co-founder for indie hackers and side projects
- Conversion Copywriter (FREE) — marketing copy for landing pages, homepages, pricing
- CTO Advisor (PAID) — tech debt, architecture, team scaling, DORA metrics
Each config includes: name, description, full instructions, conversation starters,
capability toggles. All link back to the repo for attribution.
- Add personas section with 3 persona pages (startup-cto, growth-marketer, solo-founder)
- Add orchestration page with 4 coordination patterns
- Add personas and orchestration cards to homepage
- Add personas and orchestration to navigation
- Update site description and hero text
- All numbers verified and consistent across README + docs
- Add Skills vs Agents vs Personas comparison table
- Add Personas section with 3 available personas
- Add Orchestration section with 4 coordination patterns
- Update star count (2,500 -> 4,400+)
- Add Personas badge
- Update Python tools count (245 -> 254)
- Sharpen intro copy: lead with what's in the box
Lightweight pattern for combining personas (who) with skills (how):
- Solo Sprint: one person switching personas across phases
- Domain Deep-Dive: single persona with stacked skills
- Multi-Agent Handoff: personas reviewing each other's work
- Skill Chain: sequential skill execution without personas
Includes full product launch example (6-week B2B SaaS).
No framework, no dependencies, just structured prompting.
Switching to native skill-creator eval workflow instead.
No external API key dependency needed.
Removes: eval/ directory, skill-eval.yml workflow.
No other files affected.
Add agents/personas/ directory with:
- README.md — what personas are, how to use them, comparison with agents
- TEMPLATE.md — format specification for creating new personas
- startup-cto.md — technical co-founder persona (engineering + strategy)
- growth-marketer.md — bootstrapped growth persona (marketing + analytics)
- solo-founder.md — all-in-one indie hacker persona (cross-domain)
Each persona includes:
- Identity & mindset (personality-driven, not just skill list)
- Curated skill loadouts (primary + secondary)
- Multi-step workflows for common tasks
- Handoff rules for cross-persona collaboration
- Anti-patterns to avoid
Complements existing agents/ structure — personas for role embodiment,
agents for focused task execution.
- Add eval/ directory with 10 pilot skill eval configs
- Add GitHub Action (skill-eval.yml) for automated eval on PR
- Add generate-eval-config.py script for bootstrapping new evals
- Add reusable assertion helpers (skill-quality.js)
- Add eval README with setup and usage docs
Skills covered: copywriting, cto-advisor, seo-audit, content-strategy,
aws-solution-architect, agile-product-owner, senior-frontend,
senior-security, mcp-server-builder, launch-strategy
CI integration:
- Triggers on PR to dev when SKILL.md files change
- Detects which skills changed and runs only those evals
- Posts results as PR comments (non-blocking)
- Uploads full results as artifacts
No existing files modified.
Extend rewrite_relative_links() to also handle `../../path/to/file`
backtick code references, converting them to clickable links showing
parent/filename for context (e.g., product-analytics/SKILL.md).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add rewrite_relative_links() to generate-docs.py that converts ../../
relative paths to absolute GitHub URLs. Sibling agent links (e.g.,
cs-foo.md → cs-bar.md) are preserved as local doc links. Regenerated
all agent pages with fixed references.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update all documentation to reflect 177 skills, 254 tools, 357 references,
16 agents, and 17 commands. Add 4 new skill pages, 1 agent page, and
2 command pages to MkDocs site. Sync Codex (156) and Gemini (218) indexes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Override Material's var(--md-primary-bg-color) which resolves to near-black
in slate scheme, causing dark-on-dark header text.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The style directives used dark theme colors (#161b22, #30363d) making
text invisible in light mode. Removed to let Mermaid use theme defaults.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Create comprehensive plugins page with all 19 plugins (9 domain bundles + 10 standalone)
- Include architecture diagram, compatibility matrix, install commands for all 4 platforms
- Add plugin structure docs, FAQ, and complete reference table
- Add Plugins nav tab in mkdocs.yml
- Add plugins stat card (19) to homepage grid
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix broken dark mode by correcting palette toggle order and setting primary/accent to custom
- Rewrite extra.css with full GitHub Primer color scheme (light: #ffffff/#0969da, dark: #0d1117/#1f6feb)
- Style header, sidebar, buttons, cards, code blocks, and tables to match GitHub aesthetic
- Add Open Graph and Twitter Card meta tags via main.html override
- Add JSON-LD structured data (WebSite + SoftwareApplication schemas)
- Add announcement bar (v2.1.2 release)
- Add custom 404 page with navigation buttons
- Remove inline styles from skills/index.md (moved to extra.css)
- Mobile responsive adjustments for hero sections
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New skills/index.md with full MkDocs Material capabilities:
- Hero section with gradient title and stats grid
- Mermaid architecture diagram showing skill package pattern
- 9 domain cards with skill counts and browse buttons
- Tabbed skills-by-category with expandable tables (173 skills)
- Pie chart showing Python tools distribution across domains
- 4-step "How Skills Work" explainer
- Multi-platform Quick Install tabs
- for-the-badge style shields.io badges in README.md
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- cs- prefix for slug conflicts only (ClawHub registry, not repo)
- No paid/commercial service dependencies
- Rate limit: 5 new skills/hour
- plugin.json schema enforcement
- Version must match repo release
Add slash command to list and delete merged branches (local + remote),
keeping only main, dev, and gh-pages. Includes confirmation step before
remote deletion.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Integrates skill-security-auditor as automated CI check per #241:
- Detects which skill directories changed in the PR (diff-based)
- Runs skill_security_auditor.py --strict --json on each changed skill
- Posts findings as a formatted PR comment with severity breakdown
- Blocks merge on FAIL verdict (critical findings)
- Skips non-skill paths (.github, docs, scripts, etc.)
- Updates existing comment on re-push (no comment spam)
- Concurrency grouping prevents parallel runs on same PR
Add video intelligence and content analysis skill using Memories.ai LVMM.
Enables agents to discover videos on TikTok/YouTube/Instagram, analyze
content, summarize meetings, and build searchable knowledge bases across
multiple videos.
Features:
- 21 API commands organized into workflow-oriented reference guides
- Quick video analysis and persistent knowledge base modes
- Social media video research and competitor analysis
- Meeting and lecture note extraction
- Cross-video semantic search and Q&A
- Memory management for text insights
Skill includes:
- Comprehensive SKILL.md following repository standards
- API command reference documentation
- Use cases and examples for 6 primary workflows
- Example workflow script demonstrating competitive analysis
Skill repo: https://github.com/kennyzheng-builds/seek-and-analyze-video
Co-authored-by: kennyzheng-builds <kennyzheng-builds@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Root cause: CLI tools (ai-agent-skills, agent-skills-cli) look for SKILL.md
at the specified install path. 7 of 9 domain directories were missing this
file, causing "Skill not found" errors for bundle installs like:
npx ai-agent-skills install alirezarezvani/claude-skills/engineering-team
Fix:
- Add root-level SKILL.md with YAML frontmatter to 7 domains
- Add .codex/instructions.md to 8 domains (for Codex CLI discovery)
- Update INSTALLATION.md with accurate skill counts (53→170)
- Add troubleshooting entry for "Skill not found" error
All 9 domains now have: SKILL.md + .codex/instructions.md + plugin.json
Closes#301
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Update skill count to 170, Python tools to 213, references to 314 across all docs
- Regenerate all 170 skill doc pages from latest SKILL.md sources
- Update CLAUDE.md with v2.1.1 highlights, accurate architecture tree, and roadmap
- Update README.md badges and overview table
- Update marketplace.json metadata description and version
- Update mkdocs.yml, index.md, getting-started.md with correct numbers
Reverts two overly aggressive audit changes:
- Restored content-creator, demand-gen, fullstack-engineer, aws-architect,
product-manager, scrum-master, skill-security-auditor to marketplace
- Reverted playwright-pro plugin.json name back to 'pw' (intentional short name)
- Added frontmatter to 34 skills that were missing it entirely (0% Tessl score)
- Fixed name field format to kebab-case across all 169 skills
- Resolves#284
Injects the raw Google Analytics snippet via theme override so Google
Search Console can verify site ownership. Removes the duplicate
Material built-in analytics config.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sync CLAUDE.md with actual repository state: add Engineering POWERFUL tier
(25 skills), update all skill counts, add plugin registry references, and
replace stale sprint section with v2.0.0 version info.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: restructure README.md — 2,539 → 209 lines (#247)
- Cut from 2,539 lines / 73 sections to 209 lines / 18 sections
- Consolidated 4 install methods into one unified section
- Moved all skill details to domain-level READMEs (linked from table)
- Front-loaded value prop and keywords for SEO
- Added POWERFUL tier highlight section
- Added skill-security-auditor showcase section
- Removed stale Q4 2025 roadmap, outdated ROI claims, duplicate content
- Fixed all internal links
- Clean heading hierarchy (H2 for main sections only)
Closes#233
Co-authored-by: Leo <leo@openclaw.ai>
* fix: enhance 5 skills with scripts, references, and Anthropic best practices (#248)
* fix(skill): enhance git-worktree-manager with scripts, references, and Anthropic best practices
* fix(skill): enhance mcp-server-builder with scripts, references, and Anthropic best practices
* fix(skill): enhance changelog-generator with scripts, references, and Anthropic best practices
* fix(skill): enhance ci-cd-pipeline-builder with scripts, references, and Anthropic best practices
* fix(skill): enhance prompt-engineer-toolkit with scripts, references, and Anthropic best practices
* docs: update README, CHANGELOG, and plugin metadata
* fix: correct marketing plugin count, expand thin references
---------
Co-authored-by: Leo <leo@openclaw.ai>
---------
Co-authored-by: Leo <leo@openclaw.ai>
* docs: restructure README.md — 2,539 → 209 lines (#247)
- Cut from 2,539 lines / 73 sections to 209 lines / 18 sections
- Consolidated 4 install methods into one unified section
- Moved all skill details to domain-level READMEs (linked from table)
- Front-loaded value prop and keywords for SEO
- Added POWERFUL tier highlight section
- Added skill-security-auditor showcase section
- Removed stale Q4 2025 roadmap, outdated ROI claims, duplicate content
- Fixed all internal links
- Clean heading hierarchy (H2 for main sections only)
Closes#233
Co-authored-by: Leo <leo@openclaw.ai>
* fix: enhance 5 skills with scripts, references, and Anthropic best practices (#248)
* fix(skill): enhance git-worktree-manager with scripts, references, and Anthropic best practices
* fix(skill): enhance mcp-server-builder with scripts, references, and Anthropic best practices
* fix(skill): enhance changelog-generator with scripts, references, and Anthropic best practices
* fix(skill): enhance ci-cd-pipeline-builder with scripts, references, and Anthropic best practices
* fix(skill): enhance prompt-engineer-toolkit with scripts, references, and Anthropic best practices
* docs: update README, CHANGELOG, and plugin metadata
* fix: correct marketing plugin count, expand thin references
---------
Co-authored-by: Leo <leo@openclaw.ai>
---------
Co-authored-by: Leo <leo@openclaw.ai>
* fix(skill): enhance git-worktree-manager with scripts, references, and Anthropic best practices
* fix(skill): enhance mcp-server-builder with scripts, references, and Anthropic best practices
* fix(skill): enhance changelog-generator with scripts, references, and Anthropic best practices
* fix(skill): enhance ci-cd-pipeline-builder with scripts, references, and Anthropic best practices
* fix(skill): enhance prompt-engineer-toolkit with scripts, references, and Anthropic best practices
* docs: update README, CHANGELOG, and plugin metadata
* fix: correct marketing plugin count, expand thin references
---------
Co-authored-by: Leo <leo@openclaw.ai>
- Cut from 2,539 lines / 73 sections to 209 lines / 18 sections
- Consolidated 4 install methods into one unified section
- Moved all skill details to domain-level READMEs (linked from table)
- Front-loaded value prop and keywords for SEO
- Added POWERFUL tier highlight section
- Added skill-security-auditor showcase section
- Removed stale Q4 2025 roadmap, outdated ROI claims, duplicate content
- Fixed all internal links
- Clean heading hierarchy (H2 for main sections only)
Closes#233
Co-authored-by: Leo <leo@openclaw.ai>
description: Run the full 8-phase plugin audit pipeline on a skill directory.
---
Run the comprehensive plugin audit pipeline on the skill at `$ARGUMENTS`. If no argument provided, ask the user for the skill path.
Execute all 8 phases sequentially. Auto-fix non-critical issues. Only prompt the user for critical decisions (external dependencies, security findings, breaking changes).
## Phase 1: Discovery
1. Verify `$ARGUMENTS` exists and contains `SKILL.md`. If not, error and stop.
description: Scan and optimize docs for SEO — meta tags, readability, keywords, broken links, sitemap.
---
Run the SEO auditor on documentation files. Target path: `$ARGUMENTS` (default: all docs/ and root README.md).
If `$ARGUMENTS` is `--report-only`, scan without making changes.
Execute all 7 phases. Auto-fix non-destructive issues. Never change URLs. Preserve content on high-ranking pages.
## Phase 1: Discovery
Find all target markdown files:
- `docs/**/*.md` — all documentation pages
- `README.md` files in domain root directories
- If `$ARGUMENTS` specifies a path, scope to that path only
For each file, extract current state: `title:` frontmatter, `description:` frontmatter, H1, H2s, word count, link count. Store as baseline for the report.
description: Update all the documentation related files.
---
After completing any skill creation, agent creation, or command creation in this repository, run the full post-creation sync pipeline below. Execute every step — never skip a task. If something is unclear or a step fails, ask the user for guidance before continuing.
---
## Step 1: Inventory what changed
Scan the working tree to identify what was added, modified, or deleted:
```bash
git status --short
```
Classify each change:
- **New skill** — a new folder containing `SKILL.md` under a domain directory
- **New agent** — a new `.md` file under `agents/`
- **New command** — a new `.md` file under `commands/`
Report the inventory to the user before proceeding.
---
## Step 2: Cross-platform CLI sync
Ensure all platforms have compatible versions of every skill, agent, and command.
### 2a. Codex CLI
Run the Codex sync script to regenerate symlinks and the skills index:
```bash
python3 scripts/sync-codex-skills.py --verbose
```
Verify the output: check `.codex/skills-index.json` for correct `total_skills` count and that new skills appear in the index.
### 2b. Gemini CLI
Run the Gemini sync script:
```bash
python3 scripts/sync-gemini-skills.py --verbose
```
Verify: check `.gemini/skills-index.json` for correct total count. New skills, agents, and commands should all have corresponding entries and symlinks under `.gemini/skills/`.
### 2c. OpenClaw
Verify that `scripts/openclaw-install.sh` will pick up the new skills. The install script uses the same directory structure, so no separate sync is needed — but confirm the new skill directories are not excluded by any filter in the script.
Report sync results (skill counts per platform) to the user.
---
## Step 3: Claude Code plugin marketplace
### 3a. Domain-level plugin.json
For each domain that had changes, update the domain's `.claude-plugin/plugin.json`:
- Update `description` with accurate skill/tool/reference counts
- Update `version` if needed
- Verify `source` paths are correct
Domain plugin.json locations:
- `marketing-skill/.claude-plugin/plugin.json`
- `engineering-team/.claude-plugin/plugin.json`
- `engineering/.claude-plugin/plugin.json`
- `product-team/.claude-plugin/plugin.json`
- `c-level-advisor/.claude-plugin/plugin.json`
- `project-management/.claude-plugin/plugin.json`
- `ra-qm-team/.claude-plugin/plugin.json`
- `business-growth/.claude-plugin/plugin.json`
- `finance/.claude-plugin/plugin.json`
### 3b. Root marketplace.json
Update `.claude-plugin/marketplace.json`:
- Update the top-level `metadata.description` with accurate total counts (skills, tools, references, agents, commands)
- If a new individual skill plugin entry is needed (for standalone install), add it to the `plugins` array following the existing pattern
- Update `keywords` arrays if new domains or capabilities were added
- Verify all `source` paths point to valid directories
---
## Step 4: Update documentation files
### 4a. Root CLAUDE.md
Update `/CLAUDE.md` (the root project instructions):
- Available Bundles table (skill counts per bundle)
- Python Tools section (tool count)
- FAQ answers (any count references)
---
## Step 5: Regenerate GitHub Pages
Run the docs generation script to create/update all MkDocs pages:
```bash
python3 scripts/generate-docs.py
```
This generates pages for:
- Every skill (from SKILL.md files)
- Every agent (from agents/*.md)
- Every command (from commands/*.md)
- Index pages for skills, agents, and commands sections
### 5a. Update mkdocs.yml navigation
Open `mkdocs.yml` and update the `nav:` section:
- Add new skill pages under the correct domain section
- Add new agent pages under the Agents section
- Add new command pages under the Commands section
- Update `site_description` with current counts
### 5b. Verify the build
```bash
python3 -m mkdocs build 2>&1 | tail -5
```
The build should complete without errors. Warnings about relative links in SKILL.md files are expected and can be ignored (they reference skill-internal paths like `references/` and `scripts/`).
Report the build result and page count to the user.
---
## Step 6: Consistency verification
Run a final consistency check across all updated files:
1. **Count consistency** — Verify the same skill/agent/command/tool counts appear in:
- Root CLAUDE.md
- Root README.md
- docs/index.md
- docs/getting-started.md
- .claude-plugin/marketplace.json
2. **Path validation** — Verify all `source` paths in marketplace.json point to existing directories
3. **New script verification** — If new Python scripts were added, verify they run:
```bash
python3 path/to/new/script.py --help
```
4. **Frontmatter check** — Verify all new SKILL.md, agent, and command files have valid YAML frontmatter with at minimum `name` and `description` fields
Report any inconsistencies found and fix them before finishing.
---
## Step 7: Summary report
Present a summary to the user:
| Item | Status |
|------|--------|
| New skills added | [list] |
| New agents added | [list] |
| New commands added | [list] |
| Codex CLI sync | count |
| Gemini CLI sync | count |
| OpenClaw compatible | yes/no |
| Marketplace updated | yes/no |
| CLAUDE.md files updated | [count]/[total] |
| README.md updated | yes/no |
| GitHub Pages regenerated | [page count] pages |
| MkDocs build | pass/fail |
| Consistency check | pass/fail |
Ask the user if they want to commit and push the changes.
"shortDescription":"388 production-ready skills for AI coding agents across 20 domains",
"longDescription":"The largest open-source skills library for AI coding agents. 388 skills covering engineering (architecture, DevOps, security, AI/ML, agent tooling), marketing (SEO, AEO, CRO, content), product management, C-level advisory, regulatory compliance (ISO 13485, SOC 2, GDPR), project management, research and research operations, business operations, commercial, finance, and personal productivity. Includes 727 stdlib-only Python CLI tools, 842 reference guides, 118 orchestration agents, and 150 slash commands. Works with Codex, Claude Code, Gemini CLI, Cursor, Hermes Agent, Mistral Vibe, and 7 more tools.",