avouch 0.1.22 → 0.1.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -32,7 +32,7 @@ Read in this order:
32
32
 
33
33
  Start with step 0, then do the two steps, in this order.
34
34
 
35
- 0. At the top level of the git repository, run `npx -y avouch init`. It installs the Claude Code plugin (see "Claude Code plugin") and adds the Avouch instructions for coding agents. The instructions tell an agent to read the rules with `avouch query`, not with a text tool, and to run `avouch check` and `avouch gate docs` after a change. There are two modes: `--append` adds the instructions to `AGENTS.md` and `CLAUDE.md`, if they exist; `--print` writes them to the terminal, and you add them yourself. Without a flag, `init` asks in a terminal and prints otherwise. `--dry-run` shows what would change and writes nothing. Then run `/avouch:scan` in Claude Code, which drafts `avouch.config.json`, a first ontology and the document review ledger. See "init" in "Command line".
35
+ 0. At the top level of the git repository, run `npx -y avouch init`. It installs the plugin for Claude Code and for Codex (see "Claude Code and Codex plugin") and adds the Avouch instructions for coding agents. The instructions tell an agent to read the rules with `avouch query`, not with a text tool, and to run `avouch check` and `avouch gate docs` after a change. There are two modes: `--append` adds the instructions to `AGENTS.md` and `CLAUDE.md`, if they exist; `--print` writes them to the terminal, and you add them yourself. Without a flag, `init` asks in a terminal and prints otherwise. `--dry-run` shows what would change and writes nothing. Then run `/avouch:scan` in Claude Code (`$avouch:scan` in Codex), which drafts `avouch.config.json`, a first ontology and the document review ledger. See "init" in "Command line".
36
36
  1. Every project: keep a document review ledger, and run `avouch gate docs` in CI. See "Document review ledger (gate docs)". The gate works with any Markdown style. It guarantees that each changed section of a design document has a recorded review decision. It does not guarantee that the decision is complete: it does not check that a person read the section, that `claims` lists every claim, or that the claimed places say what the section says.
37
37
  2. For the structured checks, choose one path. The checks are: the field lists and catalogs of R2, and R3, R5, R6, R8, R9 and R10 (SPEC section 5). Each needs a fact from the project's documents (SPEC section 6). R7 needs execution evidence, which the built-in adapter does not read.
38
38
  - (a) Write the documents to the Markdown convention, `docs/markdown-convention.md`, and use the built-in adapter. `avouch facts` checks the documents without an ontology.
@@ -86,7 +86,7 @@ A project supplies an adapter and a profile. The adapter reads the project's sou
86
86
 
87
87
  ## Command line
88
88
 
89
- Build with `npm run build`, then run it. `avouch --help` (or `-h`) prints the usage lines of all commands; `avouch <command> --help` prints the usage of one command. Both exit with 0 and need no files, configuration or git. For example:
89
+ Build with `npm run build`, then run it. `avouch --help` (or `-h`) prints an overview: the commands, each with a short description, and the options `-h` and `-v`. `avouch <command> --help` prints the usage of one command. `avouch --version` (or `-v`) prints the version. All three exit with 0 and need no files, configuration or git. `avouch` with no arguments prints the overview on stderr and exits with 2; an unknown command prints an error and exits with 2. For example:
90
90
 
91
91
  ```sh
92
92
  avouch check [-f <ontology.yaml>] [--config <avouch.config.json>] [--adapter <module|config.json>]
@@ -107,7 +107,7 @@ An `--adapter` path that ends in `.json` is not loaded as a module: it is the co
107
107
  avouch init [--append | --print] [--plugin | --no-plugin] [--dry-run]
108
108
  ```
109
109
 
