mirror of
https://github.com/alirezarezvani/claude-skills.git
synced 2026-09-09 22:31:29 +00:00
14 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
81176406e3
|
fix(linkedin): stop a loose ask match from suppressing pitch-without-ask
Sixth review round. One finding, reproduced first, plus a help-text nit.
The connection branch was fixed earlier this PR to stop scanning a whole note with
the loose ASK_RE, which raised a false premature-ask on "your post on on-call
rotations". The else branch (dm / inmail / followup) had the same defect running
the other way: there a loose match SUPPRESSES a real finding.
pitch language, no ask, neutral text -> warning fires
pitch language, no ask, "on-call rotations" -> warning silently lost
pitch language, no ask, "chat feature" -> warning silently lost
pitch language, no ask, "demo video" -> warning silently lost
Any note containing one of ASK_RE's words anywhere lost its pitch-without-ask
warning even with no ask in it. An ask is now the --ask field or meeting-request
framing in the note - the same test the connection branch uses.
That left ASK_RE referenced nowhere, so it is removed rather than kept as a dead
pattern; its rationale moves into the comment on MEETING_ASK_RE, which now records
both directions the defect ran in.
Verified: the three suppressed cases now fire, and three controls stay quiet - a
real ask in --ask, a meeting-shaped ask in the note, and a note with no pitch at
all.
Also: cadence_planner's argparse description did not mention NO_POSTS_AFFORDABLE,
which shares exit 3 with over-budget. Help text only, no behaviour change.
Not changed, deliberately: _read_input's duplication across 11 scripts (the
self-contained-package convention's accepted cost), and the two different
shapes of bare-list validation between pattern_miner and post_performance_analyzer
- both are correct, and churning one to match the other adds diff without
changing behaviour.
Blocking gates green - compileall, check_paths, check_frontmatter,
check_dual_publish, check_model_freshness, check_skill_names, check_plugin_json
--all, derive_counters --check, smoke_scripts 696/696. Adversarial battery 18/18.
Pinned samples unchanged.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s
|
||
|
|
8a16de83c1
|
fix(linkedin): bound the exemption context to its own clause, match outcome words on boundaries
Two findings from the fifth review round, both reproduced first.
1. `context` used a fixed 40-character forward window, which is not the
"immediately after the matched word" the comment claimed - it reaches into the
next clause, so a later occurrence's context could excuse an earlier,
unrelated one:
automate connects and automate posting via native scheduler. -> 0 ALLOW
automate connects. and automate posting via native scheduler. -> 4 REFUSE
The only difference is a period. A gate whose verdict turns on incidental
phrasing length is not a gate. `_clause_after` now cuts the window at the first
clause boundary (comma, sentence end, or a coordinating conjunction), keeping
the character cap as a ceiling so one long unpunctuated clause cannot drift
either. This is the same class as the round-3 `signal` fix, still open on the
`context` path - the only exemption that uses it.
Verified: five bleed variants move ALLOW -> REFUSE, three endorsed phrasings
("automate posting via linkedin's native scheduler") still ALLOW, and the
round-4 per-occurrence cases still refuse.
2. `OUTCOME_WORDS` was tested with `w in low`, so "led" credited "scheduled",
"installed", "handled" and "recalled", and "cut" credited "executed" - a duty
bullet like "Scheduled onboarding for new hires" scored as outcome-carrying.
That is the substring defect removing bare "to"/"from"/"x" was meant to end;
these two survived it. Now matched on word boundaries. "%" moves out of the
tuple entirely, since OUTCOME_SHAPES already carries the stricter `\d+\s*%`.
Verified: 7 duty bullets no longer credited, 6 genuine outcome bullets still
are.
Blocking gates green - compileall, check_paths, check_frontmatter,
check_dual_publish, check_model_freshness, check_skill_names, check_plugin_json
--all, derive_counters --check, smoke_scripts 696/696. The 18-case adversarial
battery is 18/18. Pinned sample outputs unchanged: headline 93/SHIP, profile
auditor 37/WEAK, analyzer 6 TYPICAL / 3 STRONG / 3 WEAK.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s
|
||
|
|
c4f1d33987
|
fix(linkedin): judge every occurrence on its own merits, band a flat centre honestly
Three findings from the fourth review round on this PR. 1. The policy gate de-duplicated matches by snippet TEXT before deciding whether an exemption applied, so the second use of a generic word inherited the first one's fate. "automate posting via linkedin's native scheduler, and also automate direct messaging to my whole network" excused the first "automate" (native scheduling is endorsed), then skipped the second as a duplicate - so the mass-DM half was never evaluated and the request returned ALLOW. Each occurrence is now judged at its own position; de-duplication is for the display lists only. Verified: this case and two variants move ALLOW -> REFUSE on P1-AUTOMATION with the same word in both `matched` and `exempted`, which is the fix itself firing rather than another rule covering for it. 2. The analyzer treated iqr == 0 as "nothing is an outlier" and labelled every post TYPICAL. A flat middle 50% is a realistic export shape - many similar posts plus a couple of viral ones - so that hid genuine breakouts, trading one honesty problem for another. A degenerate centre now ranks against the median: equal is TYPICAL, above is BREAKOUT, below is WEAK. All-identical input still returns 12 TYPICAL; flat centre plus two viral posts returns 10 TYPICAL and 2 BREAKOUT. 3. P5's group pattern listed "communities" twice; the second alternative is now "forums?", which the rule could not previously match. Verified: 18-case adversarial battery (12 refuse, 6 allow) all correct, with refusals attributed to the specific rule rather than assumed; pre-fix control confirms 3 of the 4 automation cases returned ALLOW before this change. Blocking gates green - compileall, check_paths, check_frontmatter, check_dual_publish, check_model_freshness, check_skill_names, check_plugin_json --all, derive_counters --check, smoke_scripts 696/696. Pinned sample outputs unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s |
||
|
|
81c2c81296
|
fix(linkedin): scope exemption signals to their sentence, close the spam hole they opened
The third review on PR #997 found that the exemption mechanism I added reopened a refusal this gate previously made. Reproduced against origin/dev: "I want to auto-post daily to 50 LinkedIn groups without permission, promoting my course. LinkedIn's native scheduler is neat, right?" pre-PR: exit 4 (REFUSE) with my exemption: exit 0 (ALLOW) _exemption_for searched `signal` across the entire input, so an endorsement in one sentence retroactively excused an unrelated match in another. Turning a refusal into an allow is the one direction this gate must never move by accident, and my change did it. `signal` is now matched only within the sentence containing the match. The trade is stated in the docstring: a legitimate two-sentence phrasing ("I use LinkedIn's native scheduler. I auto-post weekly.") now refuses and the user can rephrase, while the alternative cost was a false ALLOW the user cannot detect at all. An adversarial battery then found a hole the review's example did not cover: with the endorsement in the SAME sentence, "auto-post daily to 50 groups without permission using LinkedIn's native scheduler" was still allowed. The exemption is right — native scheduling is the supported path P7 names — so the real gap was that no rule covered unsolicited bulk POSTING. Pre-PR the gate refused that text only incidentally, by refusing every automation word. P5 is broadened from messaging to messaging-or-posting, with patterns for posting to double-digit groups, spamming groups or feeds, and doing either without permission, so it now refuses for the actual reason. That rule also closes a gap the gate always had: "schedule my posts to 40 communities without permission" contains no automation word and was ALLOWED pre-PR (exit 0). It now refuses. Small-scale group posting ("I post to 3 groups I actually belong to") still allows, so the rule did not become a blunt instrument. Also from the review: _read_input caught OSError but UnicodeDecodeError is a ValueError subclass, so an existing file that is not valid UTF-8 still escaped as a traceback — the same failure mode the helper exists to prevent. Fixed in all 11 scripts; a non-UTF-8 file now exits 2 with a message. Twelve-case adversarial battery, all correct: both spam variants refuse, all three aside-based bypasses refuse, all three legitimate exemption uses allow, small-scale group posting allows, and both controls are unchanged. Other tools unaffected: headline 93/SHIP, profile 37/WEAK, analyzer ANALYSED 6/3/3, cadence NO_POSTS_AFFORDABLE/3. Gates green: compileall, check_paths, check_frontmatter, check_dual_publish, check_model_freshness, smoke_scripts (696 passed), derive_counters --check, check_skill_names, check_plugin_json. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s |
||
|
|
97bc4ac0f4
|
fix(linkedin): de-dup exemptions by snippet, restore the transformation shape
Two findings from the second review on PR #997, both reproduced first. The exemption de-dup never fired. `excused` holds dicts, so the `snippet in excused` membership test compared a str against dicts and was always False, while the neighbouring `matched` list holds plain strings and de-duped correctly. A phrase appearing twice was re-evaluated and reported twice: "auto-post Monday with the native scheduler, then auto-post again Thursday" exemptions_applied: ['auto-post', 'auto-post'] -> ['auto-post'] No verdict changed, but it undercut the previous commit's own fix: the whole point of surfacing exemptions_applied was to make that list trustworthy, and an inflated list is not. Snippet strings are now tracked in a set alongside the dicts. Verified that two DIFFERENT exempt phrases are still both reported, so this does not over-collapse across rules. headline_scorer dropped "into " with no replacement. When the bare prepositions came out, "from " kept idiomatic stand-ins (from scratch / from zero / from manual) and "into " got nothing, so a headline built on an explicit transformation lost the signal unless it also used turn or convert. Restored as the construction rather than the preposition, using the shapes mechanism already in the file: "took the team from manual QA into automated coverage" outcome 20 "putting budget into growth" outcome 12 (via "grow" only) "excited to share my thoughts from the conference" outcome 0 Ordinary prose still scores nothing, which was the reason the bare marker was removed. Not changed: MEETING_ASK_RE does not match gerunds ("arranging a meeting"). The reviewer called it a nice-to-have rather than a fix-now item and I agree — it is a content linter, not a security boundary, and widening it toward gerunds is how the false positives it was written to avoid ("your post on on-call rotations") creep back in. Regression re-run: all 12 policy-gate cases hold; headline sample 93/SHIP with audience 20 and outcome 20, weak sample 19, profile auditor 37/WEAK, analyzer sample ANALYSED with 6 TYPICAL / 3 STRONG / 3 WEAK. Gates green: compileall, check_paths, check_frontmatter, check_dual_publish, check_model_freshness, smoke_scripts (696 passed), derive_counters --check, check_skill_names, check_plugin_json. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s |
||
|
|
4dbb60f30e
|
fix(linkedin): make exemptions visible, and cover the automate-posting phrasing
Three findings from the review on PR #997, all reproduced first. The PR description claimed "the exemption applied is reported in the output rather than silently swallowed". That was only true for the mixed case. _scan attached the excused list to a hit, and a hit is only created when the rule still has an unexempted match — so when EVERY match was exempted, which is exactly what happens for the two headline examples, no hit existed and the trace was discarded. An ALLOW that recognized and excused a prohibited-looking phrase looked identical to one that never matched anything. Exemptions are now collected regardless of verdict and surfaced as exemptions_applied, so the claim is true as written. render_human never printed them either, even in the mixed case, so the reasoning was JSON-only for the output mode most likely to be read interactively. It now prints a "Recognized but exempt" block. The P1 exemption covered only the auto-post family, so the same endorsed action phrased through the other pattern — "automate posting with LinkedIn's native scheduler" — still refused, leaving one instance of the self-contradiction this PR exists to fix. The bare token "automate" is far too generic to exempt on the scheduler signal alone, so exemptions now support an optional positional context that must appear just after the matched word. Verified both directions: "automate posting with LinkedIn's native scheduler" allows, while "use LinkedIn's native scheduler and automate my DMs" still refuses. Not changed: _read_input is duplicated across the eleven scripts. That is the repo's self-contained-package rule (CLAUDE.md lists cross-skill dependencies as an anti-pattern), and these scripts live in six different skills. The cost is real — a future change needs eleven synchronized edits — and it is the deliberate trade. A verification note worth recording: an earlier before/after run in this session compared HEAD against the working tree after the fix was already committed, so it compared the fix with itself and appeared to show the bypass never existed. The real baseline is origin/dev, against which the bypass reproduces (exit 0, no premature-ask) and the fix blocks it (exit 3), with innocent phrasing unaffected at exit 0 both before and after. Regression battery re-run: all eleven policy-gate cases hold, including every no-bypass control. Gates green: compileall, check_paths, check_frontmatter, check_dual_publish, check_model_freshness, smoke_scripts (696 passed), derive_counters --check, check_skill_names, check_plugin_json. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s |
||
|
|
4e771557a5
|
fix(linkedin): repair the policy gate's self-contradictions and six related defects
Addresses the marketing/linkedin findings raised during PR #994's review, which were deliberately left out of that PR because the plugin was already-merged content riding along in the diff. Each was reproduced before being fixed, and each fix verified in both directions. Two rules refused the exact action their own substitute recommends: export my connections list as a csv was REFUSE -> now ALLOW LinkedIn's native scheduler to auto-post was REFUSE -> now ALLOW P2-SCRAPING told the user to run LinkedIn's own data export while refusing the phrase for it; P1-AUTOMATION refused native scheduling that P7's substitute names as the supported path. Rather than loosening the patterns, _scan now supports per-rule exemptions that drop a single matched snippet and never the whole rule, so a sentence mixing an endorsed action with a prohibited one still refuses. Verified: "native scheduler to auto-post AND auto-connect with 500 recruiters" still exits 4, as does "export my connections list AND scrape their emails", and a leads database is still not the self-export. The exemption applied is reported in the output rather than silently swallowed. P3's pod lookahead could only match noun-before-verb ("pods to join"), so the common "join a pod" was structurally unmatchable. Added the verb-first form; both phrasings now refuse. outreach_message_builder.py only checked the --ask field for a premature ask, so the same ask moved into --reason or --specific-line passed clean, making the documented "refuses an ask in a first-touch note" guarantee bypassable. The note body is now scanned with a meeting-request pattern rather than the loose ASK_RE, which would have flagged "your post on on-call rotations" — verified that innocent phrasing still passes while both hiding places now block. post_performance_analyzer.py labelled every post BREAKOUT on zero-dispersion data: with identical rates the IQR is 0, every fence collapses onto the median, and the >= hi_fence test fires for all of them. Twelve identical posts went from 12 BREAKOUT to 12 TYPICAL; varied data is unchanged. Two profile tools credited prose as signal. The auditor counted bare "to"/"from"/"x" substrings as outcomes, so "Reported to the VP of Engineering" scored as outcome-carrying; multipliers and from/to deltas are now shapes requiring a number. headline_scorer counted bare "for "/"to "/"from "/"into ", so "excited to share my thoughts from the conference" scored both audience and outcome. Removing them alone cost a real signal — the sample's "Head of Data for Series A/B SaaS" names an audience through the construction — so the directed-at construction is restored as a shape that must land on an actual audience noun. Sample score is unchanged at 93 and the weak sample at 19, while the prose false positives are gone. All eleven scripts crashed with a FileNotFoundError traceback and exit 1 on a mistyped --input; each now exits 2 with a message. The two analytics scripts died with AttributeError on a bare list of scalars; both now exit 4 naming the problem. Note that catching json.JSONDecodeError does not catch ValueError - the subclass relation runs the other way - so the analyzer's except clause was widened rather than left to trade one traceback for another. cadence_planner reported FITS with exit 0 while handing back a week containing zero posts; that now returns NO_POSTS_AFFORDABLE with exit 3 and a blocking finding, with the docstring's exit table updated. Normal budgets are unaffected, the below-floor path still exits 2, and --sample still exits 3 for its own pre-existing reason. pattern_miner's multiple-comparisons note now states plainly that it is an accounting of expected false positives and not an applied Bonferroni or BH correction, so the number cannot be read as a stronger guarantee than it is. Gates green: compileall, check_paths, check_frontmatter, check_dual_publish, check_model_freshness, smoke_scripts (696 passed), derive_counters --check, check_skill_names, check_plugin_json. The advisory JSON-output gate still reports its 8 pre-existing agent-launcher failures; none is in this plugin. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BswsZp5zrJWFAGU6KWNA1s |
||
|
|
645c523be1
|
feat(marketing): add linkedin plugin — organic presence with platform rules in code
Answers discussion #934, which asked for a strategic assistant for growing a LinkedIn presence organically rather than a post generator. Six skills under marketing/linkedin/: an orchestrator (context: fork) plus profile, strategy, content, engagement, and analytics lanes. 17 stdlib-only tools, 15 references, 2 agents, 8 /cs:* commands. The design constraint is the differentiator: no LinkedIn credentials, no API calls, no scraping, nothing auto-sent. Automated posting, connecting, and commenting are prohibited by LinkedIn's User Agreement 8.2, and a restricted account ends a compounding asset. linkedin_policy_gate.py runs before any drafting and refuses seven request classes — automation, scraping, engagement pods, bulk messaging, fake identity, fabricated proof, named third-party automation platforms — each carrying the policy anchor and a compliant substitute, so the gate never just says no. Refusals are real rather than advisory. A cadence under 90 minutes a week returns a comment-only plan instead of a schedule that dies in week five. A newsletter whose six-month cost exceeds the budget is refused before the promise is made. An experiment needing more posts than a quarter allows is reported infeasible rather than quietly re-sized. The pattern miner refuses to test anything below 10 posts and reports NOTHING_SURVIVED as a finding. Evidence discipline: two widely repeated claims are corrected rather than propagated. The "personalised note triples acceptance" claim is not supported by the largest samples (acceptance is near-identical either way, ~26.4%); what a note moves is the post-accept reply rate (~5.4% to ~9.4%), which is why the message builder refuses an ask in a first-touch note. The ~19% in-body link reach reduction has never been confirmed by LinkedIn as a penalty and has a plausible dwell-time explanation, so it is a warning rather than a block. Every reference carries per-claim confidence levels. Accessibility is a blocking lint finding: Unicode pseudo-bold is announced by screen readers as mathematical symbols and is not indexed by search. All six SKILL.md files are 6/6 PASS on the write-a-skill checklist. Every tool supports --help, --sample, and --output json with typed exit codes. Counters: skills 380 -> 386; plugins 96 -> 97; tools 706 -> 723; refs 823 -> 838; agents 114 -> 116; commands 138 -> 146 (derive_counters.py --check). Also syncs three previously-merged skills (agent-memory, hivemind, skill-doctor) into the .hermes/ and .vibe/ mirror trees, which had drifted behind .codex/. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JSPxUHU6utqme7qC6EwHEh |
||
|
|
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 |
||
|
|
a088c8ba77
|
fix: phantom-path sweep — 888 unresolvable references to zero
A directory reorg added a skills/ path segment; hundreds of references never followed. This sweep repoints every path-like reference in SKILL.md, agents, commands, orchestration, and templates to verified on-disk targets: - 30 root commands + 19 root agents: missing skills/ segment inserted - 7 c-level persona agents: 17 hallucinated reference filenames substituted with the real files (e.g. okr_execution.md -> process_frameworks.md) - 5 research skills: phantom scripts/office/validate.py step replaced with a runnable stdlib zip-integrity check - email agents: skills frontmatter corrected to productivity/email - orchestration/ORCHESTRATION.md + templates: stale paths fixed; agent-template now requires trigger phrasing in descriptions (root cause) - 76 more files across engineering, c-level-advisor, compliance-os, research-ops, ra-qm, marketing, productivity; dual-publish pairs mirrored - dead refs dropped/replaced where no target ever existed (REGISTRY.md, trend_analyzer.py, cursor-microinteractions.md) New: scripts/check_paths.py linter (CI gate G1) + narrow allowlist for teaching examples. Verified: 540 files scanned, 0 unresolvable. https://claude.ai/code/session_019AJddAL1NADWMXsy1qNPQF |
||
|
|
3db7dab15f
|
chore(versioning): unify remaining 20 plugins to 2.9.0
PR #756 normalized most marketplace versions to 2.9.0, but 20 newer plugins (added after the normalization pass) remained on their own versions on both marketplace.json and their plugin.json. Bump them all to 2.9.0 so the registry advertises one unified release version, with marketplace.json and every plugin.json fully in sync (62/62 at 2.9.0). https://claude.ai/code/session_01JGwZR83iSg59EAtpTSCBjH |
||
|
|
6e45e578b5
|
release(v2.7.0): version bumps + CHANGELOG + plugin.json schema doc
Final polish for v2.7.0 release. Changes: - All 12 v2 plugin.json files bumped 1.0.0 → 2.7.0 (release alignment) - CHANGELOG.md: new v2.7.0 section documenting the 13 skills, 3 new domain folders, marketplace + codex sync, Path-B convention, and 8-phase audit verification results - CLAUDE.md: 'Current Version' bumped 2.6.1 → 2.7.0 with v2.7.0 highlights block (13 skills, Path-B pattern, verification summary) - CLAUDE.md: ClawHub plugin.json schema clarified — `source` and `attribution` formally accepted as approved extension fields (consistent with existing pattern across 13 new v2 skills + 3 engineering Matt-Pocock-derivative plugins). Stripped at ClawHub-publish time if/when stripping pipeline lands. - CLAUDE.md: ClawHub rule #6 version reference bumped 2.2.0+ → 2.7.0+ Audit verification before release: - 39/39 scripts pass --help across all 13 v2 skills - Spot-check audit (pulse/litreview/notebooklm): all 86.4/GOOD structure, 3/3 scripts, 0 critical/high security findings - Bulk audit (9 remaining skills): all 79.5-86.4 structure, 0 critical/high security findings (1 false positive in syllabus: hardcoded user-facing error message string contains 'npm install docx' — not runtime install) - Cross-skill consistency: 7/7 research-pack siblings carry the Agent Integrity Rules block; orchestrator disambiguation present in 5 places https://claude.ai/code/session_01FEUmeuYhmnxVFq7EZM8ZSw |
||
|
|
6d9630f83c
|
chore(cleanup): move pulse + capture to proper domain folders
Surgical move PR — resolves the two domain warts accumulated during
the v2 megaprompt build sweep:
engineering/pulse/ → research/pulse/ (research-pack — pulse is
the first research skill;
now joins litreview, grants,
dossier, patent, syllabus)
engineering/capture/ → productivity/capture/ (productivity — capture
is brain-dump organizer,
not engineering tooling)
WHY THIS PR
When Slice 1 (capture) shipped in PR #659, the productivity/ domain
folder didn't yet exist. When Slice 2 (pulse) shipped in PR #660, the
research/ folder didn't yet exist either. Both were placed in
engineering/ as the catch-all.
After Slices 3-5 established the productivity/, marketing/, and
research/ top-level domain folders, those two early skills were left
in engineering/ as warts. This PR resolves them BEFORE Slice 7
(13-research orchestrator) so the orchestrator can reference
research/pulse/ as its routing target without further path churn.
WHAT MOVED
Two directories moved via `git mv` (preserves rename history):
- engineering/pulse → research/pulse (11 files)
- engineering/capture → productivity/capture (11 files)
INTERNAL REFERENCES UPDATED
Inside the moved directories:
- .claude-plugin/plugin.json homepage URLs (engineering/X → new path)
- agents/cs-*.md `skills:` frontmatter field
CROSS-SKILL REFERENCES UPDATED
6 external files reference pulse and/or capture as sibling skills.
All updated via sed:
productivity/email/agents/cs-inbox-setup.md (capture ref)
productivity/email/agents/cs-inbox-triage.md (pulse + capture refs)
research/grants/agents/cs-grants.md (pulse ref)
research/litreview/agents/cs-litreview.md (pulse ref + stale
"will move in cleanup
PR" caveat removed)
research/dossier/agents/cs-dossier.md (pulse ref)
marketing/landing/agents/cs-landing.md (pulse + capture refs)
CODEX SYMLINKS RE-POINTED
.codex/skills/{capture,pulse} symlinks updated to point at new
locations. Verified resolution to SKILL.md files works.
.codex/skills-index.json still references the old paths — this file
is auto-regenerated by the codex-sync workflow on every merge to dev
(prior commits:
|
||
|
|
8690081a04
|
feat(marketing): landing skill — Path-B generator slice from megaprompt 04
Slice 4 of 13: generator shape. Validates the Path-B conversion pattern for skills that produce a single artifact (HTML file) with motion-design discipline. Also introduces the marketing/ domain folder (parallel to productivity/, separate from the existing structured marketing-skill/ folder that houses the 44 pod-based marketing skills). SOURCE SPEC megaprompts/04-landing-megaprompt.md (PR #657). The megaprompt is the canonical spec; this plugin is the working implementation. WHAT THE SKILL DOES Premium single-file HTML landing page generator. Outputs one polished .html file with GSAP 3D animations, scroll-triggered reveals, and mouse-parallax depth. All CSS inline, all JS inline; only externals are Google Fonts (Inter) + GSAP via CDN. Phase 0: 4 forcing intake questions (one at a time): Q1 — product/service (refuses vague pitches) Q2 — audience register (technical/business/consumer/internal) Q3 — brand overrides (HEX vars, or "default") Q4 — tone (professional/playful/authoritative/minimal) Then generates a single .html with three sections (Hero, Features, Closing CTA), GSAP entrance timeline, mouse-parallax handler, ScrollTrigger feature reveals, CSS floating shapes, scroll indicator. DOMAIN FOLDER DECISION (marketing/ — new) The existing marketing-skill/ folder houses 44 pod-based marketing skills with its own internal structure. v2 megaprompt-derived landing skill is a single self-contained plugin — placing it inside marketing-skill/ would disrupt that folder's pod structure. Creating marketing/ alongside it, parallel to the new productivity/ folder, gives the v2 megaprompt slices a clean visually-parallel home. Both folders coexist. DISAMBIGUATION FROM EXISTING landing-page-generator The repo already has product-team/skills/landing-page-generator/ — the v2.1.2 work that outputs Next.js TSX + Tailwind for conversion-optimized lead-gen with copy frameworks (PAS/AIDA/BAB). The v2 megaprompt 04 is a DIFFERENT skill: single-file HTML with GSAP for premium visual one-pagers. Different output (HTML vs TSX), different optimization target (visual premium vs conversion), different animation approach (GSAP vs static). Both skills coexist. README.md disambiguates clearly. Pick by use case: visual premium one-pager → marketing/landing/ conversion lead-gen → product-team/skills/landing-page-generator/ PATH-B CONVERSION DISCIPLINE - Frontmatter description preserved verbatim from megaprompt spec. - Workflow structure (megaprompt lines 28-43) became SKILL.md section ordering 1:1. - All 4 grill-me intake questions preserved verbatim with "why I'm asking" rationale. - All 5 animation patterns preserved (Hero Entrance / Mouse Parallax / ScrollTrigger Reveals / CSS Floats / Scroll Indicator). - Default brand palette preserved verbatim (--navy / --teal / --teal-glow / --amber / --off-white / --text-muted / --card-bg / --card-border). - All 3 sections (Hero, Features, Closing CTA) preserved with full spec. - Required CDN dependencies preserved verbatim. - Anti-patterns + error-handling table + validation checklist preserved. REPO STRUCTURE marketing/landing/ ├── .claude-plugin/plugin.json ← source.spec field points at megaprompt ├── README.md ← disambig from landing-page-generator ├── agents/cs-landing.md ← landing generator persona, FOUC enforcer ├── commands/cs-landing.md ← /cs:landing └── skills/landing/ ├── SKILL.md ← Path-B converted from megaprompt 04 ├── references/ │ ├── brand_system_design.md ← color theory + WCAG + algorithmic │ │ derivation (7 sources: WCAG 2.2, │ │ Refactoring UI, Material Design, │ │ IBM Carbon, APCA, Tailwind, etc.) │ ├── gsap_animation_patterns.md ← 5 animation patterns canon (7 sources: │ │ GSAP docs, Val Head, Rachel Nabors, │ │ Sarah Drasner, GPU-accel CSS, Material │ │ motion, WCAG 2.3.3) │ └── single_file_html_discipline.md ← inline + CDN-only rationale (7 sources: │ MDN, Inclusive Components, Resilient │ Web Design, no-build advocacy, etc.) └── scripts/ ├── brand_palette_validator.py ← stdlib: HEX validation + WCAG contrast │ + algorithmic palette derivation in HSL ├── kebab_slug_generator.py ← stdlib: name → kebab + duplicate detection └── html_validator.py ← stdlib: 11-rule structural post-gen check 11 files, 1,979 lines. Slightly heavier than capture (1,560) and pulse (1,643) due to denser SKILL.md (346 lines — full CSS + JS code blocks for all 5 animation patterns) and heavier html_validator.py (11 rules vs the simpler 7-rule checks in other slices). VERIFIED CLEAN - brand_palette_validator.py: sample (orange primary + teal accent + near-black bg) correctly surfaces real WCAG issue: white text on #FF6B35 = 2.64:1 (FAILs body-text 4.5:1 threshold). Real-world validation working as designed. Algorithmic palette derivation produces full var set in HSL space. - kebab_slug_generator.py: "Quill AI — Async Standup Tool" → kebab slug correctly handling em-dash. Duplicate detection + timestamp suffix suggestion. - html_validator.py: 17/17 PASS on clean sample; correctly catches 9 FAILs + 6 WARNs on violation sample (missing viewport, external CSS file, external JS file, missing 2 of 3 sections, missing gsap.set() before timeline, missing both responsive breakpoints, div with onclick, duplicate H1). - All 3 with --output json: valid JSON. - plugin.json validates; conforms to repo schema with source + distinct_from attribution. MEGAPROMPT FIDELITY MARKERS (in SKILL.md) Phase 0: 1 Hero: 18 900px: 3 gsap.set: 6 Features: 5 580px: 3 mouse parallax: 3 Closing CTA: 1 OUTPUT_DIR: 3 ScrollTrigger: 4 GSAP: 25 kebab: 4 CSS keyframes: 1 Google Fonts: 5 FOUC: 3 All megaprompt-mandated terms surface multiple times. VERTICAL-SLICE STATUS ✓ Slice 1: capture (light prompt-flow, PR #659 merged) ✓ Slice 2: pulse (research-pack, PR #660 merged) ✓ Slice 3: email-pair (workflow-pair, PR #661 merged) ✓ Slice 4: landing (generator — this PR; introduces marketing/) ☐ Slice 5: orchestrator/router (13-research) — last shape; must reconcile with existing engineering/autoresearch-agent/ After Slice 5, all 5 shapes are validated. The remaining 8 megaprompts (02-reflect light prompt-flow + 6 research-pack siblings + 03-notebooklm which is research-flavored) can be batched in larger PRs grouped by shape. NOT DONE IN THIS PR (intentional) - .claude-plugin/marketplace.json not updated (separate concern; done after all 13 ship) - .codex/skills/landing symlink not added (auto-sync workflow handles on merge per existing pattern) - engineering/capture/ NOT moved to productivity/capture/ (would break anyone who installed from current path; address in separate cleanup PR) https://claude.ai/code/session_01FEUmeuYhmnxVFq7EZM8ZSw |