Project constitution + delivery loop

PAGS.

Portable Agent Guide System: a small set of records and rules for repositories where AI agents do much of the work.

Agents forget between sessions. They add scope nobody asked for, change the architecture quietly, and make up reasons for old code. PAGS gives every project one written answer to each question an agent should ask before changing anything, plus a loop that keeps those answers current.

DesignThis page shows the system PAGS is being built into. Parts of it, such as the install manifest, are planned work tracked in issue #1.
your-repo/
  • AGENTS.mdHow should I work here?
  • README.mdWhat do users rely on?
  • .pags/CHARTER.mdWhat must not change casually?
  • .pags/WORK.mdWhat is approved, and what is being done now?
  • .pags/DECISIONS.mdWhy was this chosen? Which rules are bent?
  • .pags/ARCHITECTURE.mdWhat exists today?
  • .pags/DESIGN.mdWhat should the interface feel like?
  • .pags/*-ARCHIVE.mdWhat was finished or replaced?
§1

Agents drift in three predictable ways

Each session starts with no memory of the last one. Without written records, small, reasonable-looking changes add up to a project nobody planned.

Scope creep

An agent adds a feature because it seemed useful. Nobody approved it, and now it has to be maintained.

PAGS: new capabilities need an approved roadmap item first.

Silent architecture change

A refactor swaps a pattern or adds a dependency. The next session cannot tell whether it was intended.

PAGS: hard-to-reverse choices get a decision record.

Invented history

In old code, agents guess why something was done and state the guess as fact.

PAGS: facts are marked observed, intended, or unknown.

§2

Four records, one question each

Records that change at the same pace live together. Intent (the charter) and reality (the architecture) stay apart, because keeping them apart is what makes PAGS honest about existing code. IDs like R-003 T-014 D-012 A-001 let entries point at each other.

AGENTS.md

How should I work here?

The loop, the change table, who may approve what, the project commands, and the definition of done. The only place commands are written.

.pags/CHARTER.md

What must not change casually?

Mission, goals, non-goals, principles, constraints, and the maintainer's name. One page. Only the maintainer edits it.

.pags/WORK.mdR- T-

What is approved, and what is being done now?

The Now block, then outcomes with their tasks indented underneath, then unplanned fixes and ideas for later.

.pags/DECISIONS.mdD-

Why was this chosen? Which rules are bent?

Decisions, dependency reasons, and exceptions. An exception is a decision with an end date and an exit condition.

.pags/ARCHITECTURE.mdA-

What exists today?

Structure, flows, interfaces, invariants, and known debt. Unconfirmed facts are marked observed or unknown.

README.md

What do users rely on?

The user-facing contract. Any change to visible behavior updates it in the same change.

.pags/DESIGN.mdoptional

What should it feel like?

Terms, states, visual language, and accessibility rules, for projects with an interface.

.pags/*-ARCHIVE.mdautomatic

What was finished or replaced?

Done tasks, finished outcomes, and replaced decisions move here, so the live files stay short.

§4

The loop every agent follows

Each session goes through the same steps, from reading the handoff to writing the next one. The step that matters most is the scope check: work outside approved scope becomes a proposal and is not implemented.

flowchart TD
  S([Session starts]) --> N[Read the Now block in WORK.md]
  N --> K[Classify the change]
  K --> L[Look up its row in the change table]
  L --> Q{Inside approved scope?}
  Q -- No --> P[Write a proposal]
  P --> H{Maintainer approves?}
  H -- Not yet --> W([Record it in the Now block and stop])
  H -- Yes --> REC[Record who approved and when]
  REC --> T
  Q -- Yes --> T[Create or update the task]
  T --> DQ{Hard to reverse?}
  DQ -- Yes --> D[Record a decision]
  DQ -- No --> I
  D --> I[Make the smallest coherent change]
  I --> V[Run tests and pags check]
  V --> VQ{All green?}
  VQ -- No --> I
  VQ -- Yes --> U[Update records and archive finished entries]
  U --> NB[Rewrite the Now block]
  NB --> END([Session ends])
Hard to reverse means a new dependency, a public interface, an architectural pattern, a data format, or a lasting user-experience choice.
§5

What each kind of change needs

One table in AGENTS.md replaces separate rules for classifying, reading, and recording. An agent finds its row, reads only what that row lists, and updates only what it names.

ChangeRead firstThen update
New capabilityCharter, WorkOutcome approval, then a task
Scope or non-goal changeCharter, WorkProposal approval, then Charter, Work, and a decision
Architecture or public interfaceArchitecture, DecisionsDecision, Architecture
New or removed dependencyDecisionsDecision starting “Add dependency:”, lockfile
RefactorArchitecture, relevant decisionsTask; Architecture if the structure changes
Security changeDecisions, ArchitectureTask; a decision if a policy changes
Bug fixArchitecture for the affected areaTask under Unplanned, regression test
User-visible behaviorREADMEREADME, in the same change
Temporary rule deviationThe rule being bentException in Decisions, with end date and exit approval
Maintenance, formatting, doc fixesNothing extraNothing new, as long as scope is unchanged

If a row names a record the project does not have yet, the agent creates it from the template. A minimal install never leaves an agent pointing at a file that does not exist.

§6

Agents propose. A named person approves.

This is the rule the rest of PAGS depends on. Approval should also be quick: when the maintainer says yes in the middle of a session, the agent records the approval and carries on.

Agents may
  • Draft roadmap outcomes and decisions as proposed
  • Create and progress tasks inside approved scope
  • Record evidence, observations, and unknowns
  • Write the Now block for the next session
Only the maintainer may
  • Approve roadmap outcomes
  • Accept decisions
  • Grant exceptions
  • Change the charter
sequenceDiagram
  participant A as Agent
  participant R as Records
  participant M as Maintainer
  A->>R: Draft R-004 as proposed
  A->>M: Share the proposal and ask for approval
  M-->>A: Yes, approve R-004
  A->>R: Mark R-004 approved, add approved-by: sam 2026-09-27
  A->>R: Create T-022 for R-004
  Note over A,M: The agent never marks its own proposal approved
Fast path. A spoken or typed approval during a session counts. The agent records it and does not need a separate ceremony.
§7

How each record moves

Each record type has a short, fixed list of statuses written in brackets. pags check rejects any status that is not on the list. Finished entries move to an archive file.

R- Outcome
stateDiagram-v2
  [*] --> proposed
  proposed --> approved: maintainer approves
  proposed --> dropped
  approved --> doing
  doing --> done: its tasks are done
  approved --> dropped
  done --> [*]: moved to archive
T- Task
stateDiagram-v2
  [*] --> todo
  todo --> doing
  doing --> blocked
  blocked --> doing
  doing --> done: evidence recorded
  todo --> dropped
  done --> [*]: moved to archive
D- Decision
stateDiagram-v2
  [*] --> proposed
  proposed --> accepted: maintainer accepts
  proposed --> rejected
  accepted --> replaced: a newer decision replaces it
  rejected --> [*]
  replaced --> [*]: moved to archive
D- Exception
stateDiagram-v2
  state "exception until date" as exception
  [*] --> exception: maintainer grants it
  exception --> resolved: exit condition met
  exception --> exception: maintainer extends the date
  resolved --> [*]: moved to archive
§8

New projects and existing ones

A new project starts with a one-page charter and grows its records as it grows. An existing project starts by describing what is there, without pretending anyone planned it.

Greenfield

A new repository with little or no code.

  1. Write a one-page charter before choosing a stack.
  2. Define three to seven roadmap outcomes.
  3. Add the first few tasks.
  4. Set build, test, lint, and format commands early.
  5. Record only decisions that are expensive to reverse.
  6. Start the architecture record once real structure exists.

Brownfield

An existing codebase with history and habits.

  1. Inventory the stack, commands, tests, and deployment.
  2. Describe observed behavior in the architecture record.
  3. Establish a test and CI baseline.
  4. Backfill decisions only for important choices; mark unknown reasons as unknown.
  5. Sort every existing problem into its record (below).
  6. Apply the rules to new work first, then improve old areas gradually.
Observed

Seen in the code or its behavior today. Goes in ARCHITECTURE, marked (observed).

Intended

Someone with authority decided it. Goes in CHARTER, WORK, or DECISIONS.

Unknown

Nobody knows why. Written as why: unknown and never guessed.

flowchart LR
  X["Existing code that breaks the new rules"] --> Q{"What is it?"}
  Q -->|We accept it| L["Accepted legacy"] --> A1["ARCHITECTURE · A- accepted"]
  Q -->|We plan to change it| M["Planned migration"] --> A2["WORK · R- outcome"]
  Q -->|Allowed for now| E["Temporary exception"] --> A3["DECISIONS · exception until date"]
  Q -->|It is simply wrong| B["Defect"] --> A4["WORK · T- under Unplanned"]
Sorting what is already there. Every existing problem ends up in exactly one record, so nothing sits in an unexplained grey zone.
§9

The installer

One Python script with no dependencies sets PAGS up in any repository. It never overwrites your work silently: the default at every prompt is the safe choice, and it previews every change before writing.

flowchart TD
  A(["Run scripts/install-pags.py"]) --> B["Detect from commit count and non-doc files"]
  B --> C{"New or existing project?"}
  C -->|New| G["Greenfield starter set"]
  C -->|Existing| BF["Brownfield set, including ARCHITECTURE"]
  G --> P["Preview every file it will touch"]
  BF --> P
  P --> F{"AGENTS.md or README.md already there?"}
  F -->|Yes| MS["Insert a marked PAGS section, keep the rest"]
  F -->|No| NW["Create from template"]
  MS --> AP["Apply after you confirm"]
  NW --> AP
  AP --> CK["Install .pags/check.py"]
  CK --> MF["Write .pags/manifest with version and template hashes"]
  MF --> CL["Add CLAUDE.md that imports AGENTS.md"]
  CL --> NX(["Print next steps for this project type"])
Safe by default. Existing files are kept. Replacements are backed up first. Rerunning changes nothing unless a template changed, and the manifest shows exactly which files are out of date.
§10

Rules that are checked, not only written

Agents follow written advice less reliably as their context fills up. pags check is a small script, installed as .pags/check.py, that runs before each commit and in CI. It fails the build when the records stop agreeing with each other.

flowchart LR
  E["Edit code and records"] --> C["git commit"]
  C --> H["pre-commit runs pags check"]
  H --> CI["CI runs pags check and tests"]
  CI --> M(["Merge"])
  H -. fails .-> E
  CI -. fails .-> E
  • Every ID is unique, sits in its own file, and every ID mentioned exists
  • Status values come from each record's allowed list
  • Tasks sit under an approved outcome or under Unplanned
  • Done tasks have evidence
  • Replaced decisions have a newer decision pointing at them
  • No placeholders are left once the charter is accepted
  • No exception is past its end date
$ python3 .pags/check.pyExample
.pags/DECISIONS.md:9: error: D-015 exception ended 2026-09-01; resolve it or ask the maintainer
.pags/WORK.md:14: error: T-022 links to R-009, which does not exist
.pags/WORK.md:31: warning: T-018 is [done]; move it to WORK-ARCHIVE.md
FAIL 41 entries, 2 error(s), 1 warning(s)
§11

Every session leaves a note for the next one

The Now block sits at the top of WORK.md. It is rewritten at the end of each session, not appended to, so it stays short enough for the next agent to read first.

.pags/WORK.mdExample
## Now

- Focus: R-003 offline sync. T-014 is in progress.
- Last session: Added the retry queue. Tests pass. D-012 accepted.
- Next: Handle conflicts on reconnect (T-015).
- Waiting on: Maintainer approval for the R-004 proposal.

<!-- Rewrite this block at the end of every session. -->
§12

Where PAGS fits

Spec-driven tools help write a spec for each feature. PAGS governs the whole project over time, so the two work well together.

Per-feature spec tools

  • Examples: GitHub Spec Kit, Kiro
  • One spec, plan, and task list per feature
  • Focused on getting a single feature built well
  • Guidance files describe the product and the stack

PAGS

  • One set of records for the whole life of a project
  • Honest about existing code: observed, intended, or unknown
  • Decisions are replaced, never rewritten
  • Exceptions expire unless someone renews them
  • Scope gates that agents cannot open themselves
§13

Still being decided

These parts of the design have options on the table but no decision yet. Each links to its issue.

  • #17

    Where the records live

    A hidden .pags/ folder is skipped by ripgrep and many agent search tools. A visible docs/pags/ folder avoids that.

  • #13

    IDs that cannot collide

    Two branches that each add a decision will both pick the next number. The archive keeps files short, but the ID scheme still needs a fix, or pags check needs to catch duplicates at merge.

  • #11

    Where the approver is named

    The rule in §6 is settled in principle. The open question is whether the name goes in the charter, AGENTS.md, or a CODEOWNERS-style line.