110
- `avouch init` prepares a project for Avouch. Run it inside a git repository; it works on the git top level. Step 1 is the Claude Code plugin: with `--plugin`, it runs `claude plugin marketplace add githonllc/avouch` and `claude plugin install avouch@avouch` (it does not check if the plugin is already installed, and runs both commands again on each run). Without a flag, it asks in a terminal and only prints the two commands otherwise. When `claude` is not on `PATH`, it prints the two commands. `--no-plugin` skips the step. Step 2 is the instructions for coding agents (`templates/agents-block.md`). `--append` adds them, between the lines `<!-- BEGIN avouch -->` and `<!-- END avouch -->`, to `AGENTS.md` and `CLAUDE.md` at the top level. It never creates a file: when neither file exists, it prints the instructions. It replaces an earlier block in place, keeps all other bytes and the line endings (CRLF or LF) of the file, and a second run changes nothing. A file that does not have exactly one BEGIN line and then one END line is an error, and the file is not changed. It skips `CLAUDE.md` when the file has the line `@AGENTS.md` and `AGENTS.md` exists. `--print` writes the instructions to stdout. Without a flag, it asks in a terminal and prints otherwise. `--dry-run` runs no command and writes no file; it prints the commands and, for each file, `append`, `replace` or `unchanged`. Step 3 tells you to run `/avouch:scan` in Claude Code. Exit code 0 means done (also a print and a dry run); 1 means a plugin command failed or a file could not be changed; 2 means invalid arguments or no git repository.
110
+ `avouch init` prepares a project for Avouch. Run it inside a git repository; it works on the git top level. Step 1 is the plugin, for Claude Code and then for Codex. With `--plugin`, it runs `claude plugin marketplace add githonllc/avouch` and `claude plugin install avouch@avouch`, then `codex plugin marketplace add githonllc/avouch` and `codex plugin add avouch@avouch` (it does not check if the plugin is already installed, and runs the commands again on each run). Without a flag, it asks in a terminal for each host and only prints the commands otherwise. When `claude` or `codex` is not on `PATH`, it prints the two commands of that host. Codex runs the hook only after you approve it. `--no-plugin` skips the step. Step 2 is the instructions for coding agents (`templates/agents-block.md`). `--append` adds them, between the lines `<!-- BEGIN avouch -->` and `<!-- END avouch -->`, to `AGENTS.md` and `CLAUDE.md` at the top level. It never creates a file: when neither file exists, it prints the instructions. It replaces an earlier block in place, keeps all other bytes and the line endings (CRLF or LF) of the file, and a second run changes nothing. A file that does not have exactly one BEGIN line and then one END line is an error, and the file is not changed. It skips `CLAUDE.md` when the file has the line `@AGENTS.md` and `AGENTS.md` exists. `--print` writes the instructions to stdout. Without a flag, it asks in a terminal and prints otherwise. `--dry-run` runs no command and writes no file; it prints the commands and, for each file, `append`, `replace` or `unchanged`. Step 3 tells you to run `/avouch:scan` in Claude Code. Exit code 0 means done (also a print and a dry run); 1 means a plugin command failed or a file could not be changed; 2 means invalid arguments or no git repository.
111
111
 
112
112
  ### facts
113
113
 
@@ -299,9 +299,9 @@ Exit code 2, with one line on stderr, means:
299
299
 
300
300
  The gate does not check that a person read a unit, that `claims` lists every claim of the unit, or that the claimed places say what the unit says. Review the ledger diff in the pull request, next to the document diff. Known limit: two changes to adjacent ledger lines (for example two units of one document that follow each other) can still give a merge conflict in git.
301
301
 
302
- ## Claude Code plugin
302
+ ## Claude Code and Codex plugin
303
303
 
304
- This repository is also a Claude Code plugin marketplace. Install the plugin:
304
+ This repository is also a plugin marketplace for Claude Code and for Codex. Install the plugin in Claude Code:
305
305
 
