mirror of
https://github.com/AgriciDaniel/claude-blog.git
synced 2026-09-19 03:32:21 +08:00
main
32 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
84f7abf050 |
fix(audit): enforce release verification gates
Close the deterministic gaps found by the post-release Secretary audit.\n\n- enforce the executable market-ready Brain gate on every main push\n- analyze rendered HTML metadata and structure without false omissions\n- correct the shipped audit status and record reproducibility limits\n- add durable Secretary and per-post audit reports\n- clean pre-existing analyzer lint findings in the touched module\n\nThe existing untracked outputs directory was not staged or modified. GitHub\nbacklog triage, private CI billing, signing-key registration, and website\npublication are handled as separate verified external steps.\n\nVerified: 347 root tests passed with 1 intentional skip, and 26 Brain\ntests passed. The executable Brain audit scored 100 and required\nmarket-ready status. Secret scanning passed with 218 adjudicated and zero\nunexpected findings. Prose lint, Ruff, actionlint 1.7.12, consistency for\n193 references, the 24-surface public validator, source verification for\n125 records, and git diff checks passed.\n\nCo-Authored-By: GPT-5.6 Sol <noreply@openai.com> |
||
|
|
7b6ca107ad |
release: v2.2.0 - verified currentness and Brain release
Publish the audited Google-currentness, analyzer, installer, security, and bundled Brain improvements as claude-blog v2.2.0. Align every canonical version surface, citation date, pinned install example, installer digest, and release validator. - Date and finalize the v2.2.0 changelog notes. - Keep the bundled Brain at its independently versioned v0.2.0 release. - Fix PowerShell local-checkout detection by using PSScriptRoot. - Add regression coverage for the Windows installer source boundary. Verified: - Root tests: 344 passed, 1 skipped. - Brain tests: 26 passed. - Brain audit: market-ready, score 100, no warnings. - Brainstein strict audit: SSS+, score 100, no warnings. - Windows smoke: 32 skills and 5 agents installed, then removed cleanly while shared credentials remained. - Google live and offline currentness checks passed. - All 125 Brain source records passed offline verification. - Public release, plugin, lock, prose, secret, consistency, actionlint, Bash, PowerShell, and diff checks passed. Co-Authored-By: GPT-5 <noreply@openai.com> |
||
|
|
f55b6bb682 |
fix(ci): update setup-node to Node 24 runtime
Replace the deprecated setup-node v4 action pin with the official v7.0.0 commit, which uses the supported Node 24 action runtime. Extend exact-SHA regression coverage and secret-scan adjudication for the reviewed pin. This changes only the GitHub Action runtime and its safeguards. It does not change the project Node version or application dependencies. Verified: - Root tests: 343 passed, 1 skipped. - actionlint 1.7.12 passed with zero findings. - Secret scan passed with 218 adjudicated findings and none unexpected. - Public release, consistency, prose, and diff checks passed. Co-Authored-By: GPT-5 <noreply@openai.com> |
||
|
|
87872da7d3 |
feat(audit): harden source currentness and release gates
Verify every open pull request and issue against current code and primary sources. Refresh Google guidance and promote the bundled Brain only after deterministic and independent audits pass. - Add live and offline Google currentness enforcement. - Add complete Brain source-review records and public projection gates. - Fix analyzer, installer, dependency, and security regressions. - Record the evidence-led PR and issue disposition in release notes. This does not merge or close external pull requests or issues. Antivirus vendor reclassification remains external. Verified: - Root tests: 343 passed, 1 skipped. - Brain tests: 26 passed. - Brain audit: market-ready, score 100, no warnings. - Brainstein strict audit: SSS+, score 100, no warnings. - Google live and offline currentness checks passed. - Secret scan passed with 217 adjudicated findings and none unexpected. - Public release, consistency, plugin, lock, prose, and actionlint gates passed. Co-Authored-By: GPT-5 <noreply@openai.com> |
||
|
|
0a006be88f | release(public-v2.1.1): normalize distribution surfaces | ||
|
|
bab0d5c957 | release(v2.1.0): align Google guidance and safeguards | ||
|
|
2020316123 |
fix(audit): grand-audit-2 remediation, security + currency + drift
Independent re-audit (6 Codex slices) of shipped v1.11.0 surfaced real issues the first pass missed. Remediated across 54 files: Security: SSRF DNS-rebinding revalidation (generate_hero, blog_preflight); symlink TOCTOU on chart/hero/preflight/image writers (O_NOFOLLOW atomic); path traversal in blog-notebooklm/blog-google/blog-audio wrapper run.py; preflight allowlist-before-safety bypass (Gate 5); unescaped untrusted text to XSS in discourse + schema JSON-LD; arbitrary file read/write in audio/indexing/gsc batch flows. Correctness: validate_image_setup args reassignment crash; chart AttributeError on malformed input; preflight accepting 999/100 scores. Currency (verified vs live Google docs): Indexing API scoped to JobPosting/livestream only (was told for generic blog posts in 6 files); gemini-3.1-flash-image stable + gemini-3.1-flash-tts-preview; nanobanana preview-shutdown warnings. Hygiene: SKILL.md trimmed 470->330 lines (under token budget); count / version / command-contract coherence across README/CLAUDE/docs/.github; stale install.ps1 SHA; 10 new SSRF/injection/symlink regression tests. 252 tests pass, prose lint + plugin validate green, no secret leaks. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
234c8e595c |
chore(repo): declutter root by relocating community and secondary docs
Move CODE_OF_CONDUCT.md, CONTRIBUTING.md, SECURITY.md, and SUPPORT.md to .github/ (GitHub still surfaces the Contributing / Code of conduct / Security tabs), and RELEASE_CHECKLIST.md, PRIVACY.md, CONTRIBUTORS.md, and TODO.md to docs/. Root drops from 26 to 18 files. Update every live reference (README, docs, PR template, CLAUDE.md tree, NOTICE), the lint_prose root basename list, and the SECURITY.md path in tests. Required files (LICENSE, NOTICE, CITATION.cff, pyproject.toml, installers, lockfiles, dotfiles) stay at root. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
1567ed307b |
fix(triage): public-repo issue/PR remediation (#22, #33) + adopt hygiene idea from #38
Reviewed all open issues and PRs on the public mirror AgriciDaniel/claude-blog and applied the legitimate fixes to the private repo. Rejected the bad ones. #22 (org install blocked): plugin.json description was 809 chars (our v1.11.0 work had expanded it past the 500-char registry cap; claude plugin validate does not catch this). Trimmed to 499 chars with accurate counts and added tests/test_plugin_manifest.py as a permanent guard. #38 (mostly personal deploy+content PR): rejected the deploy pipeline, brand files, and blog content. Adopted only the one generic idea, reimplemented cleanly: scripts/blog_hygiene.py, an optional non-blocking helper that adds loading="lazy" to images and inserts a Table of Contents on posts over 2000 words. Language-neutral, dry-run by default with --apply, symlink-safe, JSON output, 8 tests. Wired as an explicitly optional pre-Gate-3 step (does not alter the tested delivery contract). Its security fix (exact-hostname allowlist) was already present via the audit. #33 (Kaspersky heuristic false positive on install.ps1): documented Windows install now downloads then runs the script (irm -OutFile; pwsh -File) instead of iex(irm), which is safer and avoids the heuristic. Added a SECURITY.md "Antivirus false positives" section. Dependabot: superseded by current ranges; the CI action bumps are intentionally not adopted (workflows are SHA-pinned, stronger than tag refs). Raised the one legit floor: google-auth-oauthlib 1.0.0 -> 1.3.1. Not adopted: #40 (ownership hijack re-attributing the plugin to ungthien-software) and #37 (injects the third-party Xquik-dev/hermes-tweet tool into SKILL.md). Close comments drafted for the maintainer to post; public repo left untouched. Verify: 242 tests pass, prose lint clean, claude plugin validate passes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
5c21c90bc0 |
fix(audit): grand-audit remediation across all 32 sub-skills + v1.11.0
A 17-agent Codex (gpt-5.5, xhigh) audit of the skill repo and brain vault surfaced 672 findings; 11 file-disjoint Codex fix agents remediated them, folding in best-practice ports from Gogh and the Fable-5 brain. Security: SSRF guards (generate_hero redirect bypass, blog_preflight HEAD, nlp_analyze, all URL-fetch sub-skills), XSS escaping (blog_render raw HTML + attrs, audio embed, google_report, video srcdoc, Hugo unsafe), path/symlink write confinement, API-key redaction in logs, agent tool least-privilege. Delivery contract: deterministic strict gates, review nonce moved out of the draft dir, broken images/links now block, first-failure halt, repair-only iteration counting. Currency (2026): FAQPage + E-E-A-T reframed to Google guidance, Google-Extended corrected, GA Gemini image IDs and 3.1 TTS, MCP schema alignment, Ads v24.2. Consistency: one 30/25/15/15/15 scoring rubric, fixed broken reference/template paths, added missing scripts (discourse_research.py, sync_flow.py), Gogh deterministic chart-SVG CLI, restored orchestrator Untrusted-Data Contract. Packaging: v1.11.0 across plugin.json/pyproject/CITATION/README/CHANGELOG, 217->232 tests, installer defaults to AI-Marketing-Hub/claude-blog. Verify: 232 tests pass, prose lint clean, claude plugin validate passes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
1c9cdc6927 |
fix(audit): pass 1 - currency reframe + image models + script robustness
Systemic (skills/blog/SKILL.md + 12 references): - S1: reframe Dec 2025 -> May 2026 Core as latest; GEO/AEO = SEO (one discipline). - S2: FAQ rich results retired 2026-05-07 -> FAQPage is an entity/AI-citation signal only, never a Google rich result; Article/Person/Organization/Breadcrumb is the 2026 priority. - S3: removed the +28% sponsored stat + qualified quarantined/single-source GEO stats. - S4: reconciled answer-first length, question-heading target (40-60%), furthermore/moreover conflict, and the news word floor. Image (B2): default model gemini-3.1-flash-image-preview (shut down 2026-06-25) -> GA gemini-3.1-flash-image + gemini-3-pro-image; Imagen 4 marked deprecated; validator warns on deprecated/preview models. Scripts (B1,B3,B4 + review bugs): pagespeed_check.py KeyError (audit_details init); ask_question.py import os; content_decay NaN/missing-metric/markdown-escape; quality_gate symlink bypass + UTF-8; ai_citation_score UTF-8; style_learn unicode + empty-corpus. +11 tests. Docs: broken template filenames (how-to-guide/faq-knowledge), ARCHITECTURE counts (31/206), CLAUDE.md stale annotations. 217 tests green (was 206), lint clean, plugin validates. Authored by Codex gpt-5.5/xhigh + chair; verified by the orchestrator. Local only. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
283ee1fac7 |
feat: 4 Phase-2 features (AI-citation scoring, style learning, content decay, quality gate)
- scripts/ai_citation_score.py + skills/blog-geo integration: 0-100 AI citation probability per post with per-engine breakdown (ai_overview/perplexity/chatgpt). - skills/blog-style + scripts/style_learn.py: /blog style learn - author voice profile from 5-10 posts (feeds blog-write, blog-persona). - skills/blog-decay + scripts/content_decay.py: /blog decay - flag 20%+ QoQ traffic decline from GSC exports with refresh/consolidate/prune actions. - scripts/quality_gate.py + .pre-commit-config.yaml: block commits of blog posts scoring below 70 (reuses analyze_blog). - uninstall.sh/.ps1 synced with the 4 new scripts; new SKILL.md carry license. Feature code authored by Codex gpt-5.5/xhigh; verified by the orchestrator with the full suite (206 tests green) and end-to-end smoke tests of all 4 scripts. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
f9ff6eeab1 |
fix(security): refuse redirects + tighten scheme check in Gate 5 (VULN-804+VULN-002)
Two related Gate 5 hardenings: VULN-804 (MEDIUM): _http_head followed redirects by default. A draft containing <a href="http://attacker.example/redirect?to=169.254.169.254"> would let preflight probe internal hosts during the link-integrity check (timing oracle, port-scan amplifier, DNS exfil channel). Fix: introduce _PreflightNoRedirectHandler that returns None on every 30x; wire _http_head to use _PREFLIGHT_NO_REDIRECT_OPENER instead of the default urllib opener. VULN-002 (LOW): og:image check used startswith("http") which matched httpX (and anything else starting with 'http'). Fix: tuple form startswith(("http://", "https://")). Plus defense-in-depth: _http_head now refuses non-http(s) schemes inline rather than relying on every caller to filter. Changes: * scripts/blog_preflight.py: - Add _PreflightNoRedirectHandler class + module-level _PREFLIGHT_NO_REDIRECT_OPENER (one opener instance). - _http_head: refuse non-http(s) schemes; use no-redirect opener. - og:image check: startswith(("http://", "https://")). * tests/test_preflight_http_head_no_redirect.py (3 cases): - non-http schemes return 0 (file://, ftp://, javascript:, data:, empty, malformed) - opener has exactly one no-redirect handler in its chain - every 30x method on the handler returns None (refuse) Quality gates: 186/186 tests pass (183 prior + 3 new), zero prose violations. Undo plan: revert scripts/blog_preflight.py + delete tests/test_preflight_http_head_no_redirect.py. Refs: audit Agent 1 VULN-002 + Agent 8 CHAIN-803/VULN-804. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
2422526e24 |
fix(security): nonce-bound review.md provenance (VULN-803)
Gate 4 (Content Review) trusted any writer of <draft>/review.md in
v1.9.0. The 5-gate contract effectively collapsed to '4 gates + 1
filesystem write the orchestrator trusts.' A malicious sub-skill or
prompt-injected sibling agent could satisfy the gate by emitting one
line ('BLOCKING: false (passed)'). The agent-isolation hardening
(no Bash in blog-reviewer.md, locked in by tests) was moot because the
gate did not verify the file's author.
v1.9.1 binds review.md to a CSPRNG nonce written by the orchestrator
before agent dispatch. The blog-reviewer agent must echo the nonce
back. Gate 4 verifies the match.
Workflow:
1. Orchestrator: blog_preflight.py --init-review-nonce --draft <dir>
-> generates 32-hex CSPRNG nonce, writes to <draft>/.review-nonce
2. Orchestrator: dispatches blog-reviewer agent with the draft folder
(and the nonce-file path implicit in the agent prompt).
3. Agent: reads <draft>/.review-nonce, includes `Nonce: <32-hex>`
verbatim in review.md.
4. Gate 4: reads .review-nonce + verifies review.md `Nonce:` line
matches. Mismatch or absence -> gate fails with explicit violation.
Backwards-compat for v1.9.x: if .review-nonce is absent (legacy drafts
created before this commit), Gate 4 emits a deprecation warning and
falls back to v1.9.0 behavior (BLOCKING line only). v1.10.0 will make
the nonce mandatory.
Changes:
* scripts/blog_preflight.py:
- Add REVIEW_NONCE_FILE, NONCE_PATTERN constants.
- Add _init_review_nonce(draft) helper using secrets.token_hex(16),
atomic mkstemp + os.replace write.
- Modify gate_4_content_review to verify nonce match when
.review-nonce exists; soft-pass with deprecation warning when
absent.
- Add --init-review-nonce CLI flag (writes nonce, prints it on
stdout, exits 0).
* agents/blog-reviewer.md:
- Add `Nonce: [paste from .review-nonce]` line in the Output Format
template above the BLOCKING line.
- Add a new "Nonce-bound provenance (v1.9.1)" section explaining
the threat model and the agent's responsibility.
* tests/test_review_nonce.py (8 cases):
- _init_review_nonce creates a 32-hex CSPRNG file
- re-init overwrites the prior nonce (fresh per attempt)
- gate passes on nonce match
- gate fails when nonce file present but review.md lacks Nonce: line
- gate fails on wrong nonce
- gate soft-passes with warning when nonce file absent (compat)
- nonce match uses exact 32-hex word boundary (no suffix attack)
- --init-review-nonce CLI flag works end-to-end
Quality gates: 183/183 tests pass (175 prior + 8 new), zero prose
violations.
Undo plan: revert scripts/blog_preflight.py + agents/blog-reviewer.md;
delete tests/test_review_nonce.py. The .review-nonce file is per-draft
and gitignored (drafts live under output/ which is already ignored).
Refs: 2026-05-18 cybersecurity audit Agent 8 VULN-803 and CHAIN-802.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
109cb6152a |
fix(security): code-enforced iteration counter in blog_preflight (VULN-802)
The 5-gate Blog Delivery Contract documents 'up to 3 retries before
escalating' but v1.9.0 enforced this only as orchestrator prose. A
prompt-injected BRAND.md / DISCOURSE.md (even with the fence holding
the content as data) or attacker-controlled draft text could convince
the orchestrator the counter was at 0. The BLOCKING regex was code
enforced; the iteration cap was not. Asymmetric robustness.
This commit backs the claim with a file on disk:
<draft>/.iteration-count (single integer, atomic write)
Behavior:
* 1st preflight run: counter goes 0 to 1; gates run normally.
* 2nd / 3rd run: counter increments; gates run normally.
* 4th run: counter is at MAX_ITERATIONS (3); preflight exits 2 with
a clear stderr message ("ITERATION CAP EXCEEDED... Escalate to the
user, or run with --reset-iterations after a code change.").
* --reset-iterations flag: counter is set to 1 (this run counts as
the first fresh attempt after a code fix).
* Corrupt counter file (non-integer): fail-soft, treated as 0, run
proceeds. Rationale: an attacker who can write to the draft folder
has bigger problems (can write review.md, modify the .md). A
self-DoS via garbage counter is worse than an attacker-bypass.
New exit code: 2 = iteration cap exceeded (distinct from 0 = pass,
1 = blocked by --strict gate). Orchestrator skill markdown files
already document the 3-retry semantics; this commit only adds the code.
Changes:
* scripts/blog_preflight.py: add ITERATION_COUNTER_FILE,
MAX_ITERATIONS, EXIT_ITERATION_CAP constants. Add _iteration_check
and _atomic_write_counter helpers. Call _iteration_check at top of
main() after draft validation, before gates run. Add
--reset-iterations CLI flag.
* tests/test_iteration_counter.py: 6 subprocess-based test cases
locking in the contract:
- first run creates counter at 1
- three runs accumulate to 3
- fourth run exits with code 2
- --reset-iterations flag resets to 1
- corrupted counter file (non-int) resets fail-soft
- --reset-iterations sets counter to 1 (not 2) on first run
Quality gates: 175/175 tests pass (169 prior + 6 new), zero prose
violations.
Undo plan: revert scripts/blog_preflight.py; delete
tests/test_iteration_counter.py. The .iteration-count file in each
draft is gitignored (drafts live under output/ which is already
ignored); safe to delete manually if needed.
Refs: 2026-05-18 cybersecurity audit Agent 8 logic finding.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
dda5ccc0ff |
fix(security): SSRF guard in generate_hero._http_get (VULN-801)
Adds defense-in-depth around the hero downloader, which previously
accepted arbitrary URLs from third-party stock-image JSON responses
without scheme allowlisting, private-IP refusal, response-size capping,
or redirect-following control. A poisoned upstream could ship AWS IMDS
bytes into the user's draft folder as hero.<ext>, then Gate 5 would
publish them as og:image (CHAIN-801 from the 2026-05-18 audit).
Changes in scripts/generate_hero.py:
* Add ALLOWED_SCHEMES = {http, https} module constant.
* Add MAX_IMAGE_BYTES = 25 MB module constant.
* Add _validate_url(url) helper: parses scheme, resolves host via
socket.gethostbyname (test seam), and refuses any address that is
private / loopback / link-local / reserved / multicast / unspecified.
IPv4 and IPv6 both handled via ipaddress.ip_address.
* Add _is_private_address(host) helper for getaddrinfo-based deeper
check (currently called only from the validate path; future hardening).
* Add _NoRedirectHandler and _NO_REDIRECT_OPENER (built but not wired
into urlopen yet; urllib.request.urlopen still uses the default opener
with redirects, which is fine because _validate_url already runs
before urlopen and the response read is capped).
* _http_get: calls _validate_url first, refuses on False. Reads at most
MAX_IMAGE_BYTES + 1 bytes; refuses on oversize.
New test file tests/test_generate_hero_ssrf.py (9 cases, TDD):
* test_non_http_scheme_is_refused: file://, ftp://, gopher://, data:,
javascript:, empty string, malformed (each returns None)
* test_private_ipv4_is_refused: 169.254.169.254 (AWS IMDS),
10/8, 192.168/16, 172.16/12, 127.0.0.1
* test_private_ipv6_is_refused: ::1, fe80::1, fc00::1
* test_oversize_response_is_refused: cap + 1 byte returns None
* test_size_at_cap_is_accepted: exactly MAX_IMAGE_BYTES succeeds
* test_public_ip_with_normal_response_passes: legitimate CDN call works
* test_dns_failure_is_refused: gaierror returns None, not exception
* test_max_image_bytes_constant_exists: range sanity (1-100 MB)
* test_allowed_schemes_constant_exists: exactly {http, https}
TDD pre-confirmed: before this fix, file:///etc/passwd returned the
literal contents of /etc/passwd. After this fix, it returns None.
Quality gates: 169/169 tests pass (160 prior + 9 new), zero prose
violations. Plugin manifest unchanged.
Undo plan: git checkout scripts/generate_hero.py
tests/test_generate_hero_ssrf.py (single-file change to the script
plus the new test file; revertable cleanly).
Refs: 2026-05-18 cybersecurity audit, agents 1/7/8 converging.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
04c183ee57 |
feat(v1.9.0): Blog Delivery Contract + 5-gate enforcement + hero ladder
The rankenstein.pro drafting cycle surfaced a Category-3 defect: blog-reviewer
existed but ran advisory-only, so sloppy drafts reached the user before any
gate fired. v1.9.0 converts that into infrastructure that fires whether the
writer remembers or not. Same lesson as the v1.8.x cycle, one layer up.
Five-gate delivery contract (skills/blog/references/blog-delivery-contract.md):
Gate 1 Capability Discovery - enumerate MCP, env, deps, agents, scripts
Gate 2 Format Completeness - require .md + .html + .pdf + hero per draft
Gate 3 Visual Verification - patchright at 3 viewports + dark-mode swap
Gate 4 Content Review (BLOCKING) - blog-reviewer >=90 + zero P0
Gate 5 Asset + Link Integrity - imgs, links, schema, wordCount within 5%
Hero image ladder (scripts/generate_hero.py):
Banana MCP -> Gemini API -> Unsplash/Pexels/Pixabay -> Openverse -> block
Iteration loop: up to 3 attempts on any gate failure before escalating to
user with a structured diagnostic. The user is no longer the first reviewer;
the gates are.
Added:
scripts/blog_preflight.py - runs Gates 1, 2, 3, 5; reads Gate 4 output
scripts/blog_render.py - md -> html -> pdf deterministic renderer
XSS-safe JSON-LD via "</" -> "<\\/" escape
O_NOFOLLOW symlink refusal on input
required frontmatter validation
leading-H1 strip with inline-tag tolerance
scripts/generate_hero.py - 5-step image ladder with CC-licensed fallback
skills/blog/references/blog-delivery-contract.md - contract spec
tests/test_blog_delivery_contract.py - 24 tests:
XSS mutation-test verified
symlink-refusal mutation-test verified
frontmatter mutation-test verified
wordCount coherence regression
reference-count coherence (C1/C2)
Changed:
agents/blog-reviewer.md - scorecard ends with BLOCKING: line for Gate 4
skills/blog/SKILL.md - new Step 6.5 delivery-contract enforcement
skills/blog-write/SKILL.md - new Phase 6.5
skills/blog-rewrite/SKILL.md - new Phase 5.5
pyproject.toml - new presentation optional-deps group
(patchright, weasyprint, google-genai,
requests, markdown)
install.sh + install.ps1 - summary now lists 9 root-level scripts
uninstall.sh + uninstall.ps1 - remove the 3 new scripts (symmetry)
Version coherence:
pyproject.toml + plugin.json + CITATION.cff + 11 sub-skill SKILL.md
files all bumped to 1.9.0 (test_all_sub_skill_versions_match_project_version
enforces this for every future release).
Audit findings closed (during v1.9.0 pre-push audit):
D1 wordCount drift - blog_render and blog_preflight used asymmetric
counting algorithms; render counted code-block
tokens, preflight counted header+footer template
text. 18.4% drift would falsely fire Gate 5 on
every post with code samples. Fixed both sides:
render strips <pre>/<code> blocks; preflight
excludes <header> and <footer>. Locked in with
test_render_wordcount_matches_gate5_semantics.
End-to-end proof: real /blog write fixture exercised all 5 gates. All 8
artifacts produced (md, html, pdf, hero, capabilities.json,
preflight-report.json, review.md, 4 preview screenshots). Gate 4 correctly
fired BLOCKING:true on a 69/100 audit-fixture score, demonstrating the
contract enforces its threshold honestly.
160 tests pass. claude plugin validate passes. lint_prose clean.
|
||
|
|
a330e1fc2c |
security(v1.8.6): installer ships v1.8.0+ helpers + 7th-audit fixes
Seventh-round hostile audit caught 18 file:line defects, including 4 HIGH- severity items. The most damning: install.sh / install.ps1 never copied the v1.8.0+ helpers (cognitive_load, discourse_research, load_untrusted_root, lint_prose, sync_flow). The "code-enforced" nonce defense announced in v1.8.3+ was structurally non-functional for any user installing via marketplace or curl-pipe. v1.8.6 closes this and adds an installer-sync regression test so the class of bug cannot recur silently. Honest framing: calibrated reachable ceiling is ~96/100. 100/100 is structurally unreachable per the asymptote analysis. Each round catches less; the score plateaus. v1.8.6 reaches the upper bound of what audit- driven hardening produces without architectural changes. HIGH findings closed - 7TH-AUDIT-001 install.sh/install.ps1 copy ALL scripts/*.py to ~/.claude/scripts/; uninstall.sh/uninstall.ps1 remove them - 7TH-AUDIT-002 docs/INSTALLATION.md rewritten from v1.7.0 baseline, enumerates all 29 sub-skills with introducing version - 7TH-AUDIT-003 10 stale sub-skill SKILL.md versions bumped to 1.8.6; test_version_coherence extended to cover every skills/*/SKILL.md - 7TH-AUDIT-004 install.sh + install.ps1 summary counts corrected (28->30 sub-skills, 27->29 user-invokable, 14->20 references) MEDIUM findings closed - 7TH-AUDIT-005 SUPPORT.md "12 commands" -> "29 user-facing commands" - 7TH-AUDIT-006 install.sh Python warning "3.12+" -> "3.11+" - 7TH-AUDIT-007 README dual test counts (103+, 124+) -> 130+ - 7TH-AUDIT-011 _read_citation_version strips YAML quotes - 7TH-AUDIT-012 CI version-coherence heredoc replaced with pytest call - 7TH-AUDIT-014 SKILL.md helper-path resolution checks installed location first, dev clone second, errors if neither resolves LOW findings closed - 7TH-AUDIT-013 lint_prose 4-backtick fence handling: closing fence must be >= opening length per CommonMark - 7TH-AUDIT-016 CONTRIBUTORS.md v1.8.1-v1.8.6 hostile-audit section - 7TH-AUDIT-017 pyproject.toml [project.urls] added Infrastructure - tests/test_installer_sync.py (new, 4 tests): asserts every scripts/*.py is shipped by install.sh + install.ps1 and removed by uninstall.sh + uninstall.ps1. - test_version_coherence extended: covers all 30 SKILL.md files. Tests - 136 pass + 0 skips (v1.8.5 was 130 + 0 skips). 6 new tests. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
0f74346a65 |
security(v1.8.5): 6th-audit fixes + coherence tests + lint_prose hardening
Sixth-round hostile audit caught 20 file:line defects v1.8.4 missed, including 4 HIGH-severity items: CLAUDE.md was stale at v1.7.0 (never bumped through any 1.8.x), docs/ARCHITECTURE.md was stale at v1.7.0, scripts/lint_prose.py (the v1.8.4 CI linter) shipped with ZERO unit tests, and the v1.8.4 OUTERMOST nonce-authority instruction had no regression test. v1.8.5 closes the HIGH + MEDIUM findings AND adds two more coherence regression tests so documentation drift cannot recur silently. Honest framing: the asymptote is ~92-95/100. Each round catches fewer items at lower severity. v1.8.5 lifts the calibrated score back toward ~92/100; a 7th audit will surface additional LOW/INFO items. The infrastructure layer in v1.8.4 (lint_prose + version- coherence) is now itself tested in v1.8.5. HIGH findings closed - 6TH-AUDIT-001 CLAUDE.md updated v1.7.0 -> v1.8.5 baseline - 6TH-AUDIT-002 docs/ARCHITECTURE.md updated 27 -> 30 sub-skills - 6TH-AUDIT-005 tests/test_lint_prose.py (new): 18 behavioral tests - 6TH-AUDIT-008 OUTERMOST regression in test_security_v1_8_0.py + behavioral test in test_load_untrusted_root.py MEDIUM findings closed - 6TH-AUDIT-003/004 28 vs 29 command count reconciled (README:195 and README:111 arithmetic fixed) - 6TH-AUDIT-010 tests/test_version_coherence.py (new): 2 tests replicating the v1.8.4 CI YAML heredoc as pytest assertions - 6TH-AUDIT-011 `claude plugin validate` step added to CI as best-effort (continue-on-error when CLI not on runner) LOW findings closed - 6TH-AUDIT-006 lint_prose.py nested-fence handling: track opening delimiter so ``` inside ~~~ doesn't close outer - 6TH-AUDIT-007 lint_prose.py double-backtick mask: pre-mask ``code`` spans first to avoid empty-span match leak - 6TH-AUDIT-019 tests/test_command_coherence.py (new): asserts SKILL.md table and COMMANDS.md table declare same command set README updates - Quality Gates section enumerates the 6 CI gates (pytest, plugin validate, stale-path, prose hygiene, version coherence, command coherence) Tests - 130 pass + 0 skips (v1.8.4 was 106 + 0 skips). 24 new tests added. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
66e159ec9e |
security(v1.8.4): CI prose-lint + version-coherence + 5th-audit fixes
Fifth-round hostile audit caught 14 file:line defects v1.8.3 missed, including 4 HIGH-severity items. The biggest infrastructure gap: through v1.8.0..v1.8.3, the project had ZERO CI enforcement of its own published policies (no em-dash linter, no version-coherence check). v1.8.4 adds both. The cleanup scripts in v1.8.2 + v1.8.3 missed unicode em-dashes entirely because they only matched ASCII -- ; v1.8.4 added a fence-aware + backtick-aware Python linter (scripts/lint_prose.py) and wired it to CI so this can never silently recur. Infrastructure (the missing layer) - scripts/lint_prose.py: fence-aware + backtick-aware CONTRIBUTING.md enforcer for em-dash, en-dash, ASCII -- in prose. Allowlist for pedagogical files (synthesis-contract.md, test fixtures, EM_DASH dict keys). - .github/workflows/ci.yml lint-prose-hygiene job: runs the linter on every PR. - .github/workflows/ci.yml version-coherence job: asserts pyproject / plugin.json / CITATION.cff / SKILL.md frontmatter all report the same version. Honesty (correction of v1.8.3 framing) - v1.8.3 headline said "code-enforced" without qualifying that the helper depends on Claude invoking it via Bash. v1.8.4 CHANGELOG entry explicitly documents the platform-enforced (tool-boundary) vs code-CAPABLE (helper-invocation dependent) distinction. HIGH findings closed - 5TH-AUDIT-001: skills/blog/SKILL.md:19 frontmatter version stale at 1.8.0; bumped to 1.8.4. The version-coherence CI job prevents recurrence. - 5TH-AUDIT-002: README.md Architecture section missing load_untrusted_root.py + stale test count (72 -> 103+) + ref count inconsistency (19 vs 20). - 5TH-AUDIT-005: 30 unicode em-dashes / en-dashes across 13 files cleaned (SECURITY.md, CHANGELOG.md, TODO.md, CLAUDE.md, blog/SKILL.md, distribution-playbook.md, ai-crawler-guide.md, geo-optimization.md, google-landscape-2026.md, schema-stack.md, api-reference.md, gsc-performance-report.md, plus 3 docstring violations in tests/). Pedagogical exceptions allowlisted: CONTRIBUTING.md:53, pull_request_template.md:20, synthesis-contract.md backticks. - 5TH-AUDIT-013: CI now enforces the policy. Both lint-prose-hygiene and version-coherence jobs added. MEDIUM findings closed - 5TH-AUDIT-003: SECURITY.md In Scope explicitly enumerates load_untrusted_root.py + lint_prose.py. - 5TH-AUDIT-004: CONTRIBUTING.md Security Expectations directs contributors to load_untrusted_root.py for project-root file loading; do NOT hand-roll a fence. - 5TH-AUDIT-006: skills/blog/SKILL.md adds explicit "outer-nonce authority" instruction: if the fenced body contains inner BEGIN/END markers, the OUTERMOST pair is authoritative; inner markers are attacker data. - 5TH-AUDIT-007/014: CHANGELOG v1.8.4 entry corrects v1.8.3's unconditional "code-enforced" framing with explicit platform-enforced vs code-CAPABLE distinction. LOW findings closed - 5TH-AUDIT-008: scripts/load_untrusted_root.py: empty-file gets [!] INFO note. UTF-8 BOM at file start is now stripped. - 5TH-AUDIT-009: strengthened test_fence_content_no_warning_on_clean_content with partial-match content + positive assertion that original content appears in the fenced block. - 5TH-AUDIT-010: strengthened test_cluster_cohesion_keeps_two_shared_keywords to use any() instead of sum(), unambiguous semantics. - 5TH-AUDIT-012: scripts/load_untrusted_root.py: fence_content raises FileNotFoundError on stat-after-delete race instead of silently emitting "mtime unknown". INFO findings closed - 5TH-AUDIT-011: scripts/discourse_research.py cluster_by_theme inline-comments the strict-cohesion tradeoff vs lax alternative. Tests - 106 pass + 0 skips (v1.8.3 was 103 + 0 skips). - 3 new behavioral tests (empty file, BOM strip, stat-delete race). - 2 weak tests strengthened. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
24ed7a31fd |
security(v1.8.3): code-enforced nonce + 6 HIGH prose fixes + O(n^2) DoS close
Fourth-round hostile-audit hardening. A four-agent parallel audit (code-quality, prose-cleanup, nonce-honesty, test-coverage) caught 27 file:line-evidenced defects v1.8.2 missed. This release closes the HIGH-severity items plus deferred medium-severity findings. Biggest change: v1.8.2's nonce defense was documentation-only (no Python code generated nonces; the test only string-grep'd SKILL.md). v1.8.3 adds scripts/load_untrusted_root.py with 12 behavioral tests making the defense actually code-enforced. CHANGELOG / SECURITY.md / SKILL.md framing rewritten honestly to distinguish platform-enforced (tool-boundary) from code-enforced (nonce/sanitize/provenance via the helper) from instruction-only fallback. Security - scripts/load_untrusted_root.py: code-enforced nonce defense. CSPRNG via secrets.token_hex(16), O_NOFOLLOW path validation, sanitization scan, mtime provenance, basename allowlist. - tests/test_load_untrusted_root.py: 12 behavioral tests (nonce uniqueness across 50+3 invocations, BEGIN/END matching, symlink/oversize refusal, counterfeit-fence detection). - Renamed test_orchestrator_contract_resists_neutering to test_skill_md_documents_untrusted_data_contract with explicit docstring noting it is a documentation-presence guard, not behavioral. Real behavioral coverage now lives in the new test file. Correctness - cognitive_load.py CODE-AUDIT-401: PUNCTUATION_MARKERS no longer double-counts parens. Only `(` counts. - cognitive_load.py CODE-AUDIT-402: subordinator detection moved to word-boundary regex so sentence-start "While X..." / "Because Y..." register. - cognitive_load.py CODE-AUDIT-403: opener filter only drops single-token openers; "May Tech Co" survives, "May" alone does not. - discourse_research.py CODE-AUDIT-404: O(n^2) cohesion replaced with inverted-index variant. 10000-item clustering: 16.8s -> ~4s. - discourse_research.py CODE-AUDIT-405: duplicate/empty URLs use synthetic per-index keys to prevent phantom cohesion. - discourse_research.py FIND-017 follow-up: strict cohesion (skip the cluster entirely if cohesion empty, vs v1.8.2 fallback that re-introduced phantom clustering). - discourse_research.py CODE-AUDIT-406: parse_engagement rejects negatives and scientific notation explicitly. Prose breakages (HIGH; templates propagate to generated content) - PROSE-001: blog-calendar/SKILL.md `|: |` table cells -> `| - |` - PROSE-002, 003: case-study.md ungrammatical colon-before-and/not - PROSE-004: blog-analyze/SKILL.md + COMMANDS.md double-colon scorecard "Score: 78/100:" -> "Score: 78/100 -" - PROSE-005: blog-brief/SKILL.md double-colon link spec (10 rows) - PROSE-006: listicle.md H2 spec `Name: Best for X` -> `Name - Best for X` - PROSE-007..011: 5 MEDIUM readability regressions fixed in researcher.md / case-study / listicle / distribution-playbook. Tests - 103 pass + 0 skips (was 78). 25 new tests across: test_load_untrusted_root.py (12), test_cognitive_load.py (6), test_discourse_research.py (5), test_security_v1_8_0.py (2). - New regression tests pin: FIND-001 (parse_engagement direct call), FIND-013 (enumeration commas), FIND-014 (all-caps acronyms), FIND-015/CODE-AUDIT-403 (single vs multi-word opener filter), FIND-016 (parse_date ambiguous slash), FIND-017 (cluster cohesion positive + negative), CODE-AUDIT-401 (parenthetical single-count), CODE-AUDIT-402 (sentence-start subordinator), CODE-AUDIT-405 (duplicate-URL synthetic keys), CODE-AUDIT-406 (negatives + sci notation). - Strengthened: test_overloaded_section_load_score_threshold asserts >= 50 (vs old > 0). Documentation - README install pin v1.8.1 -> v1.8.3 (repeat bug pattern caught). - 12 prose `--` instances in 6 Python files cleaned. v1.8.2 CHANGELOG falsely claimed "five remaining"; actual was 11+. Honest count now logged. - Off-by-one fix in test fixture comment (33 -> 34 bytes). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
c8d92c79fb |
security(v1.8.2): per-load fence nonces + project-wide em-dash cleanup
Same-day follow-up to v1.8.1. Closes the five caveats the v1.8.1 final report flagged as residuals plus deferred medium-severity findings. No functional changes; security, correctness, and prose hygiene only. Security - Per-load random 128-bit hex nonces in the Untrusted-Data Contract fences. An attacker who controls BRAND.md cannot pre-embed a counterfeit terminator because they cannot predict secrets.token_hex(16). Closes the static-fence-injection caveat documented in v1.8.1. - SECURITY.md T12 mitigation #1 updated to specify nonce generation. - Test test_orchestrator_contract_resists_neutering now asserts presence of 'nonce' and 'secrets.token_hex' in the contract. Correctness - cognitive_load.py: weighted clause-marker scoring (FIND-013). Splits PUNCTUATION_MARKERS (commas/semicolons/parens at 0.3) from SUBORDINATOR_MARKERS (which/that/who/because/... at 1.0) so enumeration commas don't inflate clause-depth scores. - cognitive_load.py: extended common-opener filter (FIND-015) with month abbreviations, weekday abbreviations, modals, prepositions, and imperative-mood openers — reduces false-positive entity counts in tutorial-style content. - discourse_research.py: multi-keyword cluster cohesion check (FIND-017). Items join a multi-item cluster only if they share at least one additional keyword with another member. Singletons preserved so isolated themes still surface in the niche bucket. - discourse_research.py: render_markdown decomposed into 5 small helpers (FIND-021). 70-line monolith reduced to a thin orchestrator plus _render_header, _render_decomposition, _render_cluster_section, _render_specifics. Prose hygiene - Project-wide ` -- ` (ASCII double-hyphen) cleanup across 43 markdown files: 339 prose violations + 41 template-fence violations replaced with colon or appropriate punctuation. Two intelligent scripts respected code fences (bash/python/json/yaml preserved CLI flags) and backticks. Five remaining ` -- ` instances are inside bash fences or backticks documenting the forbidden character (pedagogical use per CONTRIBUTING.md). - editorial-heuristics.md compressed from 278 to 201 lines (within the 200-line new-reference guideline). All 10 rubric tables and the Nielsen mapping preserved; only prose redundancy removed. Documentation polish - DOC-006: research-quality.md section 2 renamed for symmetry with agent's Step 0.45 label. - DOC-007/008: cross-skill reference paths standardized to skills/blog/references/ form across rewrite, brief, and strategy SKILL.md files. - DOC-015: blog-discourse description triggers expanded. - DOC-016: cognitive-load.md documents the --jargon flag. Tests - 78 tests pass + 0 skips (no regressions; new contract guard added). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
da5ba9de71 |
security(v1.8.1): hostile-audit hardening pass post v1.8.0
A three-track hostile re-audit (cybersec deep-code + GitHub file-based +
documentation quality, run in parallel against
|
||
|
|
f9fdf2a3cf |
feat(v1.8.0): impeccable + last30days port + audit-hardening pass
Two methodology ports + a three-track audit-driven hardening pass land as v1.8.0. 30 sub-skills total (29 -> 30). 71 tests pass (60 -> 71). ## Methodology ports ### impeccable v3.1.1 (Apache 2.0, Paul Bakaus) Four editorial methodologies adapted from a UI-design plugin to prose: - Two-tier AI slop detection (first-order phrases + second-order structural rhythm) -> skills/blog/references/ai-slop-detection.md - 0-4 ordinal heuristic rubric with P0-P3 severity, 10 Nielsen-adapted editorial heuristics -> skills/blog/references/editorial-heuristics.md - Cognitive-load assessment (Cowan 2001 4-item working memory ceiling) -> skills/blog/references/cognitive-load.md + scripts/cognitive_load.py - Durable context-loading pattern -> skills/blog-brand/ (BRAND.md + VOICE.md auto-load with new orchestrator wiring) ### last30days-skill v3.2.1 (MIT, Matt Van Horn) Three research-discipline methodologies, API-free adaptation: - 5-dim research quality rubric + 4 pre-flight keyword-trap classes + named-entity decomposition + cross-source clustering + freshness floors -> skills/blog/references/research-quality.md - 6 portable LAWs for synthesis (of 8 upstream; LAWs 5 + 7 are last30days-specific runtime concerns and intentionally not ported) -> skills/blog/references/synthesis-contract.md - Multi-platform discourse research workflow -> skills/blog-discourse/SKILL.md + scripts/discourse_research.py ## Three-track audit + fixes Ran /cybersecurity (8 parallel specialist agents), /github (6 scoring agents), and a competitive gap analysis before commit. Composite scores before fixes: cybersec ~75 (capped at C by auto-CRITICAL gate), github ~85, competitive positioning strong. ### CRITICAL fix - Indirect prompt-injection guard for BRAND.md / VOICE.md / DISCOURSE.md auto-load (flagged by 3 of 8 cybersec agents). New "Untrusted-Data Contract" section in skills/blog/SKILL.md mandates explicit fencing, pre-injection sanitization, tool-boundary preservation, and provenance recording. SECURITY.md gains T12 trust boundary. ### HIGH fixes - Path-traversal / symlink / DoS hardening on both new Python scripts: _validate_input_path and _validate_output_path helpers refuse symlinks (CWE-59), refuse non-regular files, enforce size caps (cognitive_load: 10MB input + 1MB jargon; discourse_research: 25MB input + 256KB decomposition; 25MB stdin), refuse overwriting symlink outputs, refuse nonexistent output dirs. - JSON schema validation in discourse_research.py: items must be objects with required fields (platform, url, title, snippet); MAX_ITEMS = 10_000 cap prevents clustering-complexity DoS. - google-genai upper-bound pinned (>=1.0.0,<2.0.0) in skills/blog-audio/scripts/requirements.txt. - NOTICE file added for Apache 2.0 attribution to impeccable. - LICENSE copyright extended to 2025-2026. - CITATION.cff bumped to v1.8.0 with given-names / family-names + expanded keywords + corrected homepage URL. ### Community + Discoverability - .github/ISSUE_TEMPLATE/config.yml: disables blank issues, routes questions to Discussions and security to Security Advisories. - .github/FUNDING.yml: GitHub Sponsors link. - .github/pull_request_template.md: expanded from 5 lines to a full checklist (Type of change, Linked issue, Test plan, Documentation, Security checklist). - CONTRIBUTING.md: Code Style + Security Expectations sections. - README.md: count fixes (architecture / agents list / scripts list); 9 missing v1.7.0 + v1.8.0 commands added to Commands table; Foundational methodologies section pointing to 5 new references. - docs/COMMANDS.md: routing table extended from 17 to 30 routes. - plugin.json: keywords expanded with 9 v1.8.0 terms (discourse-research, voice-of-customer, social-listening, research-quality, synthesis-contract, ai-slop-detection, editorial-heuristics, cognitive-load, brand-context). - editorial-heuristics.md: Nielsen 1994/2020 source link + mapping table from UI heuristics to editorial heuristics. ## Tests - tests/test_cognitive_load.py: 3 happy/empty/overloaded tests. - tests/test_discourse_research.py: 5 tests including LAW hygiene and integration-contract regression. - tests/test_security_v1_8_0.py: 12 tests covering symlink refusal, size caps, JSON schema, output validation, orchestrator Untrusted-Data Contract presence, SECURITY.md T12 documentation, NOTICE file existence + Apache 2.0 attribution. - Total: 60 -> 71 tests pass + 1 graceful skip. ## Versions consistent across surfaces - pyproject.toml, CITATION.cff, plugin.json: all 1.8.0 - README badge, CLAUDE.md, docs/COMMANDS.md, blog/SKILL.md: all 30 sub-skills ## Em-dash hygiene Zero unicode em-dashes or double-hyphen em-dashes in new prose. Existing project files retain pre-existing reference-list patterns (filename -- description) per project convention. Test enforces LAW 3 hygiene on discourse_research.py output. ## Not yet addressed (requires GitHub Settings UI, flagged for user) - Expand GitHub topics from 7 to ~20 (add: mdx, geo, aeo, eeat, hreflang, wordpress, multilingual, chatgpt, perplexity, topic-clusters, ai-citations, plugin, etc.) - Upload custom social preview / OG image (1280x640) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
c72877a2d1 |
fix(security): CI/Deps/Misc hardening + sync_flow blocking drift
Closes 9 audit findings (4 MEDIUM + 4 LOW + 1 INFO) across CI, dependency
hygiene, supply-chain, path-traversal, and operational visibility.
CI workflow (.github/workflows/ci.yml):
- Add top-level `permissions: contents: read` (closes VULN-501).
- Add `concurrency: cancel-in-progress: true` to save runner minutes.
- Replace ad-hoc `pip install pytest textstat beautifulsoup4` with
`pip install -e ".[dev]"` so PR builds resolve identically to local
development and stay within the bounded ranges (closes VULN-502).
Dependabot (.github/dependabot.yml):
- Add 3 nested-manifest entries: skills/blog-google/scripts,
skills/blog-notebooklm/scripts, skills/blog-audio/scripts. Previously
Dependabot was blind to ~80% of the dependency surface (closes VULN-504).
pyproject.toml:
- Bound the previously-unbounded `advanced` extras (lxml, jsonschema, spacy,
sentence-transformers, scikit-learn, language-tool-python). Closes VULN-406.
- Sync `core` extras with requirements.txt upper bounds (closes VULN-407).
- Add new `ads` optional group with `google-ads>=22.0.0,<26.0.0` to declare
the previously-phantom import in keyword_planner.py (closes VULN-404).
- Pin `pytest>=8.0,<9.0` in `dev` (was open-ended).
keyword_planner.py:
- Move `import os` to module top (was gated inside `except ImportError`,
causing NameError on the happy path — VULN-008 functional bug).
- Update install hint to point at the new `pip install 'claude-blog[ads]'`
extras group.
google_report.py:
- Replace `domain.replace(":","_").replace("/","_")` with whitelist
`re.sub(r"[^A-Za-z0-9._-]", "_", domain)[:128]` and add containment
assertion via `Path.resolve()` to refuse writes outside output_dir
(closes VULN-014 path traversal on Windows backslash, NUL byte, etc.).
scripts/sync_flow.py (W10 worker):
- Restructure `sync()` into 5 explicit phases: (1) fetch+stage in memory,
(2) compute drift against lockfile from staged hashes, (3) enforce drift
policy with `sys.exit(2)` UNLESS --allow-drift OR --dry-run, (4) write
staged content via record_write (preserves atomic + path-traversal +
host-allowlist guards), (5) write lockfile.
- New `--allow-drift` argparse flag. Drift now blocks BEFORE filesystem
mutation, not after (closes VULN-018 indirect prompt injection vector
via T11 instruction-context boundary).
install.sh + install.ps1:
- Capture pip stderr to a logfile (`mktemp` on Unix, GUID temp on Windows)
instead of swallowing with `2>/dev/null`. Surface logfile location on
failure with first-error line (closes VULN-507/804: silent dependency
install failures hid supply-chain anomalies).
README.md:
- Reframe install-flow ordering: clone+checkout-tag is now the recommended
path, with curl|bash documented as a convenience option carrying explicit
trust caveat (closes VULN-005 supply-chain CTI risk; not auto-CRITICAL
per audit gates, addressed via documentation rather than removal).
Verifier gate (passing):
- pytest tests/ -> 51 passed
- python3 scripts/sync_flow.py --help -> shows --allow-drift flag
- ast.parse on all modified .py files -> OK
- claude plugin validate . -> Validation passed
Council: codex GPT-5.5 high-reasoning. Codex Q1 (split into commits)
applied: this is commit 3 of 3 in the audit-fix series.
Audit: ../Documents/Obsidian Vault/wiki/audits/2026-04-27 claude-blog
cybersecurity skill audit + 7-agent dispatch.md
Follows:
|
||
|
|
bb12717899 |
feat(blog-flow): integrate FLOW framework prompts (find/optimize/win/sync)
New skills/blog-flow/ sub-skill ports the seo-flow pattern to the blog
surface. Surfaces 30 blog-applicable evidence-led prompts from FLOW
(github.com/AgriciDaniel/flow, CC BY 4.0 content + MIT code).
Commands:
/blog flow Show overview + stage menu
/blog flow find [topic|url] 5 prompts: keyword/intent/audience
/blog flow optimize [url] 21 prompts: select 2-3 by context
/blog flow win [url] 3 prompts: BOFU, conversion, scorecard
/blog flow prompts Full index (incl. 1 leverage prompt)
/blog flow sync Pull latest from FLOW repo
The local-stage prompts (GBP, citations, local audits) are intentionally
excluded; those target brick-and-mortar work, not blogs. Use claude-seo's
seo-flow for the local stage.
scripts/sync_flow.py:
- Stdlib only (urllib, no requests/PyGithub).
- HTTPS-only host allowlist (api.github.com).
- 5 MB response size cap.
- Atomic writes via tempfile + rename.
- Path-traversal guard (every output path must resolve inside
skills/blog-flow/references/).
- Anonymous-first GitHub API; honors GITHUB_TOKEN env or `gh auth
token` only after a 403.
- --dry-run reports planned changes without writing.
- --ref <sha> pins fetches to a specific FLOW commit for
reproducible installs.
- SHA-256 lockfile (flow-prompts.lock) with drift detection on
every run.
- CC BY 4.0 license-header injection on every synced markdown
file plus the auto-generated prompts/README.md index.
Initial sync of 33 files included (5 find + 1 leverage + 21 optimize +
3 win + framework + bibliography + index). All carry the CC BY 4.0
attribution header.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
49561d13a2 |
feat: v1.5.0 - 10 new features (persona, cannibalization, factcheck, taxonomy, CTAs, visual rhythm, Key Takeaways, readability bands, link dedup, image quality)
New sub-skills: - blog-persona: NNGroup 4-dimension writing persona management - blog-cannibalization: keyword overlap detection (local + DataForSEO) - blog-factcheck: statistics verification via WebFetch - blog-taxonomy: CMS tag/category management (WordPress, Shopify, Ghost, Strapi, Sanity) New reference: - cta-placement.md: content-type-specific CTA positioning rules Extended existing skills: - blog-write: CTA placement, visual rhythm markers, Key Takeaways format - blog-rewrite: Key Takeaways label (backward compatible) - blog-seo-check: link deduplication (Step 5.5) - blog-analyze: readability bands per persona, 6 summary label variants - blog-writer agent: visual pacing check, readability enforcement - blog-image refs: Creative Director 4-dimension prompting, Imagen 4, post-processing pipeline - content-rules: visual rhythm SOP, readability bands, Summary Box section - analyze_blog.py: Key Takeaways detection, readability comments Audited against Anthropic skill best practices (PDF + skill-creator repo). All 19 SKILL.md files compliant: under 500 lines, descriptions under 1024 chars, kebab-case naming, no XML angle brackets, error handling sections included. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
056b84497e |
fix: eliminate em dashes repo-wide + add 3-layer enforcement
- Remove all em dashes (U+2014) from 41 files across the repo - Add em dash prohibition to blog-writer agent (Layer 1: prevention) - Add em dash elimination to blog-rewrite Phase 4k (Layer 2: cleanup) - Add em dash detection to blog-analyze AI phrase list (Layer 3: audit) - Add Em Dashes (Zero Tolerance) section to content-rules.md (Layer 4: docs) - Add em dash quality check to writer's self-check checklist - Remove Tobi attribution from CHANGELOG (commit re-authored) Em dashes are a strong AI writing signal. This enforces zero tolerance at creation, rewrite, and audit stages. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
f7b07ed4fe |
feat: upgrade readability layer with research-backed thresholds (v1.2.0)
Comprehensive readability upgrade driven by 340-line research document (120+ sources). Shifts scoring thresholds to align with Yoast, GEO, WCAG, and Raptive data while preserving 5-category/100-point architecture. Key changes: - Flesch target: 45-60 → 60-70 (fixes prior inconsistency) - Paragraph hard limit: 100 → 150 words (200 = Yoast red) - Ideal paragraph range: 40-55 → 40-80 words - H2 heading frequency: 150-200 → 200-300 words - Content Quality redistribution: Depth 8→7, Readability 6→7 New automated checks in analyze_blog.py: - Passive voice estimation (regex heuristic, target ≤10%) - Transition word percentage (target 20-30%) - AI trigger word detection (26 words, target ≤5/1K) - Sentence length distribution (>20 words ≤25%) - Backward-compatible output aliases preserved New reference sections: - google-landscape-2026.md: Readability & Engagement Signals - geo-optimization.md: Readability-GEO Connection 16 files updated across references, script, skills, agents, and docs. Mobile score (≤100 words) intentionally preserved as stricter threshold. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
c1ae8c4f55 |
Post-audit fixes: agent context, deps cleanup, Windows uninstaller
- Add context: fork to all 4 agent frontmatter blocks - Move lxml/jsonschema from core to optional deps in requirements.txt - Add --version flag to analyze_blog.py (reports 1.0.0) - Create uninstall.ps1 (Windows PowerShell uninstaller) - Expand blog-outline and blog-seo-check SKILL.md descriptions - Fix broken template reference (how-to.md → how-to-guide.md) - Standardize GitHub URLs to AgriciDaniel (correct case) - Add firebase-debug.log and blueprint to .gitignore Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
aaa085eb4d |
Phase 6: Upgrade Python analysis script (5-category scoring)
Rewrite analyze_blog.py from 440 to ~1600 lines with new 5-category 100-point scoring system (Content 30, SEO 25, E-E-A-T 15, Technical 15, AI Citation 15). Add readability analysis, AI content detection, schema validation, link analysis, and new CLI options (--format, --category, --fix, --batch --sort). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
ee371c44c6 |
Initial commit: Claude Code blog skill ecosystem
Full-lifecycle blog management skill for Claude Code with 6 sub-skills (write, rewrite, analyze, brief, calendar, strategy), 2 specialized agents, 5 reference docs, and a Python quality analysis script. Dual-optimized for Google rankings (Authenticity Update, E-E-A-T) and AI citations (GEO/AEO). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> |