From a9d1cbbecd3365666071136f61a4a680a7058f78 Mon Sep 17 00:00:00 2001 From: chipfighter <92256151+chipfighter@users.noreply.github.com> Date: Fri, 17 Jul 2026 17:26:47 +0900 Subject: [PATCH] chore(repo): keep internal notes out of the public tree MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Untrack CLAUDE.md and experiments/context-measure/measure_fixed_context.py (files stay local), ignore /CLAUDE.md, /discussion/, /experiments/ at the repo root, and drop the README sentence that linked the measurement script — the fixed-context claim now rests only on what the public tree can verify: the CI-frozen budget test. Co-Authored-By: Claude Fable 5 --- .gitignore | 5 + CLAUDE.md | 68 ------------ README.md | 6 +- README.zh-CN.md | 5 +- .../context-measure/measure_fixed_context.py | 103 ------------------ 5 files changed, 9 insertions(+), 178 deletions(-) delete mode 100644 CLAUDE.md delete mode 100644 experiments/context-measure/measure_fixed_context.py diff --git a/.gitignore b/.gitignore index eba4d1b..03bdc94 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,8 @@ # Logs / temporary files *.log *.err + +# Local working notes (kept out of the public repo) +/CLAUDE.md +/discussion/ +/experiments/ diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index b3b38d3..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1,68 +0,0 @@ -# Project guide - -## Current source of truth - -Use the latest GitHub Release / tag for released state. Use the `README.md` on -`main` for the current repository state. - -## What this project is - -`coding-discipline` is a workflow-agnostic, two-layer guardrail plugin for AI -coding agents: spec sync preserves confirmed intent across sessions, while -risk-triggered skills prevent costly engineering shortcuts. The harness owns -speed and orchestration; skills intervene only for specific failure modes; -`spec-sync` writes confirmed goals, boundaries, and acceptance criteria back to -the current source of truth so humans and agents keep building the same thing. - -The product invests only in two foundations that should remain useful as models -improve: hard guardrails against recurring judgment failures, and durable -human-agent intent alignment. - -## Hard boundaries - -- Do not compete with the harness orchestration layer: no subagent scheduling, - plan-mode replacement, worktree orchestration, or model selection. -- Do not add Lite / Strict modes. Risk levels emerge from trigger boundaries. -- Each `SKILL.md` description is the only routing source. The SessionStart - primer must not duplicate the routing table. -- Project guide files point to the current spec; they do not host an active spec. -- Create skills only around named failure modes. If a skill cannot state the - failure it prevents, it does not belong. -- Once a skill triggers, do not soften its discipline. Risk calibration belongs - at the trigger boundary. -- Admit a generic high-risk signal only if it stays broadly costly across - industries and languages; project-specific risks belong in project guidance. -- Fixed injected context is zero-sum: adding text requires removing equivalent - text elsewhere. The English baseline was re-frozen at 4580 characters after - the 2026-07 dedup trim (4944 at v0.8.0). -- Regression cases grow only from real false-trigger / missed-trigger reports - and must map to the description change they justify. Do not maintain a - synthetic scenario suite or make one a release gate. -- The runtime, manifests, templates, issue forms, code comments, and primary - `README.md` are English-only. `README.zh-CN.md` is the sole maintained Chinese - translation. Agent replies still follow the user's language unless requested - otherwise. - -## Stack and directory conventions - -(Not decided.) - -## Definition of done by release - -- v0.6.0 (trigger recalibration): cross-platform CI passes and fixed injected - context does not exceed the v0.5.0 baseline. Trigger quality is calibrated - from real feedback rather than a synthetic release gate. -- v0.6.1 (review without ceremony + evidence timing): CI passes; `code-review` - no longer triggers merely because work enters a PR or merge; verification - accepts only evidence collected after the last relevant change and strong - enough to prove the claim. -- v0.7.0 (spec sync layer): add `spec-sync` and connect it to `brainstorming` - and `verify-before-done`; preserve the other seven descriptions and the - SessionStart primer; present the dual-layer positioning in both READMEs; CI - passes with fixed injected context at 1466 characters against a 1491 budget. -- v0.8.0 (English-first global release): translate the complete active product - surface to English without changing v0.7.0 skill behavior; make `README.md` - the English primary entry and keep only `README.zh-CN.md` as a Chinese - translation; freeze the English fixed-context baseline at 4944 characters; - version both manifests as 0.8.0; all metadata, Linux hook, and Windows hook - tests pass. diff --git a/README.md b/README.md index c385916..84556e8 100644 --- a/README.md +++ b/README.md @@ -42,10 +42,8 @@ clarifying question, through the skill system first. coding-discipline starts from the opposite default. Skills stay dormant until a named failure mode is at risk; routine work runs untouched. The fixed context injected per session is ~1.2k tokens and cannot silently grow — a CI -test fails when it does. Measured with symmetric rules, a workflow -framework's fixed injection is about the same size; the cost that actually -differs is how often a plugin inserts itself, and what it spawns when it -does. [Measure both yourself](experiments/context-measure/measure_fixed_context.py). +test fails the build when it does. The cost that actually differs between +plugins is how often one inserts itself, and what it spawns when it does. On top of the guardrails, this project adds a piece of its own: the spec layer. spec-sync writes confirmed goals, non-goals, hard constraints, and diff --git a/README.zh-CN.md b/README.zh-CN.md index 080e93c..595a87f 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -34,9 +34,8 @@ Superpowers 是一整套工作流:它的引导词要求 agent 在给出任何 coding-discipline 的默认值反过来:skill 平时休眠,只在具名失败模式临近 时才介入,日常改动零打扰。每个 session 的固定注入约 1.2k tokens,而且 -不会悄悄变大——一旦增长,CI 测试直接失败。用同一套规则实测,完整工作 -流框架的固定注入其实差不多大;真正不同的开销是介入频率,以及介入时会 -带出什么。[脚本在这里,可以自己测](experiments/context-measure/measure_fixed_context.py)。 +不会悄悄变大——一旦增长,CI 测试直接失败。插件之间真正不同的开销是 +介入频率,以及介入时会带出什么。 在护栏之上,这个项目加了一块自己的东西:spec 层。spec-sync 把已确认的 目标、非目标、硬约束和验收标准写回项目已有的文档——不需要 diff --git a/experiments/context-measure/measure_fixed_context.py b/experiments/context-measure/measure_fixed_context.py deleted file mode 100644 index 03aca52..0000000 --- a/experiments/context-measure/measure_fixed_context.py +++ /dev/null @@ -1,103 +0,0 @@ -#!/usr/bin/env python3 -"""Measure the fixed per-session context cost of two Claude Code skill plugins. - -Fixed context = everything a plugin adds to EVERY session before the user -types anything: - - 1. SessionStart hook payload — the additionalContext text the hook emits - (wrapper tags included, measured exactly as the host receives it). - 2. Skill metadata — the name + description lines Claude Code loads for - every skill so it can route to them. - -Both plugins are measured with the same rules. Skill bodies are excluded on -both sides: they load only when a skill triggers (progressive disclosure). - -Usage: - python measure_fixed_context.py - -Reproduce: - git clone https://github.com/chipfighter/coding-discipline - git clone --depth 1 --branch v6.1.1 https://github.com/obra/superpowers - python measure_fixed_context.py coding-discipline superpowers -""" -from __future__ import annotations - -import re -import sys -from pathlib import Path - -TOKEN_CHARS = 4.0 # rough English chars-per-token; both sides use the same ratio - - -def frontmatter_meta(skill_md: Path) -> tuple[str, str]: - text = skill_md.read_text(encoding="utf-8") - if not text.startswith("---\n"): - raise SystemExit(f"{skill_md}: no frontmatter") - block = text.split("\n---\n", 1)[0] - name = re.search(r"(?m)^name:\s*(.+?)\s*$", block) - desc = re.search(r"(?m)^description:\s*(.+?)\s*$", block) - if not (name and desc): - raise SystemExit(f"{skill_md}: missing name/description") - value = desc.group(1) - if len(value) >= 2 and value[0] == value[-1] and value[0] in "\"'": - value = value[1:-1] - return name.group(1), value - - -def skills_meta_chars(skills_dir: Path) -> tuple[int, int]: - count, chars = 0, 0 - for skill_md in sorted(skills_dir.glob("*/SKILL.md")): - name, desc = frontmatter_meta(skill_md) - count += 1 - chars += len(f"{name}: {desc}") - return count, chars - - -def coding_discipline_payload(repo: Path) -> str: - plugin = repo / "plugins" / "coding-discipline" - body = (plugin / "hooks" / "skill-discipline.md").read_text(encoding="utf-8") - mech = ( - "> On this host, invoke the skill with the **Skill tool**. Reading " - "`SKILL.md` as an ordinary file does not count as invoking it." - ) - return f"\n{body}\n{mech}\n" - - -def superpowers_payload(repo: Path) -> str: - body = (repo / "skills" / "using-superpowers" / "SKILL.md").read_text(encoding="utf-8") - return ( - "\nYou have superpowers.\n\n" - "**Below is the full content of your 'superpowers:using-superpowers' " - "skill - your introduction to using skills. For all other skills, " - f"use the 'Skill' tool:**\n\n{body}\n" - ) - - -def report(label: str, payload: str, skills_dir: Path) -> int: - count, meta = skills_meta_chars(skills_dir) - total = len(payload) + meta - print(f"{label}") - print(f" SessionStart hook payload : {len(payload):>6,} chars") - print(f" skill metadata ({count:>2} skills): {meta:>6,} chars") - print(f" fixed context total : {total:>6,} chars (~{round(total / TOKEN_CHARS):,} tokens)") - return total - - -def main() -> None: - if len(sys.argv) != 3: - raise SystemExit(__doc__) - cd_repo, sp_repo = Path(sys.argv[1]), Path(sys.argv[2]) - - cd_total = report( - "coding-discipline", - coding_discipline_payload(cd_repo), - cd_repo / "plugins" / "coding-discipline" / "skills", - ) - print() - sp_total = report("superpowers", superpowers_payload(sp_repo), sp_repo / "skills") - print() - print(f"ratio: {sp_total / cd_total:.2f}x") - - -if __name__ == "__main__": - main()