306
306
  ```sh
307
307
  claude plugin marketplace add githonllc/avouch
@@ -310,6 +310,15 @@ claude plugin install avouch@avouch
310
310
 
311
311
  Inside a Claude Code session, the same two steps are `/plugin marketplace add githonllc/avouch` and `/plugin install avouch@avouch`.
312
312
 
313
+ Install the plugin in Codex (the same marketplace file is used):
314
+
315
+ ```sh
316
+ codex plugin marketplace add githonllc/avouch
317
+ codex plugin add avouch@avouch
318
+ ```
319
+
320
+ In Codex, call the skills as `$avouch:scan` and `$avouch:cli`. Codex runs the hook only after you approve it.
321
+
313
322
  The plugin has two skills and one hook. The skills:
314
323
  - `cli` (`/avouch:cli`): checks an ontology and runs `avouch query`.
315
324
  - `scan` (`/avouch:scan [project-dir]`): drafts or updates a project's ontology from its design documents, and records the review decision of each document section in the ledger (`avouch gate docs` must pass). It uses the adapter that the project has configured and never writes an adapter. The result is a candidate. `avouch check` must exit 0, and each source gap is listed with a proposed fix to the document. When most objects have no documented field list, it also writes `avouch/doc-patch.md`: field lists, foreign keys and store names derived from the code, for a human to review and merge into the documents. It never drafts states, permissions or rules from code.
@@ -322,18 +331,21 @@ The skills run the CLI with `npx -y avouch@<version>`, pinned to the version of
322
331
 
323
332
  ## Publishing
324
333
 
325
- The npm package is `avouch`, and its command is `avouch`. Versions 0.1.0 to 0.1.21 were published as `@githonllc/avouch`, which is deprecated. A library user changes imports from `@githonllc/avouch` to `avouch`. Versions 1.0.1 to 1.0.7 of `avouch` are an unrelated earlier package from 2020 by another author. The name was transferred to Githon LLC in 2026. Those versions sort higher than 0.x, so `release.yml` publishes with `--tag latest`.
334
+ The npm package is `avouch`, and its command is `avouch`. Versions 0.1.0 to 0.1.21 were published only as `@githonllc/avouch`. Version 0.1.22 was published only as `avouch`. From 0.1.23, each release publishes the same files as `avouch` and as `@githonllc/avouch`; the docs use `avouch`. The name `avouch` was transferred to Githon LLC in 2026, and the earlier, unrelated versions 1.0.0 to 1.0.7 were unpublished. The two packages declare the same command `avouch`, so a project installs one of them, not both.
335
+
336
+ `avouch-cli` is a separate package in `alias/avouch-cli/`. It only forwards to `avouch`, so that `npx -y avouch-cli` does not run a stranger's package. It is published by hand and depends on `"avouch": "*"`. It needs a new version only when the forwarding code changes.
326
337
 
327
338
  `package.json` has `"private": true` in the repository, so an accidental `npm publish` from a working copy is refused. The release workflow removes that line only in its own checkout.
328
339
 
329
340
  A release needs the explicit approval of the project owner. Releases are published by the GitHub Actions workflow `.github/workflows/release.yml` through npm trusted publishing: no npm token is stored, and npm adds provenance. Do these steps in this sequence:
330
341
 
331
342
  1. Set the new `0.x` version in `package.json`, `.claude-plugin/plugin.json` and the `npx -y avouch@<version>` pins in `skills/*/SKILL.md`, merge it to `main`, and wait for CI to pass. Check the file list that the CI step `npm pack --dry-run` prints.
332
- 2. Tag the merge commit `v<version>` (the same version as `package.json`) and push the tag. The workflow checks that the tag matches the version, runs `npm ci`, the type check and the tests, removes `"private"`, and publishes with `--access public --tag latest`.
343
+ 2. Tag the merge commit `v<version>` (the same version as `package.json`) and push the tag. The workflow checks that the tag matches the version, runs `npm ci`, the type check and the tests, removes `"private"`, and publishes as `avouch` and then as `@githonllc/avouch`, with `--access public --tag latest`. A name that already has the version is skipped, so a re-run of a failed release publishes only the missing name.
333
344
  3. The job waits in the `npm` environment until the owner approves it in GitHub. The owner's approval is the release approval.
334
345
  4. Make sure that the release works:
335
- - `npm view avouch version` shows the new version (a new version can take a few minutes to become available);
336
- - in an empty directory, `npx -y avouch@<version>` (no arguments) prints the usage lines and exits with code 2.
346
+ - `npm view avouch version` and `npm view @githonllc/avouch version` show the new version (a new version can take a few minutes to become available);
347
+ - in an empty directory, `npx -y avouch@<version>` (no arguments) prints the help and exits with code 2;
348
+ - `npx -y avouch@<version> --version` prints the version.
337
349
 
338
350
  Version 0.1.0 was published by hand, because npm accepts a trusted publisher only for a package that exists.
339
351
 
@@ -1,10 +1,11 @@
1
1
  #!/usr/bin/env node
2
+ import { readFileSync } from "node:fs";
2
3
  import { resolveProject, runCheck } from "./check.js";
3
- import { FACTS_USAGE, runFacts } from "./facts.js";
4
- import { INIT_USAGE, runInit } from "./init.js";
5
- import { GATE_DOCS_USAGE, GATE_USAGE, runGate } from "./gate.js";
6
- import { QUERY_USAGE, runQuery } from "./query.js";
7
- import { expectPositionals, parseOptions, RECONCILE_USAGE, runReconcile, wantsHelp } from "./reconcile.js";
4
+ import { runFacts } from "./facts.js";
5
+ import { runInit } from "./init.js";
6
+ import { runGate } from "./gate.js";
7
+ import { runQuery } from "./query.js";
8
+ import { expectPositionals, parseOptions, runReconcile, wantsHelp } from "./reconcile.js";
8
9
  const CHECK_USAGE = "usage: avouch check [-f <ontology.yaml>] [--config <avouch.config.json>] [--adapter <module|config.json>]";
9
10
  async function check(args) {
10
11
  if (wantsHelp(args, ["-f", "--config", "--adapter"])) {
@@ -35,12 +36,34 @@ async function check(args) {
35
36
  console.log(`${ok ? "PASS" : "FAIL"}: ${errors.length} schema error(s), ${report.violations.length} violation(s), ${report.waived.length} waived`);
36
37
  return ok ? 0 : 1;
37
38
  }
38
- const USAGES = [CHECK_USAGE, QUERY_USAGE, RECONCILE_USAGE, GATE_USAGE, GATE_DOCS_USAGE, FACTS_USAGE, INIT_USAGE];
39
+ const HELP = `usage: avouch <command> [options]
40
+
41
+ Check and query an Avouch ontology: a spec whose every claim cites its source.
42
+
43
+ Commands:
44
+ init Set up a repository: agent plugin, agent instructions
45
+ check Check an ontology against the schema, rules and documents
46
+ query Read a rule: an action, object, property or citation
47
+ facts Show what the Markdown adapter reads from design documents
48
+ gate docs Require a recorded review decision for each document change
49
+ gate verify Require a verified case for each decision row
50
+ reconcile Compare runtime results with the evaluator and expectations
51
+
52
+ Options:
53
+ -h, --help Show this help, or the help of a command
54
+ -v, --version Show the version
55
+
56
+ Run "avouch <command> --help" for the options of a command.
57
+ Docs: https://avouch.dev
58
+ `;
39
59
  async function main() {
40
60
  const args = process.argv.slice(2);
41
61
  if (args[0] === "--help" || args[0] === "-h") {
42
- for (const usage of USAGES)
43
- console.log(usage);
62
+ process.stdout.write(HELP);
63
+ return 0;
64
+ }
65
+ if (args[0] === "--version" || args[0] === "-v") {
66
+ console.log(JSON.parse(readFileSync(new URL("../../package.json", import.meta.url), "utf8")).version);
44
67
  return 0;
45
68
  }
46
69
  if (args[0] === "check")
@@ -55,8 +78,10 @@ async function main() {
55
78
  return runFacts(args.slice(1));
56
79
  if (args[0] === "init")
57
80
  return runInit(args.slice(1));
58
- for (const usage of USAGES)
59
- console.error(usage);
81
+ if (args.length > 0)
82
+ console.error(`avouch: unknown command "${args[0]}"\nRun "avouch --help" for the commands.`);
83
+ else
84
+ process.stderr.write(HELP);
60
85
  return 2;
61
86
  }
62
87
  try {
@@ -9,10 +9,10 @@ export declare function createAsker(input: NodeJS.ReadableStream, output: NodeJS
9
9
  close: () => void;
10
10
  };
11
11
  /**
12
- * How to run `claude` with fixed arguments. On Windows `claude` is usually `claude.cmd`, which only a shell can run; the
13
- * arguments are constants, so the command line is safe for the shell. Elsewhere no shell.
12
+ * How to run a host (`claude` or `codex`) with fixed arguments. On Windows the host is usually `<host>.cmd`, which only a shell
13
+ * can run; the arguments are constants, so the command line is safe for the shell. Elsewhere no shell.
14
14
  */
