Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions .devia/01_ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ Content is data. Code reads it; code never encodes what a rule says.
| No runtime dependencies | The tool that preaches `ARC-004` cannot carry a tree of its own | `.cursor/rules/devia.mdc`, `CONTRIBUTING.md` |
| Own YAML subset parser | Frontmatter and impact maps only; devia writes the files it reads | `src/lib/yaml.mjs` header |
| Rule IDs are stable and never reused | Citations in old reports must keep resolving | `GOVERNANCE.md`, `rules/LIFECYCLE.md` |
| The standard is vendored into `.devia/standard/` | Agents read it offline, with no package manager and no network | `src/lib/vendor.mjs` |
| Pinning the standard into `.devia/standard/` is opt-in | 391 copied files against 17 of memory buries what the folder is for, and every sync becomes a 391-file diff. `devia rules` reads the standard; `devia sync` pins it for offline agents and audits | `src/commands/init.mjs`, `.devia/11_GAPS.md` G8 |
| The CLI version and the standard version move separately | A CLI fix must not force an adopter to re-pin the corpus | `src/lib/version.mjs` |
| `check` scans what git carries, not what the disk holds | A P0 failure on an ignored build artefact is a false positive that teaches people to ignore the gate | `src/lib/git.mjs` |
| Design rule IDs carried over unchanged | Consolidation must not invalidate existing citations | `MIGRATION.md` |
Expand All @@ -63,5 +63,6 @@ Content is data. Code reads it; code never encodes what a rule says.

## Current vs target

This repository vendors nothing into its own `.devia/standard/`: it *is* the standard, so its
memory points at the repository files directly. Every other adopter gets the vendored copy.
This repository pins nothing into its own `.devia/standard/`: it *is* the standard, so its
memory points at the repository files directly. Adopters are in the same position by default,
and pin a copy only when they ask for one.
4 changes: 2 additions & 2 deletions .devia/02_SURFACES.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@

| Command | Purpose | Implementation | Exit code |
|---|---|---|---|
| `devia init` | Create `.devia/`, vendor the standard, install adapters | `src/commands/init.mjs` | 0, or 2 on a bad profile or a detected root away from the cwd |
| `devia init` | Create `.devia/` and install adapters; `--vendor` also pins the standard | `src/commands/init.mjs` | 0, or 2 on a bad profile or a detected root away from the cwd |
| `devia validate` | Memory integrity | `src/commands/validate.mjs` | 1 on any FAIL |
| `devia check` | Readiness gates | `src/commands/check.mjs` | 1 on any P0 FAIL |
| `devia doctor` | Adoption, drift, staleness | `src/commands/doctor.mjs` | 1 when there is no `.devia/` |
| `devia rules` | Query the registry | `src/commands/rules.mjs` | 1 when `--id` is unknown |
| `devia sync` | Refresh the vendored standard | `src/commands/sync.mjs` | 1 without `.devia/` |
| `devia sync` | Pin the standard, or refresh a pinned copy | `src/commands/sync.mjs` | 1 without `.devia/` |
| `devia skills` | Install adapters and the skill pack, per repository or `--global` | `src/commands/skills.mjs` | 2 on a bad action |
| `devia gap` / `devia debt` | Registry lines | `src/commands/registry.mjs` | 1 when the id is unknown |

Expand Down
2 changes: 1 addition & 1 deletion .devia/04_PERMISSIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ content stays. `--force` overrides both, and says which paths it took.

| Operation | Where | Guard |
|---|---|---|
| `rm -rf .devia/standard` before re-vendoring | `init`, `sync` | Only that one directory, which the tool owns |
| `rm -rf .devia/standard` before re-pinning | `init --vendor`, `sync` | Only that one directory, which the tool owns |
| Overwriting memory files | `init --force` | Off by default, warned about in the output |
| Removing a registry line | `gap`/`debt close` | Moves the line to the closed table, never deletes it |

Expand Down
4 changes: 2 additions & 2 deletions .devia/05_FLOWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@

| Journey | Steps | Covered by |
|---|---|---|
| Adopt | `npm i -D @schneiderjoseph/devia` → `devia init` → memory, adapters and vendored standard exist | `tests/cli.test.mjs` "init creates the memory…" |
| Adopt | `npm i -D @schneiderjoseph/devia` → `devia init` → memory and adapters exist, nothing pinned | `tests/cli.test.mjs` "init creates the memory…" |
| Re-run safely | `devia init` on a repository that already has a filled memory keeps every decision | "init does not overwrite a filled memory" |
| Verify | `devia validate` → structure, config, impact map, registry ids, placeholders | "validate reports placeholders…", "validate detects a reused registry id" |
| Gate | `devia check` → P0 failures block, exit code 1 | "check blocks on P0 and explains why", "check finds a committed secret" |
| Record | `devia gap add` / `devia debt add` / `debt close` → monotone ids, nothing deleted | "gap and debt lines get monotone ids…" |
| Upgrade | `devia sync` → vendored standard refreshed, pin updated, memory untouched | "sync refreshes the vendored standard" |
| Upgrade | `devia sync` → standard pinned or refreshed, pin updated, memory untouched | "sync pins the standard on demand" |
| Cite | `devia rules --id SEC-001` → the full rule text | "rules can be queried by id and by filter" |

