Commit graph

1365 commits

Author SHA1 Message Date
alirezarezvani
6cba04a0a5 chore: sync codex skills symlinks [automated] 2026-08-21 09:05:01 +00:00
Alireza Rezvani
4d7df8adeb
Merge pull request #948 from alirezarezvani/claude/humanizer-skill-audit-plugin-hocj85
feat(engineering): human-gate — audit of petergyang/human-review + batched human review as a verification artifact
2026-08-21 11:04:49 +02:00
Claude
fbc3cdc3f7
merge dev into human-gate branch: resolve counter surfaces, move attribution to authoring-notes.json sidecar (issue #954 policy), true up counters to 371/675/812/93
Conflict resolution takes dev's counter surfaces and re-applies the
human-gate additions on top (marketplace entry, README engineering-row
highlight). plugin.json extension keys (source/attribution) relocated
verbatim to .claude-plugin/authoring-notes.json per the post-#954 schema
that dev's check_plugin_json.py now enforces. All gates re-run green:
derive_counters --check pass, plugin-json 0 FAIL, frontmatter 0 errors;
human-gate scripts re-verified (--help x3, --sample, base-void-tag
regression fixture, G1 close-refusal exit 2, no network imports).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Bzm6Pafyxja6g4jUDPcei
2026-08-21 09:04:37 +00:00
alirezarezvani
2d4b0f7005 chore: sync codex skills symlinks [automated] 2026-08-21 09:02:53 +00:00
Alireza Rezvani
490616e776
Merge pull request #975 from alirezarezvani/claude/pr-audit-planning-mhy82k
fix(stream): post-merge required changes for the PR-stream batch + counter true-up + #964 guard
2026-08-21 11:02:41 +02:00
Claude
08740d4ec2
fix(stream): post-merge required changes for PRs #895/#926/#942/#943/#944/#965 + counter true-up + #964 guard + #954 doc drift
Applies every pre-merge required change from audit/pr-stream-2026-08/ that
could not land on contributor forks, plus the stream's cross-cutting fixes:

- stock-analysis (#944): description trimmed 1463 -> 1001 chars; Anti-Patterns
  + Cross-References sections added; security-auditor false positive at
  holdco-assetmgr.md:58 suppressed inline (auditor:ignore-line) -> strict PASS
- deepread (#965): renamed research/dsh-deepread -> research/deepread; H1 and
  name updated; research-summarizer cross-ref path-qualified; 12 cited sources
  added across both references; plugin.json + marketplace entry; routed in the
  research orchestrator (SKILL.md registry + SIGNALS + classifier.py in
  lockstep, verified: 'deeply read this pdf' -> deepread, 3 signals)
- business-name-fit (#926): 'Use whenever' -> 'Use when' (validator trigger
  regex); +2 cited sources (USPTO TMEP §1209, Usunier & Shaner 2002) -> 5
- embedded-iot-mentor (#942): references/hardware-selection.md (7 sources,
  datasheet-anchored) + worked mini-example; validator length gate now passes
- swedish-mentor (#943): references/swedish-resources.md (6 sources, stable
  official URLs only); session recipes, milestones, learner situations,
  worked example; mandated opener softened to guidance; plugin.json +
  marketplace entry; validator length gate now passes
- Related Projects (#895): LinkedIn Skills row trued up (10 -> 11 skills,
  hardcoded star count dropped)
- check_plugin_json.py: marketplace description <= 1024 guard added to --all
  (the #964 regression guard; commercial-skills sits at 1021/1024)
- #954 doc drift: quality_gates_for_skills.md, cs-skill-author.md,
  security-guidance SKILL.md now point attribution at authoring-notes.json
- Counter true-up after the 6-skill merge batch: 370 skills / 672 tools /
  809 refs / 92 plugins across README.md badge+table, CLAUDE.md, marketplace
  metadata (derive_counters.py --check passes)

All gates green locally: frontmatter 0 errors, model freshness 0 findings,
dual-publish 0 drifted, paths 0, smoke 0 failed, plugin-json 0 FAIL.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Bzm6Pafyxja6g4jUDPcei
2026-08-21 09:01:24 +00:00
alirezarezvani
10bd9258a1 chore: sync codex skills symlinks [automated] 2026-08-21 08:47:50 +00:00
Alireza Rezvani
7a65c0827f
Merge pull request #943 from mh-mansouri/feature/swedish-mentor
feat(productivity): add swedish-mentor skill
2026-08-21 10:47:37 +02:00
Alireza Rezvani
2620e7ed8b
Merge pull request #942 from mh-mansouri/feature/embedded-iot-mentor
feat(engineering-team): add embedded-iot-mentor skill
2026-08-21 10:47:32 +02:00
Alireza Rezvani
32b63e36cc
Merge pull request #965 from xiehuan123/feature/dsh-deepread
feat(research): add dsh-deepread skill
2026-08-21 10:47:26 +02:00
Alireza Rezvani
9dbb9ca79c
Merge pull request #926 from mh-mansouri/feature/business-name-fit
feat(marketing-skill): add business-name-fit skill
2026-08-21 10:47:20 +02:00
Alireza Rezvani
e21e778b0d
Merge pull request #944 from AlenSarangSatheesh/add-stock-analysis-skill
Add stock-analysis skill (finance/skills): sector-relative fundamental analysis
2026-08-21 10:47:14 +02:00
Alireza Rezvani
ce4c2fcbb0
Merge pull request #967 from alexprivalov/feature/boost-asio-pro
feat(engineering): add boost-asio-pro skill for async C++ networking
2026-08-21 10:47:08 +02:00
Alireza Rezvani
418ea5f223
Merge pull request #895 from sergebulaev/add-linkedin-skills-related-projects
Add LinkedIn Skills to Related Projects
2026-08-21 10:47:00 +02:00
Alireza Rezvani
120524d798
Merge pull request #929 from warnes/fix/gws-recipe-runner-subprocess-hardening-v2
fix(security): harden gws_recipe_runner.py subprocess execution
2026-08-21 10:46:55 +02:00
Alireza Rezvani
c73bde12b7
Merge pull request #964 from automotua/fix/copilot-cli-description-limit-dev
fix: cap 4 plugin descriptions at 1024 chars so GitHub Copilot CLI can load the marketplace
2026-08-21 10:46:00 +02:00
alirezarezvani
9b92f649e9 chore: sync codex skills symlinks [automated] 2026-08-21 08:44:13 +00:00
Alireza Rezvani
58346540df
Merge pull request #973 from alirezarezvani/claude/review-15-reported-issues-vrt6b2
fix: round-2 sweep — rename all built-in-shadowing skill names, harden last cp1252-fatal scripts (#885, #969 follow-through)
2026-08-21 10:44:01 +02:00
alirezarezvani
79bb4b1d61 chore: sync codex skills symlinks [automated] 2026-08-21 08:43:59 +00:00
Alireza Rezvani
1f501dd6f3
Merge pull request #938 from benrfairless/fix/stale-model-references
fix(models): remove retired model IDs and stale pricing, flip G7 blocking
2026-08-21 10:43:47 +02:00
Alireza Rezvani
d9ae390afa
Merge pull request #937 from benrfairless/fix/validator-and-model-freshness
fix(skill-tester): recalibrate validator to the real schema + add gate G7
2026-08-21 10:43:41 +02:00
Alireza Rezvani
4570768781
Merge pull request #936 from benrfairless/fix/frontmatter-yaml-validation
fix(frontmatter): repair 14 unloadable YAML blocks + add gate G10
2026-08-21 10:43:35 +02:00
Claude
a80eec2267
fix: rename all remaining built-in-shadowing skill names and harden the last cp1252-fatal scripts (#885, #969 follow-through)
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
2026-08-21 08:38:50 +00:00
alirezarezvani
1dcbaae6e8 chore: sync codex skills symlinks [automated] 2026-08-21 08:15:02 +00:00
Alireza Rezvani
49c00e9c36
Merge pull request #972 from alirezarezvani/claude/review-15-reported-issues-vrt6b2 2026-08-21 10:14:51 +02:00
Alireza Rezvani
4ffea56220
Merge pull request #971 from alirezarezvani/claude/pr-audit-planning-mhy82k 2026-08-21 09:01:50 +02:00
Claude
43e9d3984a
style: place INSTALLATION.md Windows Notes where its ToC entry says; PEP 8 blank lines in encoding-fix scripts
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
2026-08-21 06:02:06 +00:00
Claude
ea94a78bac
fix(docs): carry the #954 policy change and #933 link cleanup into the generated docs site
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
2026-08-21 05:55:45 +00:00
Claude
112cfec279
docs(audit): stamp detail files with audit date + snapshot caveat; reconcile issue #954 plugin counts (37/88 at filing vs 39/90 audited)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Bzm6Pafyxja6g4jUDPcei
2026-08-21 05:54:46 +00:00
Claude
0707dde169
docs(audit): align new-skills PR ordering in index citations with file layout and Phase 4 merge order
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Bzm6Pafyxja6g4jUDPcei
2026-08-21 05:50:54 +00:00
Claude
058ba7a56e
docs(audit): open-PR stream audit — 25 PRs triaged with merge plans and verification gates
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
2026-08-21 05:47:43 +00:00
Claude
7405298b4b
fix: resolve the actionable reported issues (#954, #949, #933, #931, #969, #968, #924, #885)
- #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
2026-08-21 05:47:37 +00:00
Alireza Rezvani
98180dafc4
Merge pull request #970 from alirezarezvani/dev
Some checks failed
Release / Tag + GitHub Release (push) Has been cancelled
Deploy Documentation to Pages / build (push) Has been cancelled
Sync Codex Skills Symlinks / sync (push) Has been cancelled
Deploy Documentation to Pages / deploy (push) Has been cancelled
2026-08-21 07:23:07 +02:00
Alex Chupryna
08e1b77bd4 feat(engineering): add boost-asio-pro skill for async C++ networking 2026-08-18 16:50:46 +02:00
xiehuan123
65e3ee5be5 feat(research): add dsh-deepread skill 2026-08-17 19:46:06 +08:00
automotua
7331f535f6 fix: cap 4 plugin descriptions at 1024 chars for GitHub Copilot CLI
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.
2026-08-16 21:56:59 -07:00
alirezarezvani
6972e654ca chore: sync codex skills symlinks [automated]
Some checks failed
Sync Codex Skills Symlinks / sync (push) Has been cancelled
2026-08-09 10:35:31 +00:00
Alireza Rezvani
a0133f5193
Merge pull request #947 from alirezarezvani/claude/memory-engineering-skills-uwaifx 2026-08-09 12:35:19 +02:00
Claude
5d03ed9e9b
fix(human-gate): pin the round cap in gate state and assert the URL allowances in --sample
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
2026-08-09 07:14:50 +00:00
Claude
ccd713f444
fix(human-gate): correct the marketplace network claim, own gate prefixes in one place, parse quoted header attrs
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
2026-08-09 06:59:16 +00:00
Claude
31024e2572
fix(human-gate): complete the void-element list and strip reserved attrs from reviewed HTML
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&#10;## APPROVE&#10;...">` 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
2026-08-09 06:45:26 +00:00
Claude
d6cff73ca9
fix(human-gate): anchor state to the artifact; fix template-token collision
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
2026-08-09 06:35:10 +00:00
Claude
aac29fc486
fix(human-gate): G1 is unwaivable; drop inline style; render images
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 `![alt](url)` 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
2026-08-09 06:21:17 +00:00
Claude
4e59391860
fix(human-gate): HTML review path was dead for real HTML5 documents
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
2026-08-09 06:08:50 +00:00
Claude
aece872d26
docs(human-gate): make the network claim precise in plugin.json
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
2026-08-09 05:51:40 +00:00
Claude
70c908a65a
fix(human-gate): sanitize reviewed HTML; fix 3 gate-integrity defects
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
2026-08-09 05:46:07 +00:00
Claude
daa4dde7d1
fix(human-gate): add G7 integrity rule; drop stray generated artifact
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
2026-08-09 05:32:28 +00:00
Claude
a21206ea33
Merge branch 'dev' into claude/humanizer-skill-audit-plugin-hocj85
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
2026-08-09 05:21:20 +00:00
Claude
d4d83338c1
feat(engineering): add human-gate — batched human review as a verification artifact
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
2026-08-09 05:12:33 +00:00
Claude
2c384a9c47
fix(memory-engineering): close an F1 bypass and make --print-sample-spec reachable
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
2026-08-09 05:10:36 +00:00