Signposts' own signposts — a live listing
Signposts runs on Signposts. This is the live listing of this repo’s own bundles, signs and rules — generated at build time from its signposts.yml, so it can never drift from what actually ships.
Each entry’s one-line summary is its description: field. A sign steers (it never blocks); a rule blocks at the moment shown. The bundles below are the four the project ships: core (what a fresh install carries), local (dogfood guards for working on Signposts), and the installable git-hygiene and justfile bundles.
Signposts defaults
The orientation and guards you want on any repo that uses Signposts. This is what a fresh install carries.
| type | id | moment | what it does |
|---|---|---|---|
| sign | orientation | session | What Signposts is and how it steers — shown at the start of every session. |
| sign | rules-self-edit | touch | A nudge when you edit the guardrails themselves; it never blocks. |
| sign | authoring-rules | touch | How to write a rule, shown when you're working in rules/. |
| sign | commit-gate-hermetic | touch | Why anything that shells out at commit must scrub git's env vars first. |
| sign | event-log-contract | touch | The event log is one field-shape contract spread across three files — change one, update the others. |
| rule | rules-have-tests · core/sibling-exists | write · commit | Every rule file ships a colocated <name>.test.yml the engine runs. |
| rule | rules-tested-this-turn · core/ran-since-edit | turn-end | Holds the turn open if you changed a rule this turn but didn't run its tests. |
| sign | ast-grep-grammars | touch | What ast-grep is (a structural code matcher) and how to add a language grammar. |
| sign | depcruise-fences | touch | What dependency-cruiser is (an import-graph checker) and how the fence dialect works. |
| rule | no-delete-guardrails · core/protected-path | delete | Stops a command from deleting the config or a rule file. |
| rule | signposts-well-formed · core/signposts-lint | write · commit | Checks signposts.yml parses and every signpost has an id, a use (rules), and a description. |
| rule | no-commit-engine-log · core/protected-path | commit | Stops the Signposts event log (.signposts/) being checked in. |
Tooling — the justfile is home
The justfile is the single command source; commands you run more than once become documented recipes.
| type | id | moment | what it does |
|---|---|---|---|
| sign | tooling-first | session | Where the repo's commands live, and when to add a recipe. |
| rule | no-package-scripts · core/json-invariant | write · commit | Keeps package.json scripts empty — the justfile is the one command source. |
| rule | justfile-docs · tooling/justfile-docs | write · commit | Every listed justfile recipe carries an explicit doc string for the just --list help screen. |
Git hygiene
No AI attribution in commits, PRs or issues, and nothing silently discards uncommitted work.
| type | id | moment | what it does |
|---|---|---|---|
| sign | commit-hygiene | session | The rules for how commits, PRs and issues are written here. |
| rule | no-ai-attribution-in-commits · core/command-guard | command | Blocks Claude/Anthropic attribution in a commit, PR or issue before it is made. |
| rule | no-git-discard · git-hygiene/no-git-discard | command | Blocks a git checkout/restore that would wipe uncommitted work — git stash is the reversible path. |
| rule | commit-grammar · git-hygiene/commit-grammar | command | Checks a git commit message speaks Conventional Commits before the commit runs. |
Functional core, imperative shell
Keep decision logic pure and testable, push effects to the edges — and fence the import graph so it stays that way.
| type | id | moment | what it does |
|---|---|---|---|
| sign | fcis | touch | The functional-core / imperative-shell model, shown when you touch the decision core. |
| rule | import-fence · core/depcruise | commit | A dependency-cruiser fence — the pure layer imports no node builtins or shell, and the core never imports the CLI. |
| rule | pure-has-test · core/sibling-exists | write · commit | Every pure decision module ships a colocated .test.mjs — the functional core is TDD'd. |
| rule | pure-covered · core/tool-gate | commit | Blocks a commit if the functional core's line coverage drops below 95% (only runs when pure/ changed). |
Testing discipline
Test behaviour, not implementation; spend effort where confidence-per-cost is highest.
| type | id | moment | what it does |
|---|---|---|---|
| sign | philosophy | touch | What to test and how much, shown when you touch a test. |
Node app hygiene
A new dependency is an audit surface; the lockfile moves with it, and the version stays SemVer.
| type | id | moment | what it does |
|---|---|---|---|
| sign | dependencies | touch | What to weigh before adding a dependency, shown when you touch the manifest. |
| rule | lockfile-in-step · core/change-together | commit | package.json and the lockfile must change in the same commit. |
| rule | version-is-semver · core/json-invariant | write · commit | package.json version is valid SemVer 2.0.0. |
TypeScript discipline
In the site's TypeScript, never silence the checker; the strict preset stays on.
| type | id | moment | what it does |
|---|---|---|---|
| sign | types-as-design | touch | Use types as a design tool, shown when you touch the site's TypeScript. |
| rule | tsconfig-stays-strict · core/json-invariant | write · commit | The site's tsconfig keeps extending Astro's strict preset. |
| rule | site-typechecks · core/tool-gate | commit | Type-checks the website at commit (astro check) — only runs when a site/ file changed. |
Web quality
The lintable slices of accessibility and performance for the docs site.
| type | id | moment | what it does |
|---|---|---|---|
| sign | accessibility | touch | The a11y checks a linter can't make, shown when you touch the site's UI. |
| sign | performance | touch | The edit-time performance rules of thumb for the site. |
| sign | asset-budget | touch | The byte budgets to keep in mind when adding site assets. |
Docs — agent vs user
docs/agent/ is written for agents (whatever format they consume best); docs/user/ is written for humans — HTML only, multimodal, minimum cognitive load.
| type | id | moment | what it does |
|---|---|---|---|
| sign | docs-shape | touch | The two-audience docs convention, shown when working in docs/. |
| rule | user-docs-are-html · core/protected-path | write · commit | docs/user/ is the human-facing surface — HTML and assets, never markdown. |
Working-docs journal
.work/ is the gitignored working-docs journal (specs · plans · handovers · research) — never committed into the code repo.
| type | id | moment | what it does |
|---|---|---|---|
| sign | work-journal | touch | .work/ is the gitignored working-docs journal — don't commit it. |
Developing Signposts
Orientation and guards for working ON the Signposts codebase itself.
| type | id | moment | what it does |
|---|---|---|---|
| sign | dev-orientation | session | How the Signposts codebase is laid out and how we work in it. |
| rule | commit-runs-tests · core/tool-gate | commit | Runs the deterministic test suite (rules + hooks, ~6s; not e2e/live) at commit and blocks if anything fails. |
| sign | site | touch | How to build and style the website. |
| sign | engine-failsafe | touch | Why the hooks and event log must never throw or block an edit. |
| sign | yaml-writes-keep-comments | touch | Why writes to signposts.yml must go through editYaml, to preserve the user's comments. |
Dogfood. The local bundle’s signposts-well-formed rule (core/signposts-lint) is what keeps this file honest — it blocks a commit if any sign or rule is missing its description, so this table is never half-empty. See the config file for the schema.