## Failure behaviour
Expand Down
1 change: 1 addition & 0 deletions .devia/11_GAPS.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ Add one with `npx devia gap add "question"`.
|---|---|---|
| G6 | Should devia install its contract at user level for every agent, or stay per-repository outside Claude Code? | devia is for every agent — user-level install built for Claude Code, Codex, Cursor and Gemini in 0.3.0 |
| G1 | Should `devia check` grow ecosystem-specific gates (Python, Go, Rust) or stay deliberately generic? | Reframed: the failure was not the ecosystem but the assumption that the manifest sits at the repository root — fixed in 0.4.0. Ecosystem-specific gates remain out of scope |
| G8 | Should devia pin a copy of the standard into every adopter repository by default? | No — opt-in via devia sync. Measured on a real repository: 391 pinned files against 17 of memory, tripling a 211-file project and turning every sync into a 391-file diff |
7 changes: 4 additions & 3 deletions .devia/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ Machine files: [`devia.json`](devia.json) (profile, maturity, pinned version) an

This repository **is** the standard, so its memory points at the repository files directly —
[`../standard/`](../standard/), [`../rules/`](../rules/README.md) — and vendors nothing into
`.devia/standard/`. Every other adopter gets the vendored, version-pinned copy instead: the same
text for every agent, offline, no network and no package manager required.
`.devia/standard/`. Adopters are in the same position by default: they read the standard with
`devia rules`, and pin a version-locked copy with `devia sync` when an agent must read it
offline or an audit needs the exact wording.

## The two registries

Expand All @@ -45,7 +46,7 @@ text for every agent, offline, no network and no package manager required.
npx devia validate # structure, registries, placeholders
npx devia doctor # is the memory older than the code?
npx devia check # readiness gates
npx devia sync # refresh the vendored standard after an upgrade
npx devia sync # pin the standard under .devia/standard/, or refresh it
```

`.devia/` is committed. It is part of the repository, not a local scratch pad.
31 changes: 31 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,36 @@
# Changelog

## 0.5.0 — 2026-09-09

The standard is unchanged: `VERSION` stays at 0.1.0.

### Pinning the standard is now opt-in

`devia init` used to copy the whole standard into `.devia/standard/`. Measured on a real
repository: **391 pinned files against 17 of memory** — a folder whose purpose is to be read by
a human and an agent, in which 96% of the files were a copy nobody wrote. On a 211-file project
it tripled the repository, and every `devia sync` produced a 391-file diff in which a real
memory change was invisible.

- `devia init` writes the memory and the adapters, and pins nothing: **17 files, 57 kB**
- `devia init --vendor` pins the copy for those who want it up front
- `devia sync` pins it on demand and refreshes it afterwards — that is now its first job, not
only its maintenance one
- `doctor` reports an unpinned standard as `INFO`, not a `WARN` to clear: the default is not a
defect
- The memory templates, the agent adapters and the skill read the rules with
`npx devia rules --id <ID>` / `--domain <name>` instead of linking into a copy that may not
exist. A pinned copy is mentioned as what it is: optional

Nothing to do when upgrading. An existing `.devia/standard/` is left alone, `devia sync` keeps
refreshing it, and only new `devia init` runs behave differently. Recorded as G8.

### A P0 blocker comes from the priority cell, never from prose

`MEM-DEBT-P0` matched `P0` anywhere in a debt row. A P1 line reading "becomes P0 once the
payment module ships" failed the gate, so a project with no P0 debt was told it was blocked by
one. The check now reads the priority cell. Found by writing a real project's debt registry.

## 0.4.0 — 2026-09-09

The standard is unchanged: `VERSION` stays at 0.1.0, no adopter needs `devia sync`.
Expand Down
5 changes: 3 additions & 2 deletions MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,6 @@ Then:
(undecided) and `.devia/12_DEBT.md` (decided, not built) — the split matters.
4. Replace `node scripts/production-check.mjs` in CI with `npx devia check`.

Nothing in the old repos is lost: the full text of both is vendored here, and `devia init`
vendors it again into the project under `.devia/standard/`.
Nothing in the old repos is lost: the full text of both ships with this package, readable with
`npx devia rules`, and `npx devia sync` pins a copy under `.devia/standard/` when a project
wants one on disk.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ npx devia doctor # adoption + staleness diagnosis
├── 14_INDEX.md # where to find what
├── impact-map.yaml # change type → files that must be updated
├── devia.json # profile, modules, maturity target, pinned version
└── standard/ # vendored, version-pinned copy of the standard
└── standard/ # optional: `devia sync` pins a copy of the standard here
```

