{"slug":"harness-authoring","title":"harness-authoring","summary":"Decide where an instruction belongs and write it there, then sync and lint. Use when asked to add, change or remove a rule, skill, instruction, hook, setting or CLAUDE.md line, to \"remember\" something that should persist beyond this session, or when a correction should apply to f","platform":"Claude","tags":[],"authorName":"LLM Mart","authorSlug":"llm-mart","score":0,"source":"github","price":null,"verified":false,"createdAt":"2026-09-24T15:41:10.785403Z","repo":{"url":"https://github.com/JakeSelby/agent-harness","stars":16,"forks":1,"license":"MIT","updatedAt":"2026-09-24T13:44:24Z"},"bodyHtml":"<hr>\n<h2>name: harness-authoring\ndescription: Decide where an instruction belongs and write it there, then sync and lint. Use when asked to add, change or remove a rule, skill, instruction, hook, setting or CLAUDE.md line, to \"remember\" something that should persist beyond this session, or when a correction should apply to future sessions.</h2>\n<h1>Harness authoring</h1>\n<p>Every instruction has exactly one right home. This skill finds it, writes there, and keeps the\nharness checkout as the source of truth for everything generic.</p>\n<h2>Find the checkout and the caller</h2>\n<pre><code>python3 - &lt;&lt;'EOF'\nimport json, pathlib\nm = json.load(open(pathlib.Path.home() / \".local/state/agent-harness/manifest.json\"))\nprint(m[\"repo\"])\nEOF\ngit -C \"$(…)\" remote -v\n</code></pre>\n<p>If the manifest is missing, locate or install the harness before editing managed content.\nDo not create a second authority in a runtime configuration directory. If <code>origin</code> is <code>&lt;owner&gt;/agent-harness</code> and you are that owner, you are the\n<strong>maintainer</strong>. If <code>origin</code> is a fork and <code>upstream</code> is the harness, you are a <strong>fork user</strong>.</p>\n<h2>The ladder — first match wins</h2>\n<ol>\n<li><strong>Must run at a lifecycle point regardless of the model's judgment</strong> (a check before every\ncommit, a validator after every write) → a shared policy under <code>policy/hooks/</code>, dispatched by\n<code>lib/harness_core/lifecycle.py</code>; native registrations belong in runtime adapters.</li>\n<li><strong>Changes tool or editor configuration, not behaviour</strong> → an owned native setting in the relevant\nadapter or editor projection, reconciled by the installer. Do not add a second primitive to represent a runtime setting.</li>\n<li><strong>True of this user only, a secret, or about one project</strong> → never the harness repo. A\npersonal preference goes in user configuration or a custom stance root documented in\n<code>docs/primitive-authoring.md</code>; other personal guidance stays in the runtime personal file.\nA fact about one repo goes in that repo's <code>AGENTS.md</code>.</li>\n<li><strong>A reasonable user would hold the opposite preference</strong> → a stance variant under\n<code>primitives/stances/&lt;pref&gt;/&lt;variant&gt;.md</code>, and a line in <code>config.example.json</code> and\n<code>docs/preferences.md</code>. Never a core rule.</li>\n<li><strong>A procedure with steps, longer than 40 lines, or only needed on a trigger</strong> → a skill\nunder <code>primitives/skills/&lt;name&gt;/SKILL.md</code>, with a description that says when to use it.</li>\n<li><strong>Applies only to some kinds of file</strong> → a rule with <code>paths:</code> frontmatter, in the repo it\napplies to.</li>\n<li><strong>Short, global, wanted on every turn</strong> → <code>primitives/rules/&lt;topic&gt;.md</code>. Check every existing\nrule first; the usual outcome is one sentence folded into an existing file, not a new one.</li>\n<li><strong>Otherwise it is a memory, not an instruction</strong> → auto memory for the current project.</li>\n</ol>\n<p>A \"remember this\" request runs the same ladder from the top. A fact about one project or one\nmachine is auto memory for that project, never the harness. A correction to how the agent\nshould behave anywhere is a rule or a stance, and you say so before writing it. A fact about\nthe user is a personal file, outside the repo.</p>\n<h2>Tests to apply before writing</h2>\n<ul>\n<li><strong>Rule or skill?</strong> Rules load every session and cost context on every turn for every user.\nSkills load on invocation. When a rule starts growing steps, it wanted to be a skill.</li>\n<li><strong>Core or stance?</strong> If you can imagine a competent engineer choosing the opposite, it is a\nstance. Licensing, commit style, testing philosophy and autonomy level are stances; \"verify\nbefore you claim it works\" is not.</li>\n<li><strong>Does it duplicate a global rule?</strong> Grep <code>primitives/rules/</code> and <code>primitives/stances/</code> for the\ntopic. Do not restate a policy that lives in a global rule inside a project rule; link it.</li>\n<li><strong>Is it generic?</strong> No names, no paths under a home directory, no employer, no project. The\nlint will reject it anyway; write it in second person from the start.</li>\n</ul>\n<h2>Write, sync, lint, commit</h2>\n<ol>\n<li>Edit shared sources in the isolated development checkout. Runtime directories contain\nmanaged links and generated views; editing them can change the live checkout or create drift.</li>\n<li>Run <code>bin/harness generate</code> for native views and <code>bin/harness generate --check</code> to verify them.\nSee <code>docs/primitive-authoring.md</code> for custom dimensions and native bindings.\nVerify sync in a disposable home with <code>HARNESS_HOME</code>, <code>CLAUDE_CONFIG_DIR</code>, and <code>CODEX_HOME</code>\nredirected. Sync normal installations from the reviewed release, not the development worktree.</li>\n<li><code>bin/harness lint</code> — fails on personal strings and secret patterns.</li>\n<li>Commit with a Conventional Commit. Then, by who you are:\n<ul>\n<li><strong>Maintainer:</strong> every change goes on a branch in a worktree and opens a PR; the <code>main</code>\nruleset requires green checks and a squash merge. Code changes (<code>bin/harness</code>, shared policy,\ntests) carry a test; content changes are gated by the lint and review.</li>\n<li><strong>Fork user:</strong> commit to your fork's <code>main</code>, which is your live harness. If the change is\nworth sharing, <code>git fetch upstream &amp;&amp; git rebase upstream/main</code>, push a branch to the fork,\nand <code>gh pr create --repo &lt;owner&gt;/agent-harness</code>.</li>\n</ul>\n</li>\n<li>Record in one line where the item went and why, so the placement is auditable.</li>\n</ol>\n<h2>Writing rule and comment text: the conciseness examples</h2>\n<p><code>conciseness.md</code> was cut to its operative lines when the always-loaded context was capped. Its\nworked examples live here.</p>\n<p><strong>Explain a decision once.</strong> Pick the single most natural home for a design rationale — usually\nthe module or class docstring where the thing is defined, or the user-facing doc page for\nanything a user needs. Every other file that touches the concept gets a short pointer back, not\na restatement.</p>\n<pre><code># Bad — restates the full rationale in a consuming file\n# We chunk at 999 rather than the documented 10,000 limit because early testing\n# suggested the endpoint became unreliable above 1,000 records, and because ...\n\n# Good — one line, points at the canonical explanation\n# Chunked per `batch_size`; see the class docstring for the API's limits.\n</code></pre>\n<p>If a second doc explains the same concept as a first, it links to it.</p>\n<p><strong>Don't narrate what the code already says.</strong> Comments explain a non-obvious <em>why</em>. If a comment\nwould be an accurate one-line summary of the next line of code, delete it.</p>\n<p><strong>Docstrings follow the house pattern.</strong> Match the surrounding style exactly. Read a neighbouring\nfunction before writing a new one. Do not add docstrings purely to satisfy a linter that isn't\nrunning; add them where a user of the public API needs them.</p>\n<p><strong>No private-context references in shipped code.</strong> Code, tests, and docs must stand on their own\nto a stranger. No references to planning docs, other repos, internal ticket numbers, or\nevaluation notes. Public issue and PR numbers are fine and useful — they are resolvable by any\nreader.</p>\n<p><strong>PR descriptions.</strong> Lead with what and why in a few bullets, plus a link to the issue. Fill in\nthe template's sections and delete none, but keep each short. A long PR description with heavy\nheading and bold formatting is harder to review, not more informative. Long explanatory content\nbelongs in the issue or in <code>docs/</code>, referenced from the PR body.</p>\n<h2>The always-loaded cap</h2>\n<p><code>primitives/instructions.md</code>, every file in <code>primitives/rules/</code>, and the longest variant of each\nstance dimension are loaded on every turn of every session. <code>harness lint</code> fails when their combined\nsize exceeds <code>ALWAYS_LOADED_TOKEN_CAP</code> in <code>bin/harness</code> — a third of the 12,607-token standing\ncontext measured in issue #430, and the binding limit — or the secondary <code>ALWAYS_LOADED_CAP</code> in\nlines. Both are printed on every lint run. A rule that needs more room than the\ncap allows is telling you it wanted to be a skill: keep the operative line resident, move the\nrationale, examples and evidence into the skill the rule points at, and leave a one-line pointer\nbehind. The stance count uses the <em>longest</em> variant per dimension, so no configuration a user\ncan select is ever over the cap.</p>\n","files":[{"path":"SKILL.md","sizeBytes":7991,"isText":true}],"reviewScore":null,"reviewSummary":null,"trust":{"provenance":"trusted-source-unreviewed","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow.","bodySource":null},"bodyLocked":false,"purchaseUrl":null,"sourceUrl":null,"report":{"provenance":"trusted-source-unreviewed","screen":{"ran":true,"outcome":"clean","suspicious":0,"notes":0,"hiddenCharacters":false},"virusScan":{"engine":"clamav","status":"clean","scannedAt":"2026-09-24T15:41:26.320442Z","sha256":"97848775E5F5C66D3DFFEAAF33F698A172A968F47B5674A37C68281EE9DD8618","sizeBytes":3805},"review":null,"source":{"repositoryUrl":"https://github.com/JakeSelby/agent-harness","path":"primitives/skills/harness-authoring","license":"MIT","commit":"0c8664f1ff51266df03af64c157b906697dafe77","subtreeSha":"D4A0CDA1834E967463AB881C938CAC93F1DC286DAC462BEE707EBC9EF2B1F22F","lastSyncedAt":"2026-09-24T15:41:09.641234Z"},"reviewedAt":"2026-09-24T15:41:58.237853Z","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow."},"install":[{"target":"skills-cli","command":"npx skills add https://github.com/JakeSelby/agent-harness/tree/main/primitives/skills/harness-authoring"},{"target":"claude-code","command":"claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install jakeselby-agent-harness@llmmart"},{"target":"git","command":"git clone https://github.com/JakeSelby/agent-harness.git"}]}