15
- export declare function pluginSpawn(args: string[], platform?: NodeJS.Platform): {
15
+ export declare function pluginSpawn(args: string[], platform?: NodeJS.Platform, host?: string): {
16
16
  command: string;
17
17
  args: string[];
18
18
  options: SpawnSyncOptions;
package/dist/cli/init.js CHANGED
@@ -7,15 +7,17 @@ import { gitTop } from "./check.js";
7
7
  import { expectPositionals, parseOptions, wantsHelp } from "./reconcile.js";
8
8
  export const INIT_USAGE = "usage: avouch init [--append | --print] [--plugin | --no-plugin] [--dry-run]";
9
9
  const FLAGS = ["--append", "--print", "--plugin", "--no-plugin", "--dry-run"];
10
- const PLUGIN_COMMANDS = [
11
- ["plugin", "marketplace", "add", "githonllc/avouch"],
12
- ["plugin", "install", "avouch@avouch"],
10
+ // The hosts of the plugin, in the order that init handles them, and the commands that install it into each.
11
+ const HOSTS = [
12
+ { name: "claude", label: "Claude Code", suffix: "", commands: [["plugin", "marketplace", "add", "githonllc/avouch"], ["plugin", "install", "avouch@avouch"]] },
13
+ { name: "codex", label: "Codex", suffix: " for Codex", commands: [["plugin", "marketplace", "add", "githonllc/avouch"], ["plugin", "add", "avouch@avouch"]] },
13
14
  ];
15
+ const CODEX_HOOK_NOTE = "In Codex, the hook runs only after you approve it: approve the avouch hook when Codex asks.";
14
16
  const BEGIN = "<!-- BEGIN avouch -->";
15
17
  const END = "<!-- END avouch -->";
16
18
  const TARGETS = ["AGENTS.md", "CLAUDE.md"];
17
19
  const isTty = () => process.stdin.isTTY === true && process.stdout.isTTY === true;
18
- const commandLine = (args) => `claude ${args.join(" ")}`;
20
+ const commandLine = (host, args) => `${host} ${args.join(" ")}`;
19
21
  /**
20
22
  * Yes/no questions on one readline interface, made at the first question. Lines that arrive before a question is asked
21
23
  * (typed ahead) are queued and answer the next questions in order; at the end of input a question gets no (an empty answer).
@@ -57,21 +59,21 @@ export function createAsker(input, output) {
57
59
  let asker = createAsker(process.stdin, process.stdout);
58
60
  const ask = (question) => asker.ask(question);
59
61
  /**
60
- * How to run `claude` with fixed arguments. On Windows `claude` is usually `claude.cmd`, which only a shell can run; the
61
- * arguments are constants, so the command line is safe for the shell. Elsewhere no shell.
62
+ * How to run a host (`claude` or `codex`) with fixed arguments. On Windows the host is usually `<host>.cmd`, which only a shell
63
+ * can run; the arguments are constants, so the command line is safe for the shell. Elsewhere no shell.
62
64
  */
63
- export function pluginSpawn(args, platform = process.platform) {
65
+ export function pluginSpawn(args, platform = process.platform, host = "claude") {
64
66
  return platform === "win32"
65
- ? { command: commandLine(args), args: [], options: { stdio: "inherit", shell: true } }
66
- : { command: "claude", args, options: { stdio: "inherit" } };
67
+ ? { command: commandLine(host, args), args: [], options: { stdio: "inherit", shell: true } }
68
+ : { command: host, args, options: { stdio: "inherit" } };
67
69
  }
68
- // True when an executable file named `claude` is in a PATH directory.
69
- function claudeOnPath() {
70
+ // True when an executable file named `name` is in a PATH directory.
71
+ function onPath(name) {
70
72
  for (const dir of (process.env.PATH ?? "").split(delimiter)) {
71
73
  if (dir === "")
72
74
  continue;
73
- for (const name of process.platform === "win32" ? ["claude.exe", "claude.cmd", "claude"] : ["claude"]) {
74
- const path = join(dir, name);
75
+ for (const file of process.platform === "win32" ? [`${name}.exe`, `${name}.cmd`, name] : [name]) {
76
+ const path = join(dir, file);
75
77
  try {
76
78
  if (!statSync(path).isFile())
77
79
  continue;
@@ -130,27 +132,22 @@ function printBlock() {
130
132
  process.stdout.write(wrappedBlock("\n"));
131
133
  console.log("-----8<----- end of the Avouch agent instructions -----8<-----");
132
134
  }
133
- /** Step 1: the Claude Code plugin. Returns false when a plugin command failed. */
134
- async function plugin(opts, dryRun) {
135
- console.log("Step 1: the Avouch plugin for Claude Code (a hook that blocks text reads of an ontology, and the skills /avouch:scan and /avouch:cli).");
136
- if (opts.has("--no-plugin")) {
137
- console.log("Skipped (--no-plugin).");
138
- return true;
139
- }
135
+ /** Step 1, one host: install the plugin or print the commands. Returns false when a plugin command failed. */
136
+ async function pluginFor(host, opts, dryRun) {
140
137
  const printCommands = (why) => {
141
- console.log(`${why} To install the plugin, run:`);
142
- for (const c of PLUGIN_COMMANDS)
143
- console.log(` ${commandLine(c)}`);
138
+ console.log(`${why} To install the plugin${host.suffix}, run:`);
139
+ for (const c of host.commands)
140
+ console.log(` ${commandLine(host.name, c)}`);
144
141
  };
145
- if (!claudeOnPath()) {
146
- printCommands("No `claude` executable is on PATH.");
142
+ if (!onPath(host.name)) {
143
+ printCommands(`No \`${host.name}\` executable is on PATH.`);
147
144
  return true;
148
145
  }
149
146
  if (dryRun) {
150
147
  if (opts.has("--plugin")) {
151
148
  console.log("Dry run. These commands would run:");
152
- for (const c of PLUGIN_COMMANDS)
153
- console.log(` ${commandLine(c)}`);
149
+ for (const c of host.commands)
150
+ console.log(` ${commandLine(host.name, c)}`);
154
151
  }
155
152
  else
156
153
  printCommands(`Dry run. Without --plugin, init would ${isTty() ? "ask before it runs these commands" : "only print these commands"}.`);
@@ -162,7 +159,7 @@ async function plugin(opts, dryRun) {
162
159
  printCommands("No terminal, so init does not run the commands.");
163
160
  return true;
164
161
  }
165
- run = await ask("Install the Avouch plugin for Claude Code (user scope)?");
162
+ run = await ask(`Install the Avouch plugin for ${host.label} (user scope)?`);
166
163
  if (!run) {
167
164
  printCommands("Not installed.");
168
165
  return true;
@@ -170,17 +167,33 @@ async function plugin(opts, dryRun) {
170
167
  }
171
168
  let ok = true;
172
169
  // Both commands run even when the first fails: adding a marketplace that is already added can fail while the install still works.
173
- for (const c of PLUGIN_COMMANDS) {
174
- console.log(`Running: ${commandLine(c)}`);
175
- const s = pluginSpawn(c);
170
+ for (const c of host.commands) {
171
+ console.log(`Running: ${commandLine(host.name, c)}`);
172
+ const s = pluginSpawn(c, process.platform, host.name);
176
173
  const r = spawnSync(s.command, s.args, s.options);
177
174
  if (r.error !== undefined || r.status !== 0) {
178
175
  ok = false;
179
- console.error(`FAIL: ${commandLine(c)}: ${r.error !== undefined ? r.error.message : r.status !== null ? `exit ${r.status}` : `signal ${r.signal}`}`);
176
+ console.error(`FAIL: ${commandLine(host.name, c)}: ${r.error !== undefined ? r.error.message : r.status !== null ? `exit ${r.status}` : `signal ${r.signal}`}`);
180
177
  }
181
178
  }
182
179
  return ok;
183
180
  }
181
+ /** Step 1: the plugin for Claude Code and Codex. Returns false when a plugin command failed. */
182
+ async function plugin(opts, dryRun) {
183
+ console.log("Step 1: the Avouch plugin for Claude Code and Codex (a hook that blocks text reads of an ontology, and the skills avouch:scan and avouch:cli).");
184
+ if (opts.has("--no-plugin")) {
185
+ console.log("Skipped (--no-plugin).");
186
+ return true;
187
+ }
188
+ let ok = true;
189
+ for (const host of HOSTS) {
190
+ const hostOk = await pluginFor(host, opts, dryRun);
191
+ ok = hostOk && ok;
192
+ if (host.name === "codex" && hostOk)
193
+ console.log(CODEX_HOOK_NOTE);
194
+ }
195
+ return ok;
196
+ }
184
197
  /** Step 2: the agent instructions. Returns false when a file could not be written. */
185
198
  async function instructions(top, opts, dryRun) {
186
199
  console.log("Step 2: the Avouch instructions for coding agents (AGENTS.md, CLAUDE.md).");
package/package.json CHANGED
@@ -1,7 +1,19 @@
1
1
  {
2
2
  "name": "avouch",
3
- "version": "0.1.22",
3
+ "version": "0.1.23",
4
+ "description": "Avouch: an ontology spec whose every claim cites its source, with a checker and a CLI.",
4
5
  "license": "Apache-2.0",
6
+ "author": "Githon LLC",
7
+ "keywords": [
8
+ "avouch",
9
+ "ontology",
10
+ "specification",
11
+ "design-docs",
12
+ "ai-agents",
13
+ "claude-code",
14
+ "checker",
15
+ "cli"
16
+ ],
5
17
  "repository": {
6
18
  "type": "git",
7
19
  "url": "git+https://github.com/githonllc/avouch.git"
@@ -7,6 +7,6 @@ The business rules of this project are in an Avouch ontology (`*.ontology.yaml`,
7
7
  - Do not read the ontology file with grep, cat, sed or a script. Comments and neighbouring entries in the text look like rules, but the checker does not read them.
8
8
  - If the rule is `unspecified` or is in `knownSourceGaps`, the documents do not decide it. Do not invent the behavior: tell your user, and say so in the pull request.
9
9
  - If the ontology, the documents and the code disagree, do not decide in code. Tell your user which texts disagree.
10
- - To change a rule, change the design document first, or ask your user to. Then update the ontology so that each claim quotes the new text: in Claude Code with `/avouch:scan`, otherwise with the writing rules in https://avouch.dev/llms.txt. Do not add a rule that no document states.
10
+ - To change a rule, change the design document first, or ask your user to. Then update the ontology so that each claim quotes the new text: in Claude Code with `/avouch:scan`, in Codex with `$avouch:scan`, otherwise with the writing rules in https://avouch.dev/llms.txt. Do not add a rule that no document states.
11
11
  - After you change the ontology or a cited document section, run `npx -y avouch check`, and `npx -y avouch gate docs` if the project has a ledger (`avouch.ledger.jsonl`). Both must exit 0. `check` covers the format rules only; it does not replace the project's tests.
12
12
  - Do not edit the ledger to make the gate pass without reading the changed section.