Plus adapters so every agent gets the same contract: `AGENTS.md` (universal), `CLAUDE.md`,
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@schneiderjoseph/devia",
"version": "0.4.0",
"version": "0.5.0",
"description": "One standard, one memory: engineering and design rules plus living project memory for AI coding agents",
"type": "module",
"license": "MIT",
Expand Down
5 changes: 3 additions & 2 deletions skills/devia/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ the difference between a task and a guess (`AGT-002`).

## Step 2 — work under the rules

The rules are pinned in `.devia/standard/rules/` with stable IDs. The ones that stop most bad
changes:
The rules have stable IDs and are read with `npx devia rules --id <ID>`, or `--domain <name>`
for a whole area. A project that ran `devia sync` also has them on disk under
`.devia/standard/rules/`. The ones that stop most bad changes:

| If you are about to… | Rule |
|---|---|
Expand Down
13 changes: 10 additions & 3 deletions src/commands/check.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,16 @@ function makeChecks(root, ctx) {
run: () => {
const text = read(path.join(root, ".devia", "12_DEBT.md"));
if (text === null) return { kind: "SKIP", detail: "no debt registry" };
const rows = (text.match(/^\|\s*D\d+\s*\|.*$/gm) || []).filter(
(r) => /\bP0\b/.test(r) && !/TODO\(devia\)/.test(r)
);
// The priority is a cell, not a word somewhere in the row. Matching the whole line made
// a P1 line reading "becomes P0 once the payment module ships" fail the gate — a P0
// blocker invented out of prose, on a project that had none.
const rows = (text.match(/^\|\s*D\d+\s*\|.*$/gm) || []).filter((row) => {
if (/TODO\(devia\)/.test(row)) return false;
return row
.split("|")
.slice(1, -1)
.some((cell) => cell.trim().toUpperCase() === "P0");
});
return rows.length
? { kind: "FAIL", detail: `${rows.length} P0 debt line(s) open` }
: { kind: "PASS" };
Expand Down
9 changes: 4 additions & 5 deletions src/commands/doctor.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,11 @@ ${color.bold("devia doctor")} — adoption, drift and staleness
const vendored = walk(path.join(deviaDir, "standard")).length;
if (path.resolve(root) === path.resolve(packageRoot)) {
status("SKIP", "vendored standard", "this repository is the standard");
} else if (vendored) {
status("PASS", `standard pinned: ${vendored} files`);
} else {
status(
vendored ? "PASS" : "WARN",
`vendored standard: ${vendored} files`,
vendored ? "" : "run `devia sync`"
);
// Not pinning is the default, so absence is a fact to report, never a warning to clear.
status("INFO", "standard not pinned", "`devia rules` reads it; `devia sync` pins a copy");
}

// Adapters
Expand Down
15 changes: 9 additions & 6 deletions src/commands/init.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ ${color.bold("devia init")} — create .devia/ in this repository
--profile <name> ${Object.keys(PROFILES).join(" | ")}
--force overwrite existing memory files (dangerous: they hold your decisions)
--no-agents do not write the agent adapters
--no-vendor do not vendor the standard into .devia/standard/
--vendor pin a copy of the standard into .devia/standard/ (~390 files)
--yes accept a detected root that is not the current directory
`.trim());
return 0;
Expand Down Expand Up @@ -163,17 +163,20 @@ ${color.bold("devia init")} — create .devia/ in this repository
status("SKIP", "devia.json kept", "use --force to regenerate");
}

// 3. Vendored standard
if (flags.vendor === false || flags["no-vendor"]) {
status("SKIP", "standard not vendored", "--no-vendor");
} else {
// 3. Pinned standard — opt-in. Vendoring writes ~390 files a project did not author, which
// buries the memory it is supposed to serve: on a real repository the ratio was 17 files of
// memory to 391 of copy, and every `sync` produced a 391-file diff. The rules stay reachable
// through `devia rules`, and `devia sync` pins the copy for whoever needs it offline.
if (flags.vendor && flags.vendor !== "false") {
const files = vendorStandard(path.join(deviaDir, "standard"), {
by: "devia init",
cli,
standard: version,
date: vars.DATE,
});
status("PASS", `standard vendored: ${files} files`, `v${version}`);
status("PASS", `standard pinned: ${files} files`, `v${version}`);
} else {
status("SKIP", "standard not pinned", "`devia sync` writes .devia/standard/ when you need it");
}

// 4. Agent adapters
Expand Down
4 changes: 2 additions & 2 deletions templates/agents/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,5 @@ npx devia check # readiness gates
Update `.devia/` in the same change (see `.devia/impact-map.yaml`), then report what you changed
**and what you did not verify**.

Full standard: [`.devia/standard/AGENTS.md`](.devia/standard/AGENTS.md) ·
rules by ID: [`.devia/standard/rules/README.md`](.devia/standard/rules/README.md)
Rules by ID: `npx devia rules --id SEC-001`, or by domain: `npx devia rules --domain database`.
A pinned copy lives under `.devia/standard/` only if this project ran `devia sync`.
3 changes: 2 additions & 1 deletion templates/agents/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,5 @@ npx devia check

Report the checks that ran, the rule IDs involved, and what you did **not** verify.

Full contract: `.devia/standard/AGENTS.md`. Rules by ID: `.devia/standard/rules/README.md`.
Rules by ID: `npx devia rules --id SEC-001`, or by domain: `npx devia rules --domain database`.
A pinned copy lives under `.devia/standard/` only if this project ran `devia sync`.
20 changes: 12 additions & 8 deletions templates/project/14_INDEX.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,17 @@
|---|---|---|
| TODO(devia) | | |

## Standard (vendored)
## Standard

| Need | Where |
The standard is read through the CLI, not copied into this repository.

| Need | Command |
|---|---|
| Work contract | [`standard/AGENTS.md`](standard/AGENTS.md) |
| Rule by ID | [`standard/rules/README.md`](standard/rules/README.md) |
| Engineering policy | [`standard/standard/engineering/README.md`](standard/standard/engineering/README.md) |
| Design policy | [`standard/standard/design/README.md`](standard/standard/design/README.md) |
| Checklists | [`standard/checklists/README.md`](standard/checklists/README.md) |
| Memory doctrine | [`standard/MEMORY.md`](standard/MEMORY.md) |
| A rule by ID | `npx devia rules --id SEC-001` |
| Every rule in a domain | `npx devia rules --domain database --priority P0` |
| Work contract | `AGENTS.md` at this repository's root |
| Readiness gates | `npx devia check` |

`npx devia sync` pins a version-locked copy under `standard/` when an agent must read it
offline, or when an audit needs the exact wording you built against. Add the paths here if you
do.
6 changes: 3 additions & 3 deletions templates/project/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ This file is your contract. Violating it is a failed task.
1. Read [`10_NEVER_ALWAYS.md`](10_NEVER_ALWAYS.md) — what this project has already banned
2. Read [`00_OVERVIEW.md`](00_OVERVIEW.md) — what this project is
3. Read the memory file for the surface you are about to change ([`14_INDEX.md`](14_INDEX.md))
4. Read the standard section for the domain: [`standard/AGENTS.md`](standard/AGENTS.md),
[`standard/rules/README.md`](standard/rules/README.md)
4. Read the rules for what you are touching: `npx devia rules --domain <name>`, or
`npx devia rules --id <ID>` for one

Then work. Then update this memory in the same change.

Expand Down Expand Up @@ -48,4 +48,4 @@ TODO(devia): add this project's own commands — install, dev, test, lint, migra
- Not verified: ...
```

Full contract, routing table and hard stops: [`standard/AGENTS.md`](standard/AGENTS.md).
Full contract, routing table and hard stops: the `AGENTS.md` at this repository's root.
9 changes: 6 additions & 3 deletions templates/project/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,11 @@ Created by `devia init` (devia {{DEVIA_VERSION}}, {{DATE}}).
Machine files: [`devia.json`](devia.json) (profile, maturity, pinned version) and
[`impact-map.yaml`](impact-map.yaml) (change type → files to update).

The standard itself is vendored, version-pinned, under [`standard/`](standard/) — the same text
for every agent, offline, no network and no package manager required.
The standard itself is not copied in here. Read it with `npx devia rules --id SEC-001` or
`npx devia rules --domain database`, which is the same text for every agent. If you need it on
disk — an agent with no network, or an audit that must show the exact wording you built against
— `npx devia sync` pins a version-locked copy under `standard/`, and `14_INDEX.md` then points
at it.

## The two registries

Expand All @@ -43,7 +46,7 @@ for every agent, offline, no network and no package manager required.
npx devia validate # structure, registries, placeholders
npx devia doctor # is the memory older than the code?
npx devia check # readiness gates
npx devia sync # refresh the vendored standard after an upgrade
npx devia sync # pin the standard under standard/, or refresh a pinned copy
```

`.devia/` is committed. It is part of the repository, not a local scratch pad.
Loading
Loading