agentleFS
Space-DinosaursSpace-Dinosaurs/DinoStack/AGENTS.md

DinoStack

AGENTS.md14 starsChanged 12 days agoApache-2.0View on GitHub

A portable package of the agentic engineering protocol for AI-assisted software development. It provides a structured delegation model, risk classification, adversarial review loops, code quality gates, git workflow conventions, and named agent definitions.

  • Pipes a download into a shell
  • Reads credentials
  • Deletes or force-pushes
  • Commits and pushes

The file

We split this AGENTS.md into the rules it gives an agent

6 rules. About 0 are common, 1 is distinctive, and 5 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈1

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 5

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    No enforcement hook may deny conductor Read/Grep/Glob to force delegation, and none may gate on inferred session capability - flat …

    line 17
  2. Very specific:

    Update local main: bin/ds-base-sync <this-checkout-path> main (run from this repo's own checkout, since it's both ticket repo and tool …

    line 60
  3. Very specific:

    After any content/SKILL.md change, run .claude/build.sh to regenerate its SKILL.md copy (.pi/build.sh belongs to the catch-up chore).

    line 74
  4. Very specific:

    Verify DCO author/sign-off with lowercase git log --format=%ae (raw) - uppercase %aE and git show both APPLY .mailmap, which can show a …

    line 79
  5. Distinctive:

    After an isolation-worktree engineer commits, the main checkout's view of that branch ref can lag behind the worktree's own HEAD.

    line 89
  6. Very specific:

    Never include "mode": "opt-in" in doc or adapter example JSON unless demonstrating opt-in activation - it silently disables the methodology …

    line 107

≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
AGENTS.md

dinostack

A portable package of the agentic engineering protocol for AI-assisted software development. It provides a structured delegation model, risk classification, adversarial review loops, code quality gates, git workflow conventions, and named agent definitions.

Decisions

  • Methodology source-of-truth: content/sections/01-*.md-12-*.md (12 sections; 06-capability-preflight.md added by P2, renumbering 06-11 to 07-12). Edit content/sections/ for any methodology change - content/rules/agent-methodology.md no longer exists.
  • scripts/build-methodology.sh is the canonical assembly script; it also supports --corpus minimal|medium|full (DS-204, default full with no flag - byte-identical to the pre-DS-204 output). Only .claude/ and .gemini/ corpus-qualify their build: each invokes it TWICE per build - once plain/--corpus full for a full-corpus sibling file, once with --corpus minimal --full-text-name <sibling-basename> for the skill's trigger-loaded embed - so their skill bodies default to the minimal corpus while a full-corpus fallback stays reachable via a generated "Deferred at this corpus" pointer block. .kimi/ and .copilot/ (generating .github/skills/) were flipped the same way and then HELD BACK in the same DS-204 round (runtime QA came back INCONCLUSIVE for both - no drivable runtime on the verification host) - both invoke it plain, full corpus, unconditionally, same as .codex/build.sh (bash "$REPO_DIR/scripts/build-methodology.sh", unaffected by DS-204) and every other adapter. .cursor/build.sh differs in output structure and skips it.
  • .claude/install.sh manages ~/.claude/CLAUDE.md via a managed_content Python string from content/templates/claude-managed-content.md (lean Skill Loading table). DS-143: the 3 @-import lines (METHODOLOGY.md, code-standards.md, conventions.md) drop when the skill symlink resolves (SKILL_LINK_OK) - methodology loads via /dinostack instead, embedded verbatim into .claude/skills/dinostack/SKILL.md by .claude/build.sh. Broken symlink: install.sh keeps imports and warns. Re-run install.sh after template changes.
  • bootstrap.sh (repo root, PR #109) is the public curl | bash installer: clones to $(pwd)/DinoStack (override AE_DEST_DIR), writes the resolved path to ~/.agentic/agentic-engineering-config.json (repo_dir). /ds-update-agentic-engineering reads repo_dir at runtime (git-rev-parse validated, falls back to ~/DinoStack).
  • skill_auto_load opt-in enforcement (PR #97): hooks/skill-auto-load-check.sh wired per adapter - Claude/Codex: UserPromptSubmit; Gemini: BeforeAgent. Kimi's SessionStart nudge is an independent reimplementation, not a consumer of this file - a repo-wide grep for skill-auto-load-check returns no .kimi hit. OpenCode: session.created plugin (.opencode/plugins/session-context.ts). Cursor: no hook (loaded via .mdc). All install scripts use read-modify-write for config updates - bare overwrite destroys existing keys. OpenCode reads ~/.config/opencode/agentic-engineering.json; all other adapters read ~/.claude/agentic-engineering.json. DS-218 added an applicability filter: the hook fires when skill_auto_load=true and the turn's prompt looks like a software-development request, or when the prompt cannot be determined (fail-open) (see hooks/AGENTS.md for the fail-open contract).
  • FE/QA methodology (P0+P1+P2) shipped 2026-05-28 in 14 PRs (#137-#140, #142-#145, #149-#154). qa_criteria.method enum is now 7 values: browser, api, runtime-required, visual_conformance, accessibility, perceptual_diff, motion. Capability preflight default is blocking as of P2 (9 agents populated; skeptic + orchestration-planner are deliberate no-ops). Canonical new reference docs: content/references/capability-preflight.md and content/references/frontend-discipline.md (7 sections + 8 Skeptic finding categories). Motion scenarios require Playwright (CDP Emulation.setEmulatedMedia); agent-browser cannot execute them. Storybook 6 ships URL format detection only; full SB6 framework adapter procedure improvements are deferred.
  • Project-level identity override: ds-identity --scope project writes <repo>/.agentic/identity.yml. Effective identity resolves 4-tier confirmation-first: project-confirmed > global-confirmed > project-provisional > global-provisional > none. Gitignored per-developer. Resolver: bin/ds-identity + hooks/stop-context.js (5 regression tests in bin/tests/test_agentic_identity.py).
  • Telemetry-commit-on-PR: commit_telemetry toggle in .agentic/config.json (default true) makes /ds-implement-ticket Phase 8 commit .agentic/session-log/<dev>.jsonl as a separate commit when identity is confirmed (!.agentic/session-log/ carve-out in .gitignore). Path-aware PR-checkout resolution + HEAD-branch soft-fail guard prevents wrong-branch commits. Eventual-consistency: a session's own line lands in the NEXT ticket's Phase 8 commit; non-/ds-implement-ticket PRs are not covered.
  • Progressive-disclosure kernel split (PR #340): the always-on methodology body keeps only the governance kernel inline; trigger-only detail lives in content/references/**, reached by read-on-trigger pointers. content/references/design-goals.md Goal 4 (three-question partition test) is canonical for inline-vs-defer. Sections 03/05/06/11 are NOT split - their reference files are supplements, not full copies.
  • .agentic/tasks.jsonl ownership is defined by bin/tests/fold_model.py (DS-108, #521), not prose; ordering is arrival-order only. Gates: test_fold_invariants.py, test_tasks_jsonl_fold.sh.
  • Host-harness instruction conflicts (#530, d6b61e7b; DS-132 generalized one collision to four): kernel rule in content/sections/02-delegation.md; catalog + delegation-suppression rule in content/references/delegation-detail.md §Harness-Injected Instruction Conflicts.
  • No enforcement hook may deny conductor Read/Grep/Glob to force delegation, and none may gate on inferred session capability - flat prohibitions (#530): hooks/AGENTS.md §No gating on inferred session capability.
  • evals/ is git-untracked (decision #203), stays that way pending explicit re-tracking; invisible (not merely ignored) inside an isolation worktree. See evals/AGENTS.md.
  • Post-merge local base-branch sync (#540, DS-121): bin/ds-base-sync, called unconditionally at /ds-implement-ticket Phase 12 - NOT nested under auto_merge_on_ci_green (defaults false). diverged requires BOTH behind>0 AND ahead>0; ahead-only isn't divergence. Taxonomy/recovery: content/references/base-branch-sync.md.
  • Hooks-snapshot dogfooding-gap closure (DS-54 follow-up): a merged hook fix stays dormant on this machine until an installer re-syncs the snapshot - the SessionStart nudge only fires at a brand-new session's first tool call, never mid-session or at merge time. Three mechanisms now close it: bin/ds-doctor's check_hooks_snapshot_staleness check (on-demand; --fix calls sync_hooks_snapshot, the identical call every adapter install.sh already makes unconditionally; half_applied is NOT reported resolved by that sync alone - it only refreshes snapshot content, never an adapter's own hook config, so --fix on half_applied reports it unfixable with an actionable "re-run that adapter's install.sh" message; a nonzero exit from the classifier is a WARN, never a silent OK); bin/ds-base-sync's non-blocking advisory note after every invocation (the one guaranteed post-merge trigger point, since Phase 12 calls it unconditionally; read-only, never mutates); and bin/ds-update's _hooks_snapshot_diverged check, which forces the adapter-install loop on its old_head==new_head early-return path when the live hooks/ source hash diverges from the snapshot's stored hash - closing the case where an operator manually git pulled a hooks change before running ds-update, leaving no diff for the normal rebuild-trigger logic to see (scripts/update.js, the interactive updater, has no direct equivalent on this path - it relies transitively on its own unconditional runDoctor() call instead). None of the three can auto-rewire a live session's hooks from a passive trigger - only an explicit --fix or an adapter install.sh run ever calls sync_hooks_snapshot (the DS-54 invariant). All three hashing call sites (the sync writer, the SessionStart classifier, and ds-update's divergence check) call the SOLE hooks_source_paths function in scripts/lib/hooks-snapshot.sh - never a hand-copied path list. Friction cost: any operator with uncommitted local hooks/ edits gets the full adapter-install loop forced on every ds-update "already up to date" run (the live hash differs from the last sync by construction) - expected, not a bug. Full detail: hooks/AGENTS.md §Downstream consumers "Merged is not live". Adapter asymmetry: .cursor/install.sh and .opencode/install.sh symlink hook config directly into the checkout instead of snapshotting it, so those two harnesses have no dormancy gap at all - Claude Code (the primary harness), Codex, Gemini, and Kimi are the ones subject to it.
  • Resident-set budget ratchet (DS-68 redo, #532; redefined DS-143): scripts/check-resident-budget.sh measures only the post-manifest body of content/templates/claude-managed-content.md (the Skill Loading table - the sole content resident every session after DS-143 stopped ~/.claude/CLAUDE.md @-importing METHODOLOGY.md/conventions.md/code-standards.md). Workflow .github/workflows/resident-budget.yml; suite bin/tests/test_check_resident_budget.sh. Required on main (ruleset 14778332, 15 checks). THRESHOLD ratchets downward - lower it in the same PR as any deliberate shrink; run bash scripts/check-resident-budget.sh for the live figure, never trust a cited pair. Separate gate scripts/check-skill-embed-budget.sh (suite bin/tests/test_check_skill_embed_budget.sh) guards generated .claude/skills/dinostack/SKILL.md three ways: FLOOR (catches regression to pointer-only skill); CEILING (safety boundary on verified-safe injection size, not a tidiness budget - DS-45 found its own arithmetic is 1.1x a 2026-08-07 build-size snapshot (126,509 B, 598 B below the injection-confirmed 127,107 B figure), not 1.1x the injection-verified figure it claims to protect; the 2026-08-19 raise to 145,000 B was an explicit operator decision to unblock work, not a new measurement - see the CEILING constant's own comment); an embed-completeness check (DS-143 follow-up) pinning EXPECTED_SECTION_COUNT/EXPECTED_RULES_COUNT against content/sections/[0-9][0-9]-*.md and content/rules/*.md (excluding module-manifest.md) - bump the matching constant in the same commit as any source add/remove/renumber. check-skill-embed-budget is required on main too (count moved 15->16 when this job was promoted, and 16->15 when check-codex-skill-sync was dropped on 2026-10-31). DS-45 sweep RUN 2026-09-03 via scripts/skill-embed-sweep-harness.sh + docs/skill-embed-injection-sweep.md: headless claude -p probes confirmed intact injection (tail canary, declared_total_bytes, and an exact pad_block_sha256 match) at 140,000 / 145,000 / 150,000 / 160,000 B, so CEILING's current value (145,000 B) is now a genuinely verified-safe injection size - this result says nothing about whether raising CEILING is warranted; do not raise it on the basis of this sweep. Raising it remains a separate operator decision requiring its own new swept confirmation, exactly as before this sweep was run.
  • Root MEMORY.md is untracked (DS-129), same rationale as /decisions.md/.agentic/*: methodology self-improvement scratch, not shippable. MEMORY-archive.md is deleted, the archive pattern retired (DS-130) - an archived entry stops being enforced once it leaves the always-loaded file. Fresh clones and worktree-isolated engineers have no MEMORY.md; put facts an engineer needs in AGENTS.md or the spawn brief.
  • Command file size ratchet: scripts/check-command-file-budget.sh measures the raw on-disk byte size of content/commands/ds-implement-ticket.md directly (wc -c, no build step) - closing the gap left by check-resident-budget.sh, which deliberately measures only the assembled resident set and never sees command files at all. That file grew from 233,942 B to 363,761 B in about two weeks with zero shrink commits before this gate existed. Workflow .github/workflows/command-file-budget.yml, regression suite bin/tests/test_check_command_file_budget.sh. THRESHOLD_BYTES has been raised five times since gate creation (DS-188, DS-170 rounds 2-4, DS-244) and lowered since; its live value is deliberately not recorded here (run the script) - it is meant to fire on sustained growth, not the next paragraph. Shares scripts/lib/budget-gate.sh with the other budget gates (grep -rln '^source .*lib/budget-gate.sh' scripts/*.sh finds the current set), but not identically: every gate sourcing that library calls budget_repo_dir/budget_file_bytes, while only check-resident-budget.sh calls the exit-calling budget_report wrapper - this gate calls the underlying budget_eval directly instead (see the DS-182 paragraph below for why); check-skill-embed-budget.sh calls neither, hand-rolling its own OK-path tail (see the DS-182 paragraph below for why). Advisory, not required: it is deliberately NOT added to the main ruleset's required-checks list - promoting it to a blocking check is a separate operator decision - but the job itself is NOT continue-on-error: it fails (goes red, with a ::error:: annotation) on overage like any other check. THRESHOLD_BYTES ratchets downward over time - lower it in the same PR as any deliberate compression of the file; never raise it to accommodate un-triaged growth, and never trust a cited figure - run bash scripts/check-command-file-budget.sh for the live number.
  • Command arg-substitution gate (DS-192): scripts/check-command-arg-substitution.py fails CI when a bare $0-$9/$ARGUMENTS token reappears inside an executable (bare/bash/sh/shell/zsh) fence anywhere under content/commands/** - the harness's slash-command literal-text argument substitution silently corrupts awk field-selector syntax at any such site before the model ever reads the instruction. Workflow .github/workflows/command-arg-substitution.yml (non-required, scan-only - no regenerate-then-diff step, since that would flip content/commands/ds-implement-ticket.md's provenance under scripts/gate-provenance.sh's D1 rule); regression suites bin/tests/test_check_command_arg_substitution.sh (the six named reddening mutations) and bin/tests/test_arg_substitution_field_rewrites.sh (old-form/new-form byte-identity on representative fixtures). Fixed 12 sites at ticket creation; each converted to whichever substitution-safe form fit its construct (dynamic-field awk, a pure-bash scan, or a non-$N comment wording).
  • Per-PR delta axis on the two shared/merge-order-sensitive budget gates (DS-182): budget_report's pre-DS-182 shape (prints OK/OVER BUDGET and exits itself) is unchanged for its one remaining original caller, check-resident-budget.sh (byte-unchanged; it gained no git axis at all) - scripts/lib/budget-gate.sh split its body into a non-exiting budget_eval (returns 0/1) plus a thin budget_report wrapper (if budget_eval "$@"; then exit 0; else exit 1; fi). New library functions budget_base_resolve <repo_dir> [base_branch] (resolves origin/<branch> then <branch> against -C <repo_dir>, default main; returns 1 and prints nothing when git/a work tree/a resolvable ref is unavailable - takes repo_dir explicitly, same as budget_delta, so both always resolve against the caller's repo root rather than the process's own cwd), budget_delta (signed byte delta of a path between a base ref and the working tree; returns 2 and prints nothing when the path is absent at base - never conflated with a delta equal to the path's own full size), and budget_burn_line (one informational line, ALWAYS returns 0 and ALWAYS prints something - a distinct "burn: SKIPPED (...)" line, never a blank line, when git/a base ref/the base commit date is unavailable). Two different uses on the two gates that needed a git axis: check-command-file-budget.sh (hand-authored file - a PR's diff to it is that PR's own doing) gained a hard-failing per-PR DELTA_LIMIT_BYTES (32,936 B, re-derived as ceil(max_observed_delta * 1.1) from the 43 first-parent non-creation commits touching the file, max_observed_delta = 29,941 B at commit d644217c; fires 0/43 on the history it was derived from) - it calls budget_eval directly (not budget_report), since a delta breach is recorded (delta_over=1) rather than exiting immediately, so the THRESHOLD_BYTES budget_eval report still runs and prints even when both axes are over budget in the same run; the delta context is reported via budget_eval's existing extra-context slot so lines[-1] of stdout (what bin/ds-evaluate's _collect_budget_gates reads as the gate's summary) stays the headroom: line. check-skill-embed-budget.sh (a GENERATED artifact - its size on any branch reflects upstream content/** churn as much as that PR's own diff, the exact "merge order decides pass/fail" failure mode DS-182 exists to close, per KNW-20260818-001) gained only the informational budget_burn_line (a B/day burn RATE, "burn: <B_per_day> B/day over <D> d - <N> d to limit", not a raw delta - <D> is the whole-day span since the resolved base ref's own commit date, floored at 1; <N> = headroom / burn rate, omitted when the rate is <= 0), no hard delta limit. Its OK-path tail is hand-rolled directly in the gate script rather than routed through budget_eval, because bin/ds-evaluate's summary consumer depends on the exact pre-DS-182 wording (ceiling:/headroom to ceiling:), which budget_eval's shared threshold:/headroom: labels cannot express; the burn line is computed once before the FLOOR/CEILING checks and printed on all three exit paths (OK, BELOW FLOOR, ABOVE CEILING), not only the OK path. Both workflow files needed fetch-depth: 0 added to the relevant checkout step(s) (command-file-budget.yml's single job; resident-budget.yml's check-skill-embed-budget job only - check-resident-budget's checkout is deliberately untouched, since that gate gained no git axis at all) or origin/main is unreachable on a default shallow checkout and the git axis silently degrades to its SKIPPED variant on every CI run. All three git-based functions degrade gracefully (never a hard failure) when git is absent or repo_dir isn't a git work tree - verified against every per-gate test suite (grep -rl budget-gate.sh bin/tests/test_check_*.sh finds the current set - test_budget_gate_lib.sh is a sibling library-level suite outside this set and does build a real git init fixture for its own DS-182 scenarios), which have always built their scratch fixtures with zero git init at all. Deciding which axis a NEW budget-gate target needs (a hard per-PR DELTA_LIMIT_BYTES for an AUTHORED/hand-edited target, vs. an informational budget_burn_line for a DERIVED/generated one) is not a fresh judgment call each time: run bash scripts/gate-provenance.sh <repo-relative-path> first - it classifies the target as AUTHORED or DERIVED against the real CI workflows and manifest headers and cites which rule fired. DS-183/184/185/186 (any future budget-gate axis work) should run it before assigning an axis, not re-derive the classification by hand.
  • Dependency-advisory gate: scripts/check-npm-audit.sh audits BOTH lockfiles (package-lock.json, scripts/package-lock.json) and fails only on advisories with a non-breaking fix available. The predicate is actionability, NOT severity, and NOT fixAvailable truthiness: npm reports fixAvailable as a truthy object even when its only remedy is a semver-major change, often a downgrade of a parent package, for an advisory with no patched version at all, so a severity or truthiness predicate would keep main red on advisories nobody can fix (example, measured 2026-11-06, not a live count: every advisory in scripts/ proposed such a fix, e.g. a @marp-team/marp-cli@0.12.1 downgrade flagged isSemVerMajor: true). The discriminator is isSemVerMajor !== true; a breaking-only fix is an operator call, reported on every run but never a failure. npm audit resolves from the lockfile with NO node_modules present, so the gate needs no install step (~0.5 s per manifest). Job: npm-audit in .github/workflows/codeql.yml (placed there for the weekly schedule - the failure class is drift, not diff; see .github/workflows/AGENTS.md); the job installs a pinned npm 11 release before auditing (see the step in codeql.yml), because npm 10.9.9 and 11.3.0 report a non-breaking fixAvailable on @eslint/config-array where none exists. Regression suite bin/tests/test_check_npm_audit.sh drives the predicate through --classify with fixtures, since live output changes whenever the upstream advisory DB does. Advisory, not required - deliberately off the main ruleset's required-checks list, same precedent as check-command-file-budget and check-slide-overflow, but the job is NOT continue-on-error and goes red on an actionable advisory. Covered by scripts/check-local.sh (whose preflight requires npm); it is the only covered gate needing NETWORK, which no preflight can require, so it splits on ${CI} - loud SKIPPED locally, hard red in CI. It can never go green in CI having asserted nothing, but a green LOCAL check-local.sh run is not proof the audit ran; read the gate's own output. Precedence when manifests disagree: an actionable advisory DETECTED in one manifest outranks another manifest failing to audit, and is reported as exit 1 (naming the unaudited manifest too) rather than discarded in favour of a skip. Retirement is keyed to an observable, not to .github/dependabot.yml - that file already configures npm updates for both directories, and security alerts are governed separately from version-update scope. The test: next time the gate goes red, check whether an update PR proposing that same fix was already open BEFORE it fired. That test is only valid on an advisory whose remediating package is NOT covered by an ignore: rule, because an ignore rule suppresses security updates as well as version updates. .github/dependabot.yml ignores @marp-team/* on /scripts, so for any advisory that remediates through @marp-team/* the test is guaranteed to answer "no PR was open" by deliberate config choice rather than by the automation failing - answering the retirement question on it would keep the gate alive on evidence that could never have come out any other way. If the gate has only ever gone red on ignored packages, the test has not been run yet.
  • CI trigger policy (2026-09-03): workflows are PR-only by default; the post-merge run is CONSOLIDATED, not deleted. Do NOT re-add push: branches: [main] to an individual workflow, and do NOT delete .github/workflows/verify-merged-tree.yml on the theory that strict required checks make it redundant - that theory is false here. Ruleset 14778332 sets strict_required_status_checks_policy: true BUT also carries bypass_actors: [{RepositoryRole admin, bypass_mode: always}], and gh pr merge --admin --squash is the normal unattended-agent merge path, so a behind-base PR can merge without being brought up to date. Measured over the 25 most recent first-parent merges by comparing each squash commit's tree object to its PR head commit's tree object: 19 matched, 6 did NOT (#850, #854, #855, #856, #857, #860 - 24%; #850 differed across 46 files). verify-merged-tree.yml (push:main + workflow_dispatch) runs a ~10s needs-full-run gate comparing those two trees and skipping the suite when they match. Its fail-open behavior is TWO-AXIS: inside the script, AND at the job boundary, where all 10 suite jobs guard on if: ${{ !cancelled() && (needs.needs-full-run.result != 'success' || needs.needs-full-run.outputs.run_full == 'true') }} (merged-codex-skill-sync adds inputs.all_harnesses && after !cancelled(), so it runs only on an all_harnesses dispatch) - a bare if: needs.<job>.outputs.<x> == 'true' gets GitHub's implicit success() and would SKIP the suite when the gate FAILS, inverting the contract exactly when the gate is least trustworthy. Never simplify that expression: the ${{ }} wrapper is mandatory (a bare leading ! opens a YAML tag and is a scanner error), and !cancelled() is preferred over always() so an operator cancel does not start all 10 jobs. Two runner-semantics traps that bit this workflow and generalize: (1) GitHub runs a run: block as bash -e {0} unless the step sets shell:, so error-fallthrough branches written on a "no errexit" assumption are DEAD - the gate step sets shell: bash {0} deliberately, and any harness testing a run: block must read the step's own shell: key rather than assuming bash -c; (2) git rev-parse <bad-ref> prints its argument to STDOUT and exits 128, so an emptiness test on its output never fires - use --verify. push: main is NOT only merges: changelog-publish.yml pushes CHANGELOG.md + docs/changelog.html daily with a PAT (CHANGELOG_PUSH_TOKEN - a PAT DOES trigger workflows) and no PR, so the gate has a second run_full=false path for no-PR pushes whose <sha>^ <sha> diff is a subset of a two-entry UNTESTED_SAFE_PATHS allowlist of files no check reads; keep it tiny, it retires when changelog-publish opens a PR instead. The cheap way to keep run_full=false the norm for merges is gh pr update-branch --rebase before an --admin merge (works as of local gh 2.100). A separate 0-catches-in-600-runs/31-merges measurement is evidence that ~19 duplicate runs per merge was the wrong shape, NOT that the post-merge run is unnecessary. codeql.yml, gitleaks.yml, scorecard.yml keep push: main. bin-tests.yml still has its own push trigger: when that is dropped, its three jobs MUST be added to verify-merged-tree.yml in the same change. Canonical policy: .github/workflows/AGENTS.md.
  • Claude Code first (operator ruling 2026-10-30/31): a methodology PR regenerates and checks only .claude (bash .claude/build.sh); the other 10 adapters plus the .github/* Copilot surfaces catch up later in an on-demand chore PR, never in each PR. One switch, DS_ALL_HARNESSES=1, turns the non-Claude set back on everywhere: hooks/pre-commit (all builds, staging, and the Codex skill-sync gate), scripts/check-local.sh, .claude/install.sh's .cursor build, the tests that read or rebuild non-Claude output (bin/tests/harness_scope.py for pytest, [ "${DS_ALL_HARNESSES:-}" = 1 ] in shell, process.env.DS_ALL_HARNESSES === '1' in the hook JS tests), and CI, where it is set for any PR whose branch starts with chore/adapter-catch-up (adapter-sync.yml, bin-tests.yml, hooks-tests.yml, codex-skill-sync.yml) and by verify-merged-tree.yml's all_harnesses dispatch input (which also adds itself to merged-codex-skill-sync's job-level if:, after !cancelled()). check-codex-skill-sync left the required set (15 required checks) and runs only on PRs touching the Codex skill pipeline (paths:) or on dispatch; nothing was deleted. Between catch-ups main carries stale non-Claude artifacts: outside the switch the non-Claude installers skip their build and install the committed files, so ds-update keeps working (Kimi still builds its gitignored per-command skills via .kimi/build.sh --untracked-only), and .codex/install.sh only warns that its source is stale or its staged build failed. The catch-up procedure is in CONTRIBUTING.md "Non-Claude harnesses (catch-up chore)".

Tools

  • GitHub operations: use gh CLI, not GitHub MCP
  • gh pr create requires an authenticated gh session (gh auth status) - run gh auth login if needed.
  • rm -rf is blocked by Claude Code permissions here; remove files individually: rm <file> then rmdir <dir>
  • bin/ds-memory - lightweight retrieval tool for querying .agentic/events.jsonl, MEMORY.md, .agentic/context.md on demand.
  • bin/ds-base-sync - fast-forwards the local base branch after a merge without a checkout; the only way to move a local branch ref outside an explicit checkout+pull.
  • Force-push (--force, -f, --force-with-lease) is blanket-denied by the harness permission layer for subagents AND the conductor; chat authorization doesn't clear it. Push to a NEW branch name instead of rebasing a branch with an open PR.
  • bin/ds-tracker - manages the project-local gitignored .agentic/tracker.yml overlay (init/set/show/path/resolve). Applied after the four-step AGENTS.md tracker chain: overlay is sole source (_source: "overlay") when AGENTS.md declares no tracker or a different one; merges field-by-field (_source: "merged") only when both declare the same tracker. Refuses git-tracked paths; --force-unignored overrides.
  • The Graphify PyPI package is genuinely named graphifyy (double-y); CLI/skill command stay graphify - verified against upstream README, do not "fix" it.
  • git checkout <sha> -- <path> inside a worktree resurrects files a later commit deleted (adds files present at <sha>, doesn't replay deletions). When basing a step on a non-main commit this way, git rm anything it deleted and gate on an exact git ls-files set.

Deploy

  • The docs site (docs.dinostack.ai) auto-deploys on push to main via Vercel git integration (~3 min); verify with curl -sI https://docs.dinostack.ai/<path> | grep last-modified. There is no manual deploy step; do NOT run vercel --prod from a local CLI unless its authenticated scope demonstrably contains the dinostack-docs project (a mis-linked deploy once caused a live 404).
  • dinostack-docs Vercel project's Root Directory is docs/, so Vercel reads docs/vercel.json - repo-root vercel.json is ignored for redirects/rewrites/headers (once caused a live install-URL redirect to silently 404). Put Vercel redirect/rewrite/header changes in docs/vercel.json.

Conventions

  • Base branch: main is the sole integration branch for this repo. Declaration: BASE_BRANCH: main.
  • Workflow for all implementation work (non-Trivial risk):
    1. git fetch origin to ensure latest main.
    2. Spawn subagent Workers using isolation: "worktree" with worktrees branched from origin/main. Worktree path: .agentic/worktrees/<branch-name>.
    3. Worker implements, runs quality gates (lint, typecheck, tests), commits.
    4. Push branch to origin: git push -u origin <branch-name>.
    5. Open PR against main via gh pr create.
    6. Once CI/CD checks pass, auto-merge: gh pr merge --squash --delete-branch.
    7. Clean up: retire or hold each carrier at completion (ds-retire-carrier, content/references/worktree-lifecycle.md §Carrier lifecycle by purpose). Session-start prune + branch-prune remain as backstops.
    8. Update local main: bin/ds-base-sync <this-checkout-path> main (run from this repo's own checkout, since it's both ticket repo and tool source) - fast-forwards local main without a checkout. Fall back to git checkout main && git pull --ff-only origin main only when bin/ds-base-sync is not present at that path.
    • Steps 6-8 are automatic - never pause for merge approval when CI is green.
    • main enforces strict required status checks: a PR whose base has moved must be rebased and re-run before merge - GitHub does not re-run workflows on base movement. Sync with gh pr update-branch --rebase; the default (merge) update produces an unsigned commit that fails the DCO check.
    • Failed CI is a hard stop - investigate before proceeding.
  • Conductor never edits shippable artifacts directly, even Trivial one-liners - delegate to a worktree-isolated engineer from origin/main; conductor may only edit exempt artifacts (.agentic/, conductor-direct prints/decisions/resolver execution). Classifier: content/rules/conventions.md §Git Workflow.
  • Superseding an open PR: close + rebase, never bundle (content/rules/conventions.md §Git Workflow).
  • Sequential isolation:worktree spawns: the worktree is cleaned up between them, so later Workers fall back to the main tree - tell them explicitly. Round-N rework mechanic: content/rules/conventions.md §Git Workflow, content/references/worktree-lifecycle.md §Round-N rework mechanic. (DS-123)
  • Parallel engineer spawn briefs must say "branch your worktree from current origin/main, NOT a local checkout that may include not-yet-merged sibling units" - worktree branch leaks are the most common cross-unit contamination class.
  • Multi-unit PR assembly: main requires DCO Signed-off-by on every commit. Conductor git merge --no-ff is unsigned - cherry-pick each engineer's signed commit (no merge commits) or git merge --signoff. Never force-push to fix; gh pr merge --admin --squash discards merge commits anyway.
  • Pre-commit builds and stages the .claude generated files (.claude/commands/*.md, .claude/skills/dinostack/{METHODOLOGY,SKILL}.md; every adapter's, .codex/agents/*.toml included, only under DS_ALL_HARNESSES=1) only in the primary checkout with a staged content/ change - inside a linked worktree the hook exits early before any build or staging runs. Since an agent is always in a worktree, run bash .claude/build.sh and stage its output manually after any content/ edit.
  • A green bin/tests/ run is not the gate set - the required hooks-js-tests check pins methodology prose byte-for-byte and lives outside bin/tests/, so it is entirely possible to have a green pytest bin/tests/ and a red PR. There is now a single literal command for the locally-runnable part of the set: bash scripts/check-local.sh (exit 0 every covered gate passed, 1 a gate failed, 2 toolchain preflight failed - see CONTRIBUTING.md "Local toolchain"). Its coverage is deliberately partial and it says so: three gates are excluded on cost (the full Codex skill suite, the slides build plus overflow checks, and the gitleaks full-history scan), and every run ends with a NOT RUN LOCALLY (run in CI) block naming them and their exact commands. A green run means the covered set passed, never that CI will be green - read that block. The hooks JS set is derived, never hand-counted: list_hooks_js_tests in scripts/lib/ci-test-discovery.sh transcribes the hooks-js-tests job's own loop (glob hooks/tests/test-*.js minus the case-arm quarantine into the separate wrap-lock-tests job), pinned against a fresh inline re-derivation by bin/tests/test_ci_test_discovery.sh. That exclusion is not a local exemption: check-local.sh runs the two excluded files as its own wrap-lock-tests gate, and bin/tests/test_check_local.sh breaks each in turn to prove it. Do not infer membership from a filename - test-wrap-lock-abandoned.js, test-wrap-lock-session-id.js, and test-wrap-lock-verdict.js all run in hooks-js-tests, not wrap-lock-tests. Two of those prose-pinning tests are test-wrap-md-partA-parity.js (asserts /ds-wrap retains its whole-flow lock) and test-wrap-context-format-golden.js (sha256-pins content/references/wrap-context-format.md from its NORMATIVE marker to EOF).
  • Docs-currency pass is mandatory before any work is declared complete and before its PR merges - ticket work or ad-hoc, regardless of which paths changed. Enumerate the surfaces the diff touched, then verify and update any related documentation that now states something stale; land doc updates in the SAME PR as the work. Candidate doc surfaces to check: docs/index.html, docs/slides/*.md (plus rebuilt .html via bash scripts/build-slides.sh), README.md, CONTRIBUTING.md, content/SKILL.md, and the relevant AGENTS.md sections. This generalizes the content/-triggered bullet below: that bullet's trigger stays mandatory for content/ edits specifically, while this pass applies to all work. Skeptic tiering per content/references/doc-sync-obligation.md.
  • Any change to content/rules/, content/references/, content/agents/, content/commands/, or content/sections/ MUST also update docs/index.html and any affected docs/slides/*.md (then run bash scripts/build-slides.sh and commit the regenerated .html - do not hand-edit the .html; upgrading marp is an intentional same-PR action: bump scripts/package.json + regenerate scripts/package-lock.json + rebuild) in the same PR; additionally, any now-stale count, list, or reference in README.md, CONTRIBUTING.md, or content/SKILL.md is in-scope for the same PR. Public-facing intent debt is the worst kind. The canonical trigger predicate and tiered Skeptic classification for this obligation live in content/references/doc-sync-obligation.md; Skeptic reports missing docs sync as Minor (Blocking-minor: when a public-facing doc actively misleads). Grep the decks by hand: check-slides-sync only compares each .md against a fresh render, so an assertion that is stale in both the .md and its .html passes the gate.
  • Any new interactive prompt in .claude/install.sh MUST use ae_confirm() (reads /dev/tty when available, defaults "no"). Never bare read -p - it aborts under set -euo pipefail + piped stdin (the curl | bash path).
  • After any content/SKILL.md change, run .claude/build.sh to regenerate its SKILL.md copy (.pi/build.sh belongs to the catch-up chore). Pre-commit does not auto-stage these.
  • Mutation-testing a content/ spec assertion requires bash .claude/build.sh (bash scripts/build-all.sh for an assertion that reads non-Claude copies, run under DS_ALL_HARNESSES=1) BEFORE running the test - mutating content/ alone trips the byte-identity assertion and falsely confirms a semantic assertion caught the change.
  • codex-skill-sync CI validates exactly 4 generated native skills under .codex/skills/. It is advisory and runs on PRs touching .codex/** or its generator scripts, and on workflow_dispatch (Claude Code first, above). After changing a canonical input in the catch-up chore: python3 scripts/codex-skills.py inventory --repo . > .codex/skill-compatibility.yml, then .codex/build.sh - never hand-edit generated skill files. That redirect truncates the file to 0 bytes before Python runs, so an aborted run (e.g. a SkillError) leaves it empty on disk - git checkout -- .codex/skill-compatibility.yml restores it. Prefer a temp-file + mv on success, or check exit status first.
  • REPO_DIR is distinct from REPO: REPO is the ticket's own project checkout, REPO_DIR is the dinostack install where bin/-tools live. Resolve via scripts/lib/repo-dir.sh (resolve_repo_dir): repo_dir from ~/.agentic/agentic-engineering-config.json when valid, else ~/DinoStack. bin/ds-resolve-worktree and bin/ds-base-sync both depend on it.
  • Any local adapter-drift check must copy its pathspecs verbatim from the two drift steps in .github/workflows/adapter-sync.yml: Fail on adapter drift (-- .claude, always) and Fail on non-Claude adapter drift (the other 10 adapter dirs PLUS .github/copilot-instructions.md, .github/agents, .github/prompts, .github/instructions, .github/hooks, .github/skills; only under DS_ALL_HARNESSES=1). scripts/build-all.sh's ADAPTERS array omits those six; git diff --exit-code silently exits 0 on a nonexistent pathspec. (.github/skills added DS-186.) Both pathspecs have TWO in-repo consumers, adapter-sync.yml and verify-merged-tree.yml; the duplication is deliberate (extracting it into a composite action would move the assertion out of a workflow file and stop gate-provenance.sh's D1 rule classifying the adapter dirs as DERIVED) and is kept honest by a step in the latter's merged-adapter-sync job asserting each pair of copies is byte-identical.
  • Verify DCO author/sign-off with lowercase git log --format=%ae (raw) - uppercase %aE and git show both APPLY .mailmap, which can show a mismatched author email on a correctly signed commit.
  • Build commits with porcelain git commit -s, never git commit-tree - the plumbing command takes no -s (fails DCO) and skips pre-commit hooks entirely.
  • A new module isn't done until something in content/ invokes it - shipping uncalled and passing review is the default failure. Assert wiring explicitly, as check_prose_wiring() in bin/tests/test_worktree_lifecycle_spec.sh does.
  • docs/planning/ is gitignored - a worktree-isolated engineer branched from origin/main cannot read a plan there. Restate any obligation in the spawn brief; never keep the same binding prose in both (a fix to one copy drifts silently).
  • No CI gate checks for em dashes, so scope the check to your own diff, never the whole file: git diff --cached -U0 | grep '^+.*—' (staged) or git diff -U0 origin/main...HEAD | grep '^+.*—' (branch). A whole-file grep is useless here - 1 em dash pre-exists on main in the resident files (content/rules/code-standards.md 0, content/sections/04-risk-classification.md 1) and will match on every run. That count is the baseline: leave those alone, and treat any added line that matches as a defect to fix before committing - except the two in this bullet's own grep patterns, which are the literal search target and must not be "fixed" (doing so silently breaks both commands).
  • A shell gate whose assertions are guarded by command -v <tool> must hard-fail under ${CI} rather than skip, or the job goes green asserting nothing. bin/tests/test_check_resident_budget.sh:155-156 is the pattern; .github/workflows/bin-tests.yml:57-58 installs zsh so the guard never fires in CI. A silently-skipped assertion is indistinguishable from a pass in the job log.
  • Editing the main ruleset requires the admin gh account - a non-admin token's read of ruleset 14778332 can return bypass_actors empty when the admin read returns an actor. Treat any unfetched-as-admin bypass_actors as unverified, not empty - a PUT built from it can wipe the entry. Back up the full ruleset JSON before any PUT and diff field-by-field after.
  • Session knowledge belongs in root MEMORY.md - untracked by design (DS-129), sole-copy risk accepted; a worktree-isolated engineer branched from origin/main cannot see it, and neither can a fresh clone. Never end a session holding uncommitted MEMORY.md edits with content that exists nowhere else - confirm sole-copy status with git log --all -S "<phrase>" plus git stash list (--all does not cover refs/stash) before letting the session end. Tracked AGENTS.md files must never accumulate uncommitted session-end edits; any change to them is a normal reviewed PR like any other shippable file, never a session-end commit obligation.
  • An isolation:"worktree" engineer spawn with a named branch can leak that branch into the conductor's own checkout and switch its HEAD (once corrupted main). After every worktree-isolated spawn, verify the conductor's own checkout is still on its expected branch (git branch --show-current + git status + git diff --stat) before committing anything from it.
  • Isolation worktrees always branch from main HEAD, never from a named feature branch. A continuation fix for an existing feature branch can't be briefed as "branch from origin/<feature>" - it silently starts from main instead; cherry-pick or push the commit directly onto the existing branch's remote tip instead.
  • After an isolation-worktree engineer commits, the main checkout's view of that branch ref can lag behind the worktree's own HEAD. Push the explicit commit SHA (git push origin <sha>:refs/heads/<branch>), not the branch name, or gh pr create can reject a stale-base push.
  • An adapter-rebuild/baseline-regen commit (or one built from a stale local snapshot) can silently revert unrelated files with CI green - once reverted 51 files from three merged PRs; PR #390/#432 (DS-47) similarly reverted unrelated list items/counts/cross-refs. Verify a "regenerate generated artifacts" commit's diff touches only the intended paths; diff a PR's base..tip for unrelated hunks before merge/rebase; spot-check a key new symbol lands on main after a multi-PR feature, not just "merged."
  • .claude/install.sh has a zsh variable conflict: a local variable named status is read-only in zsh. Avoid status as a variable name in zsh-specific code; run affected blocks in a bash subshell for mixed-shell compatibility.
  • Empty-array expansion under set -u: use ${ARR[@]+"${ARR[@]}"} with the outer expansion unquoted. Figures are argc, measured 2026-09-24 by placing the expansion between two literal arguments and having the callee report $#, written as unset/empty/two-element for /bin/bash 3.2.57 | bash 5.3.9 | zsh 5.9, so 2 means the expansion added nothing and 3 means it added one empty word. Safe form ${ARR[@]+"${ARR[@]}"}: 2/2/4 | 2/2/4 | 2/2/4, and a spaced element stays one word. "${ARR[@]:-}": 3/3/4 | 3/3/4 | 3/3/4. "${ARR[@]-}": 3/3/4 | 3/3/4 | 3/2/4. Either - form can therefore add an empty positional where you wanted nothing, breaking any consumer that rejects one: bin/ds-cleanup-worktrees exits 2. Bare "${ARR[@]}": abort/abort/4 | 2/2/4 | abort/2/4. Outer-quoting the safe form is wrong under zsh: "${ARR[@]+"${ARR[@]}"}" is 2/2/4 | 2/2/4 | 3/3/4. A [[ ${#ARR[@]} -gt 0 ]] pre-guard is equally sound and is what most sites here use. Pin such a construct by executing the shipped block against an argc stub (check_step2_age_passthrough_argv, bin/tests/test_worktree_lifecycle_spec.sh), never by grepping its spelling. DS-189 recorded the wrong remedy in untracked root MEMORY.md, never in this file; DS-252 corrected it.
  • When origin/main advances mid-session, a diff against the new origin/main can make an unrelated, already-merged PR's files look reverted - a diff-base artifact, not a real one. Diagnose by comparing your commit's parent to origin/main; fix by rebasing onto current main and re-running any generator the new commits may have changed.
  • Checking for duplicate in-flight work only at spawn time misses collisions starting (or merging) mid-run - two live sessions once independently fixed the same three tickets. Check open PRs and the shared checkout's git status before spawning, and re-check for a superseding merge right before opening a PR (a dirty mergeStateStatus on a fresh PR is the after-the-fact symptom). When superseded, stand down and cite the superseding PR rather than racing a rebase.
  • Four git lessons: (1) flip a gitignored file to tracked via an additive negation (!.agentic/<file>), never remove the ignore rule; (2) a negation cannot re-include a file whose parent directory is excluded (.agentic/, /.agentic/, bare .agentic defeat !.agentic/qa.md) - only glob forms (/.agentic/*, **/.agentic/**) work; (3) matching is last-match-wins - a negation only overrides an umbrella above it (bin/agentic-migrate once appended umbrellas at EOF and killed every carve-out, fixed #527); (4) git diff --quiet <ref> -- <path> exits 0 for a path never committed to <ref> ("unchanged", not "new") - pair with git cat-file -e <ref>:<path> (fixed #534). Green CI per-PR doesn't guarantee main's end state under concurrent sessions - assert with git ls-files / git check-ignore.
  • Merging to main needs exactly 1 code-owner approval, not 3 (verified against the live ruleset: required_approving_review_count: 1; CODEOWNERS designates * @tysonhummel as sole owner). --admin is still required for gh pr merge when the PR is authored by @tysonhummel (GitHub disallows self-approval), or no @tysonhummel reviewer is present - the normal unattended-agent case. Confirmed merging #483-#486; an approval-required failure on --admin means the bypass actor was removed from the ruleset and needs re-adding in GitHub's UI.
  • The live Claude Code harness auto-locks every isolation:"worktree" worktree at creation. Directory: .claude/worktrees/agent-<agentId> (NOT worktree-agent-<id> - that's the branch name); branch: worktree-agent-<agentId>; git worktree list --porcelain shows locked claude agent agent-<agentId> (pid <pid> ...). Non-force git worktree remove refuses it (remove -f -f needed) independent of any methodology-level lock. Match cleanup detection on the branch-name pattern, not the directory-path substring.
  • Work in an isolation worktree can silently absolutize the .claude/skills/dinostack/{agents,commands,references,rules} symlinks to that worktree's path - the symlink still resolves on the breaking machine, so check-adapter-sync misses it and a merged absolutized symlink breaks the skill for every other clone. scripts/check-symlinks-relative.sh (adapter-sync.yml) gates this in CI; before staging, check git status --short for those four paths, restore with git restore --staged --worktree; audit a landed commit with git ls-tree -r <sha> .claude/skills/dinostack | awk '$1=="120000"{print $4}' then git cat-file -p <sha>:<path> (leading / = broken). Recurs on every build inside an isolation worktree - re-check before every stage. (DS-96, DS-104)
  • Moving inline prose into content/references/*-detail.md creates two silent hazards, neither producing a conflict marker: (1) the original site drifts after extraction as later commits keep patching it while the copy diverges; (2) the extracted block can arrive already wrong, since a verbatim move preserves whatever it asserted and reviewers read the move as a no-op (DS-68's move carried a stale byte figure; PR #420). Re-verify every count/path/figure against live state in the same PR - "verbatim" is a diff property, not a correctness one.
  • A verification step piped through BSD xargs -I{} can assert nothing and still pass: real paths exceed -I's ~255-byte budget, so xargs returns rc=1 and emits nothing, leaving the comparator comparing empty to empty. 2>/dev/null on a comparison step compounds this into a false pass.
  • Adapter/methodology build discipline: content/ is single-sourced into all adapter dirs; a methodology PR runs bash .claude/build.sh then git diff --exit-code -- .claude, and the other 10 adapters catch up in the on-demand chore (Claude Code first, above). content/sections/** changes also need scripts/.methodology-baseline.sha256 regenerated (bash scripts/check-methodology-drift.sh --regenerate). check-adapter-sync tests the merge result, not your branch - rebase onto origin/main and rebuild first.
  • Repo checkout convention: DinoStack; Most adapters use skill name and directory dinostack (.claude/skills/dinostack/, etc.). Codex uses dinostack-codex plus dinostack-codex-{brief,wrap,implement-ticket} in the shared ~/.agents/skills/ namespace to avoid overriding Gemini payloads; its installer migrates only exact-owned old-name symlinks. Config FILENAMES/activation markers did NOT rename: ~/.claude/agentic-engineering.json, ~/.agentic/agentic-engineering-config.json, agentic-engineering: opt-in/opt-out/-profile:/-preset: markers (live in consumer repos we don't control). Slash commands use /ds-*; bin/agentic-* CLI names unaffected. (DS-26)
  • Some content/ source files are hardlinked (not copied) into their adapter destinations, and this is inconsistent across files - check the mechanism, not a fixed list, which goes stale: grep the target build.sh for hardlink_from_content(, a bare ln (no -s), or os.link( - any adapter build whose script calls one of these against a content/ source genuinely hardlinks it (same inode, mutates in place on a content/ edit) rather than copying it. A hand-typed snapshot of which scripts/counts this resolves to has repeatedly gone stale here (DS-90 Unit 5 review) - do not restore one. A rebuild (bash .claude/build.sh, or bash scripts/build-all.sh in the catch-up chore) is still required after any content/ edit regardless of hardlink status, since a fresh git worktree checkout breaks all hardlink relationships (git does not track hardlinks - every worktree gets independent inodes) until rebuilt. (DS-78, DS-90)
  • Adapter dirs contain hand-authored sources build.sh does NOT regenerate (.codex/.copilot/.cursor/.gemini/.github hook files, .opencode/plugins/session-context.ts) - check manually after any adapter source edit or cross-adapter pattern change. (DS-26)
  • Bulk sweeps over evals/ must exclude git worktrees (evals/.worktrees/wt-* are pinned at historical commits) to avoid dirtying checkouts. (DS-26)
  • On a GLM (or any non-Claude-backed) session, spawning a methodology subagent fails immediately - every agent's model: frontmatter is a Claude alias and the Agent tool's model enum is Claude-only. Don't attempt Worker/Skeptic delegation; go conductor-direct with mechanical verification, or switch to a Claude model first.
  • Never include "mode": "opt-in" in doc or adapter example JSON unless demonstrating opt-in activation - it silently disables the methodology on repos without an agentic-engineering: opt-in marker. Show only the field being demonstrated (e.g. { "profile": "relaxed" }) or use "mode": "opt-out".
  • Marp dark-theme reskin gotchas (theme leaks, table/code-syntax fixes): see docs/slides/AGENTS.md.
  • Slide overflow gate (DS-203): scripts/check-slide-overflow.sh (check-slide-overflow job in slides-sync.yml) is wired advisory-only - deliberately NOT on the main ruleset's required-checks list, matching the command-file-budget gate's precedent, but the job itself is a real red job on overage, not continue-on-error. scripts/slide-overflow-baseline.json is membership-only (deck basename -> positional section ids, no px values) - after any edit that inserts, removes, or reorders slides in a debt-carrying deck, re-run node scripts/check-slide-overflow.js --dump-overflows, diff, and commit the updated baseline in the same PR; never hand-typed. The live figure is not hand-typed here either - run jq '[.[] | length] | add' scripts/slide-overflow-baseline.json for the current pre-existing overflow count. The sole load-bearing determinism mechanism is a fresh headless-Chrome browser context per deck (a reused page converges on wrong values, measured). Known residual: a hypothetical future deck relying only on system fonts (no @font-face at all) would trip the font fail-closed predicate's "no font face reached loaded status" axis even though nothing is actually broken - update the predicate if that ever happens.
  • A shell check written as cmd 2>/dev/null | head -N || echo 'no records' can never report its negative case: || binds to head, which exits 0 on empty input, so the fallback is unreachable. Same vacuous-pass family as the command -v guard and the em-dash check. Test the branch you expect to fire by making it fire on purpose.
  • When a methodology sentence is found to be false, prefer DELETION over a narrowed rewrite, and check first whether anything is load-bearing on it. A narrowed rewrite reads as the careful option but re-asserts the same shape of claim against the same unverified surface: DS-150's replacement for "Subagents do not have hooks." was itself false. Both original sentences were load-bearing for nothing and deletion was the correct fix. Corollary: a claim removed from content/ is not gone until its docs/slides/*.md copy is grepped by hand - check-slides-sync compares each deck against a fresh render and passes when the .md and .html are stale in agreement.
  • Read docs/overview/vision.md before designing any change to this repo's own methodology surface (content/**, hooks/**, bin/**, scripts/**, adapter dirs) and name the pillars that cut against the proposal, not only the ones that support it. Nothing enforces this mechanically: no hook, no CI gate, and check-vision-alignment inspects PR-body prose only and never opens the file. Several agent contracts and commands require the same read within their own scope - that is not a reason to skip it here.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.