Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
e474445
Add dating app shadowban FAQ
mikepsinn May 19, 2026
a964b02
Fix MCP updateTask admin bypass + add autoplan pre-existence and CBA …
mikepsinn May 19, 2026
a070dd5
Rename icewad → ic2ewd across live source + tests
mikepsinn May 19, 2026
a18b580
Add commerce store and dating foundation
mikepsinn May 20, 2026
327e6ec
Preserve legacy grant task seed keys
mikepsinn May 20, 2026
e721198
Stabilize shirt artwork image test
mikepsinn May 20, 2026
132af02
Allow iconless treaty chrome
mikepsinn May 20, 2026
4c96d8c
Polish campaign print surfaces
mikepsinn May 20, 2026
f920e00
Fix shirt URL font floor
mikepsinn May 20, 2026
6f5b0a2
Swap shirt copy + harden back-image renderer + parameter-back print copy
mikepsinn May 20, 2026
4a2da4e
Hardcode "30 seconds" on shared print copy
mikepsinn May 20, 2026
b4d5205
Rename foundation grant tasks Fund -> Join + add org-scaling backlog
mikepsinn May 20, 2026
2c7a5e3
Rename organization endorsement route to join
mikepsinn May 20, 2026
b7b3e67
Address shirt artwork review feedback
mikepsinn May 20, 2026
e500e19
Render task description as markdown in task assignment email
mikepsinn May 20, 2026
c04e884
Add /foundations stub + /shirt Earth-Optimization-Day frame + /join +…
mikepsinn May 20, 2026
547a5aa
Sanitize HTML in task assignment emails + fix /foundations heading scale
mikepsinn May 20, 2026
d50b7e1
Add funding-blocked Task primitive schema (3 tables + 4 enums)
mikepsinn May 20, 2026
4d581c9
Bump web typecheck heap to 8GB in CI
mikepsinn May 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion .claude/codex-delegation.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,15 @@ Claude edits meta-config (CLAUDE.md, this file, `.codex/config.toml`, hook scrip

## Every Codex prompt must contain

1. **Mikepsinn's verbatim message**, quoted. The user often uses speech-to-text — typos expected; interpret intent, don't surface-correct. Verbatim quoting eliminates Claude-as-telephone-game mutation.
1. **Mikepsinn's verbatim message + Claude's cleaned interpretation + relevant historical context.** Three sub-parts, in this exact shape:

a. **Verbatim quote** of Mike's current statement in a `>` blockquote. Zero mutation. Voice-to-text — typos expected.

b. **Claude's cleaned interpretation** of intent in a second `>` blockquote, prefixed `[interpretation]:`. Fix ONLY obvious voice-recognition artifacts: URL spacing (`war on disease.org` → `warondisease.org`), doubled words, missing/extra punctuation, dictation-leakage ("Hey Google, set a timer..."). DO NOT fix: word choices that look weird but might be intentional ("missions", "lousy t-shirt", any phrase that changes strategic meaning if "corrected"). If a phrase is genuinely ambiguous, flag it inline as `[ambiguous: could mean X or Y]` rather than picking one.

c. **Curated historical context** — 3-5 relevant verbatim quotes from earlier Mike statements on the same strategic thread, each in its own `>` blockquote with the turn label. NOT all 50+ messages from the session — just the strategic-arc ones on the same question. Codex's context budget shrinks if dumped wholesale.

The split lets Codex re-read the raw if the cleaned version seems off, while sparing it the attention burden of disambiguating typos. The historical thread keeps Codex from re-deriving context Mike has already settled in prior turns.
2. **Investigate-before-coding** instruction: grep, read, understand. Don't trust the framing blindly.
3. **Push back if the request hurts the 4B-voters-on-the-treaty goal.** State the concern, propose to skip, wait for confirmation. Don't silently comply with work that doesn't move that needle.
4. **Argue back if Claude misread the user.** The verbatim quote makes this checkable.
Expand Down
193 changes: 193 additions & 0 deletions .claude/hooks/enforce-cba-table-on-plan-files.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
#!/usr/bin/env node
// enforce-cba-table-on-plan-files.mjs
//
// PreToolUse hook on Skill: when /autoplan runs, look for the most recent
// plan file in ~/.gstack/projects/<slug>/*plan*.md and verify it contains
// a Cost-Benefit Matrix section with all required columns.
//
// Mike's 2026-05-19 trigger, verbatim: *"it should be like doing a cost
// benefit analysis of the value of features and the complexity cost to
// the code base and to the user interface. it seems like you're just
// suggesting a bunch of ideas and not doing a cost-benefit analysis. do
// we have guidelines to do this? isn't that the whole point of the
// autoplan thing?"*
//
// Why: /autoplan's plan-ceo-review, plan-eng-review, plan-design-review,
// and plan-devex-review challenge premises, architecture, design, and DX,
// but do NOT require a structured comparison of (CC effort × probability
// of value × opportunity cost). Result: reviewers suggest features that
// look reasonable in isolation but don't survive a real CBA against the
// priority order in CLAUDE.md.
//
// Related memory:
// - feedback_promote_violated_text_rules_to_hooks.md
// - feedback_be_opinionated_for_mike_finite_energy.md
//
// Strategy:
// 1. Pass-through unless tool_name === "Skill" AND skill === "autoplan".
// 2. Locate the most recent plan file matching the slug + branch pattern
// under ~/.gstack/projects/<slug>/.
// 3. If no plan file exists yet (first /autoplan invocation), emit an
// advisory reminding that the plan MUST include a CBA section before
// the final gate.
// 4. If a plan file exists, check it for:
// - A heading containing "Cost-Benefit" OR "Cost / Benefit"
// OR "CBA" (case-insensitive)
// - At least one table row mentioning CC hours / effort
// - At least one mention of "opportunity cost" OR "what drops"
// - At least one "Decision:" or decision column entry
// 5. If the section is missing or incomplete, emit a corrective
// template the planner can paste in. ADVISORY for now (exit 0)
// so we measure false-positive rate before hard-blocking.
//
// Bypass: if args contains "CBA-IN-PROGRESS" the hook skips (signals the
// planner is mid-draft and acknowledges the requirement).

import { execSync } from "node:child_process";
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
import os from "node:os";
import path from "node:path";

const PROJECT_DIR = process.env.CLAUDE_PROJECT_DIR || process.cwd();

const REQUIRED_SIGNALS = {
heading: /^#{1,4}\s+.*(cost[\s\-/]*benefit|\bCBA\b)/im,
effort: /(CC\s*(hours|hrs)|effort|wallclock|wall\s*clock)/i,
opportunity: /(opportunity\s*cost|what\s*drops|trade[\s\-]*off|instead\s*of)/i,
decision: /(decision|\bship\b|\bcut\b|\bdefer\b|\bresearch\b|\bkill\b)/i,
};

function safeExec(cmd) {
try {
return execSync(cmd, {
cwd: PROJECT_DIR,
encoding: "utf-8",
stdio: ["ignore", "pipe", "ignore"],
timeout: 4000,
});
} catch {
return "";
}
}

function projectSlug() {
const top = safeExec("git rev-parse --show-toplevel").trim();
if (!top) return "unknown";
const remote = safeExec("git config --get remote.origin.url").trim();
// Best-effort slug: derive from remote URL (owner-repo) if possible,
// else use the directory basename.
const m = remote.match(/[:/]([\w.-]+)\/([\w.-]+?)(?:\.git)?\/?$/);
if (m) return `${m[1]}-${m[2]}`;
return path.basename(top);
}

function findMostRecentPlanFile() {
const slug = projectSlug();
const dir = path.join(os.homedir(), ".gstack", "projects", slug);
if (!existsSync(dir)) return null;
let entries;
try {
entries = readdirSync(dir, { withFileTypes: true });
} catch {
return null;
}
const planFiles = entries
.filter((e) => e.isFile() && /plan/i.test(e.name) && e.name.endsWith(".md"))
.map((e) => {
const full = path.join(dir, e.name);
let mtime = 0;
try {
mtime = statSync(full).mtimeMs;
} catch {
// Intentional silence: stat failure (race with concurrent file
// deletion, permission flake) just means we sort that entry last;
// not worth surfacing.
}
return { full, mtime, name: e.name };
})
.sort((a, b) => b.mtime - a.mtime);
return planFiles[0] || null;
}

function cbaTemplate() {
return [
`## Cost-Benefit Matrix`,
``,
`Required before the final approval gate. Rank impact against CLAUDE.md priority order (1=vote conversion, 2=referral propagation, 3=org endorsement, 4=plaintiffs, 5=leader reminders, 6=discoverability, 7=optimitron OS).`,
``,
`| Option | CC hrs | Wallclock | Expected impact (with units) | Confidence | Brand/UX cost | Opportunity cost (which P0/P1 TODO drops) | Risk-adj score | Decision |`,
`|---|---|---|---|---|---|---|---|---|`,
`| Option A — <name> | N | N | e.g. \"+N treaty signatures / 30d\" | HIGH/MED/LOW | none/low/med/high | name the specific TODO item this displaces | qualitative | SHIP / CUT / DEFER / RESEARCH |`,
`| Option B — <name> | N | N | ... | ... | ... | ... | ... | ... |`,
`| ... (one row per real option, including \"do nothing\" and \"defer to TODO.md\") |`,
``,
`**Verdict from the matrix:** <one sentence explaining the dominant option(s) and why>.`,
``,
].join("\n");
}

try {
const raw = readFileSync(0, "utf-8");
if (!raw || !raw.trim()) process.exit(0);

const hookData = JSON.parse(raw);
if (hookData?.tool_name !== "Skill") process.exit(0);

const skill = hookData?.tool_input?.skill;
if (skill !== "autoplan") process.exit(0);

const args = String(hookData?.tool_input?.args || "");
if (args.includes("CBA-IN-PROGRESS")) process.exit(0);

const planFile = findMostRecentPlanFile();

if (!planFile) {
const msg = [
`[enforce-cba-table-on-plan-files] ADVISORY — no plan file found yet for this project.`,
``,
`When /autoplan drafts the plan, it MUST include a Cost-Benefit Matrix section before reviewers run. The matrix is the structured antidote to "suggest a bunch of ideas without weighing them."`,
``,
cbaTemplate(),
`Rule lives at: .claude/hooks/enforce-cba-table-on-plan-files.mjs`,
].join("\n");
process.stderr.write(msg + "\n");
process.exit(0);
}

const content = readFileSync(planFile.full, "utf-8");
const missing = [];
for (const [key, re] of Object.entries(REQUIRED_SIGNALS)) {
if (!re.test(content)) missing.push(key);
}

if (missing.length === 0) process.exit(0);

const lines = [
`[enforce-cba-table-on-plan-files] ADVISORY — plan file is missing required Cost-Benefit Matrix signals.`,
``,
`Plan: ${planFile.full}`,
`Missing signals: ${missing.join(", ")}`,
``,
`What each signal requires:`,
` - heading: a "## Cost-Benefit Matrix" (or "CBA") section header`,
` - effort: per-option CC hours / wallclock estimate`,
` - opportunity: name the specific P0/P1 TODO that drops if this ships`,
` - decision: SHIP / CUT / DEFER / RESEARCH per option`,
``,
`Paste this template into the plan file before re-running /autoplan:`,
``,
cbaTemplate(),
`Rule lives at: .claude/hooks/enforce-cba-table-on-plan-files.mjs`,
];

process.stderr.write(lines.join("\n") + "\n");
// ADVISORY (exit 0) on first design pass; flip to exit 2 after measuring
// false-positive rate. Hook should never block the planner mid-draft.
process.exit(0);
} catch (err) {
// Intentional silence: hooks must never fail closed on their own crash.
// Surface to stderr for the next-turn Claude to notice without blocking
// the user's /autoplan dispatch.
process.stderr.write(`[enforce-cba-table] hook crashed: ${err?.message ?? err}\n`);
process.exit(0);
}
Loading
Loading