Skip to content
Open
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
19 changes: 17 additions & 2 deletions .claude/skills/release-docs/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -1055,10 +1055,25 @@ instead of 57/2). Then:
add, rename or change a public API. Grep the new snapshot for each symbol.
2. **`<` commits are in the release only.** Step 8b's sweep covers their breaking changes;
check that every `!:` one was swept.
3. **Adjudicate every hit against `$AZTEC_NODE_DIR`**, the tag, as in Step 8b item 3. Fix
3. **Pages whose `references` changed between the two pins.** The old pin is the
destination's (the line's in a line cut); the script reads the cut's main paths:

```bash
. ~/.cache/aztec-docs-cut/<cut>/env.sh && cd "$CUT"
old=$(git -C "$DEST_ROOT" show "$DEST:docs/${LINE:+lines/$LINE/}aztec-node.json" |
node -p 'JSON.parse(require("fs").readFileSync(0, "utf8")).commit') &&
docs/scripts/pin_doc_references.sh "$old"
```

For each listed page, read its references' diff and decide as the
`update-doc-references` skill's Step 4 does, against the page's snapshot copy:
`docs/docs-developers/<page>` is `docs/developer_versioned_docs/version-v<new_version>/<page>`,
`docs/docs-operate/<page>` is `docs/network_versioned_docs/version-v<new_version>/<page>`.
A `docs/docs-participate/` page has no snapshot and follows the destination's pin: skip it.
4. **Adjudicate every hit against `$AZTEC_NODE_DIR`**, the tag, as in Step 8b item 3. Fix
the snapshot only: the source follows the destination's pin, so these fixes are
release-only (Step 17).
4. Present what was found, fixed and skipped, for user confirmation.
5. Present what was found, fixed and skipped, for user confirmation.

### Step 13: Build and Fix Issues

Expand Down
14 changes: 14 additions & 0 deletions .claude/skills/release-network-docs/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,20 @@ a failed count check work as in `/release-docs` Step 12. So do hand backports: o
to its line (`v6`) is not patch-equivalent, so `--cherry-pick` keeps it on both sides;
judge it against `$AZTEC_NODE_DIR`, the tag.

Then list the pages whose `references` changed between the two pins. The old pin is the
destination's (the line's in a line cut); the script reads the cut's main paths:

```bash
. ~/.cache/aztec-docs-cut/<cut>/env.sh && cd "$CUT"
old=$(git -C "$DEST_ROOT" show "$DEST:docs/${LINE:+lines/$LINE/}aztec-node.json" |
node -p 'JSON.parse(require("fs").readFileSync(0, "utf8")).commit') &&
docs/scripts/pin_doc_references.sh "$old"
```

Take its `docs/docs-operate/<page>` entries. For each, read its references' diff and decide
as the `update-doc-references` skill's Step 4 does, against the snapshot copy
`docs/network_versioned_docs/version-v<new_version>/<page>`; fix it under the rule below.

`>` commits are in the destination's pin but not in the release. Start with the operator
pages the second log names (aztec-node held the docs until they moved here, so a code
change and its doc edit landed in one commit) and revert those hunks in the snapshot,
Expand Down
43 changes: 24 additions & 19 deletions .claude/skills/update-doc-references/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,22 +64,25 @@ checkouts, and edit each copy whose checkout has it (Step 5): a `main` PR can fi
shares, and a page that is wrong about code both lines have is wrong in both copies.

When the change is a move of a pin rather than a PR (`node docs/scripts/aztec_node.mts
[--line <line>] pin <tag>`), take it from the two pin commits, fetched into that line's
checkout. A two-commit diff needs no history between them. For main:
[--line <line>] pin <tag>`), the pages it reaches come from the line's two pin commits. Run
this once per line whose pin moved, after `check` passes:

```bash
cd "$(git rev-parse --show-toplevel)"
pinfile=docs/aztec-node.json lineopt= # the v6 line's: pinfile=docs/lines/v6/aztec-node.json lineopt="--line v6"
old=$(git show "$(git merge-base origin/next HEAD):$pinfile" | node -p 'JSON.parse(require("fs").readFileSync(0, "utf8")).commit')
new=$(node -p "require('./$pinfile').commit")
node docs/scripts/aztec_node.mts $lineopt fetch && pin=$(node docs/scripts/aztec_node.mts $lineopt env) || exit 1
eval "$pin"
git -C "$AZTEC_NODE_DIR" fetch --depth 1 --no-tags origin "$old" "$new"
git -C "$AZTEC_NODE_DIR" diff --name-only "$old" "$new" | sed 's|^|labs/|'
git -C "$AZTEC_NODE_DIR" diff "$old" "$new" -- <path without labs/>
docs/scripts/pin_doc_references.sh # the v6 line's: docs/scripts/pin_doc_references.sh --line v6
```

The pin file also names the toolchain: when `bb`, `noir` or `l1Artifacts` moved, say so in
It prints `<reference> -> <page>, <page>` for each `labs/` reference whose files differ
between the line's pin at `git merge-base origin/next HEAD` and its pin now. Pass the old
commit as an argument when the base is another (a release cut does). That list is Step 3's
mapping. stderr names both commits and the checkout, so read one reference's change with:

```bash
git -C "$AZTEC_NODE_DIR" diff <old> <new> -- <reference without labs/ and /*>
```

`AZTEC_NODE_DIR` is the line's checkout: `eval "$(node docs/scripts/aztec_node.mts [--line
v6] env)"` exports it. The pin file also names the toolchain: when `bb`, `noir` or `l1Artifacts` moved, say so in
the report, since the examples and the Solidity snippets follow them.

### Step 3: Identify Affected Documentation
Expand All @@ -97,16 +100,14 @@ gh pr view <PR_NUMBER> --repo aztec-labs-eng/aztec-node --json files -q '.files[
sed 's|^|labs/|' >"$changed"
for root in docs docs/lines/*; do
extract_references_mapping "$root" "$map"
awk -F'|' 'NR == FNR {changed[$0]; next}
{ref = $1; dir = sub(/\/\*$/, "/", ref)
for (f in changed) if (dir ? index(f, ref) == 1 : f == ref) print f " -> " $2}' \
"$changed" "$map" | sort -u
changed_references "$map" "$changed"
done
```

For a PR of this repository drop the `sed`; for a pin move write Step 2's `--name-only`
list to `"$changed"` instead. Report any pair the prompt lists that this does not produce,
and the reverse: the dispatcher's mapping is then stale.
Each line is `<reference> -> <page>, <page>`, as `pin_doc_references.sh` prints for a pin
move, which needs no other mapping. For a PR of this repository drop the `sed`. Report any
pair the prompt lists that this does not produce, and the reverse: the dispatcher's mapping
is then stale.

### Step 4: Analyze Changes

Expand Down Expand Up @@ -163,7 +164,11 @@ pass.

### Step 6: Commit on a Branch

If changes were made, commit them on a branch from `next`:
For a pin move, commit the edits on the branch that moves the pin, so they ship in its PR,
naming each file as below; skip the new branch and Step 7, and list the pages you checked in
that PR's description.

Otherwise, if changes were made, commit them on a branch from `next`:

```bash
git fetch origin next
Expand Down
1 change: 1 addition & 0 deletions docs/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ The aztec-node (Labs) code the docs quote is the commit `aztec-node.json` pins,
- Snippet and `references:` paths keep their `labs/` prefix, which names the checkout: `labs/yarn-project/...` reads `.aztec-node/tree/yarn-project/...`, and source links name aztec-node at the pinned commit.
- `node scripts/aztec_node.mts check` fails on any drift: a checkout at another commit or with edited files, toolchain versions that differ from the tag's, or an l1-artifacts version in `package.json` that differs from the pin.
- Move the pin with `node scripts/aztec_node.mts pin <tag>` (a release or nightly tag), never by hand; then set `@aztec-foundation/l1-artifacts` to the version `check` names, run `yarn install`, and commit `aztec-node.json` with `package.json` and `yarn.lock`.
- In the same PR, update the pages the move reaches, for each line whose pin moved. Once `check` passes, `scripts/pin_doc_references.sh [--line <line>]` prints `<reference> -> <pages>` for each `labs/` reference whose files differ between the pin at `git merge-base origin/next HEAD` and the new one; run the `update-doc-references` skill on that list. Then read `node:` in `https://install.aztec.network/<toolchain.aztec>/versions` for the new pin, and if it changed, update `node_ver` on that line's `getting_started_on_local_network.md` (a release cut does this in `/release-docs` Step 10).
- `pin` needs `gh` logged in: it records the sha256 of each noir release archive in `noirArchives` once `gh attestation verify` proves noir's publish workflow built it, and `provision` refuses a nargo archive whose sha256 differs. Never edit `noirArchives` to get past a mismatch: it means the release archive changed after the pin.
- Tools that need nargo, bb or the aztec CLI use the pinned published ones: `node scripts/aztec_node.mts provision nargo bb cli`, then `eval "$(node scripts/aztec_node.mts env)"` exports `NARGO`, `BB`, `AZTEC` and the versions. Never run nargo inside `docs/` or the checkout: it takes `docs/Nargo.toml` as its workspace.
- Each line's pin follows its own aztec-node branch (see "Two dev lines: change both"): `aztec-node.json` follows `main` (v7 from 2026-11-04), and `lines/<line>/aztec-node.json` follows `<line>`. Move a line's pin with `node scripts/aztec_node.mts --line <line> pin <tag>`: it installs the line's l1-artifacts into `lines/<line>/.aztec-node/`, so `package.json` does not change. A line's `pin` and `check` refuse a tag of another major. After moving any pin, check that the recorded commit is on its branch: `gh api "repos/aztec-labs-eng/aztec-node/compare/<branch>...<commit>" --jq .status` prints `behind` or `identical`.
Expand Down
4 changes: 3 additions & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,9 @@ Documentation pages can declare which source files they document via a `referenc

2. **Validation**: During CI builds (`bootstrap.sh`), the system extracts all referenced paths from documentation frontmatter and fails the build if any of them no longer exist; update the `references` frontmatter in the affected doc.

**Implementation**: The check is `scripts/check_doc_references.sh` (with `scripts/lib/extract_doc_references.sh` for frontmatter parsing), which runs as part of the docs CI pipeline.
3. **Pin moves**: aztec-node changes reach the docs only when a line's pin moves, so the PR that moves it also updates the pages it reaches. `scripts/pin_doc_references.sh [--line <line>] [<old-commit>]` lists them as `<reference> -> <pages>`: every reference whose files differ between the old pin (by default the line's pin at `git merge-base origin/next HEAD`) and the new one. The `update-doc-references` skill under `.claude/skills/` takes that list.

**Implementation**: The check is `scripts/check_doc_references.sh` (with `scripts/lib/extract_doc_references.sh` for frontmatter parsing), which runs as part of the docs CI pipeline. `scripts/pin_doc_references.sh` uses the same library.

**Path Format**:

Expand Down
130 changes: 130 additions & 0 deletions docs/scripts/__tests__/pin_doc_references.test.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import assert from "node:assert/strict";
import { execFileSync, spawnSync } from "node:child_process";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { after, before, test } from "node:test";

const scripts = path.resolve(import.meta.dirname, "..");
const SCRIPTS = ["pin_doc_references.sh", "lib/extract_doc_references.sh", "lib/aztec_node.sh", "aztec_node.mts"];
const git = (cwd: string, ...args: string[]) =>
execFileSync("git", ["-C", cwd, "-c", "commit.gpgsign=false", "-c", "user.name=t", "-c", "user.email=t@t", ...args], { encoding: "utf8" }).trim();

function write(file: string, text: string) {
fs.mkdirSync(path.dirname(file), { recursive: true });
fs.writeFileSync(file, text);
}

// An aztec-node stand-in with one commit per step (a null content deletes the file); returns the commits.
function upstream(dir: string, steps: Record<string, string | null>[]): string[] {
fs.mkdirSync(dir, { recursive: true });
git(dir, "init", "-q");
git(dir, "config", "uploadpack.allowAnySHA1InWant", "true");
write(path.join(dir, "labs-aztec-toolchain/bootstrap.sh"), "BB_VERSION=1.0.0\nNOIR_VERSION=0.1.0\n");
return steps.map((step, i) => {
for (const [file, text] of Object.entries(step)) {
if (text === null) fs.rmSync(path.join(dir, file));
else write(path.join(dir, file), text);
}
git(dir, "add", "-A");
git(dir, "commit", "-q", "-m", `step ${i}`);
return git(dir, "rev-parse", "HEAD");
});
}

const pin = (ref: string, commit: string) =>
JSON.stringify({
repository: "https://github.com/aztec-labs-eng/aztec-node",
ref,
commit,
toolchain: { aztec: ref.slice(1), bb: "1.0.0", noir: "0.1.0", l1Artifacts: "1.0.0" },
noirArchives: { "x86_64-unknown-linux-gnu": `sha256:${"0".repeat(64)}` },
});

const page = (refs: string[]) => `---\ntitle: p\nreferences: [${refs.map((r) => `"${r}"`).join(", ")}]\n---\n`;

// The repository's docs/, whose branch moved main's pin from mainOld to mainNew and the v1 line's
// from lineOld to lineNew since origin/next; each checkout is a depth-1 clone of the new pin.
let base: string, root: string, mainOld: string, mainNew: string;
before(() => {
base = fs.mkdtempSync(path.join(os.tmpdir(), "pin-doc-references-"));
root = path.join(base, "repo");
const docs = path.join(root, "docs");
const line = path.join(docs, "lines/v1");
fs.mkdirSync(root);
git(root, "init", "-q");
for (const script of SCRIPTS) write(path.join(docs, "scripts", script), fs.readFileSync(path.join(scripts, script), "utf8"));
write(path.join(docs, ".gitignore"), ".aztec-node/\n");
write(path.join(docs, "package.json"), JSON.stringify({ devDependencies: { "@aztec-foundation/l1-artifacts": "1.0.0" } }));

[mainOld, mainNew] = upstream(path.join(base, "main"), [
{ "yarn-project/a.ts": "1", "yarn-project/same.ts": "s", "yarn-project/dir/x.ts": "1", "yarn-project/old_name.ts": "renamed\n".repeat(20), "yarn-project/gone.ts": "g", 'yarn-project/q/a"b.ts': "1" },
{ "yarn-project/a.ts": "2", "yarn-project/dir/x.ts": "2", "yarn-project/old_name.ts": null, "yarn-project/new_name.ts": "renamed\n".repeat(20), "yarn-project/gone.ts": null, "yarn-project/same.ts.orig": "o", 'yarn-project/q/a"b.ts': "2" },
]);
const [lineOld, lineNew] = upstream(path.join(base, "v1"), [
{ "yarn-project/a.ts": "1", "yarn-project/v1.ts": "1" },
{ "yarn-project/v1.ts": "2" },
]);

write(path.join(docs, "docs-developers/a.md"), page(["labs/yarn-project/a.ts", "labs/yarn-project/same.ts"]));
write(path.join(docs, "docs-developers/b.md"), "---\ntitle: b\nreferences:\n [\n \"labs/yarn-project/dir/*\",\n \"labs/yarn-project/q/*\",\n ]\n---\n");
write(path.join(docs, "docs-developers/d.md"), page(["labs/yarn-project/same.ts", "labs/yarn-project/di/*", "docs/examples/x.ts"]));
write(path.join(docs, "docs-developers/e.md"), page(["labs/yarn-project/a.ts"]));
write(path.join(docs, "docs-operate/c.md"), page(["labs/yarn-project/old_name.ts", "labs/yarn-project/gone.ts"]));
write(path.join(line, "docs-developers/a.md"), page(["labs/yarn-project/a.ts", "labs/yarn-project/v1.ts"]));

write(path.join(docs, "aztec-node.json"), pin("v1.1.0", mainOld));
write(path.join(line, "aztec-node.json"), pin("v1.0.0", lineOld));
git(root, "add", "-A");
git(root, "commit", "-q", "-m", "base");
git(root, "update-ref", "refs/remotes/origin/next", "HEAD");
write(path.join(docs, "aztec-node.json"), pin("v1.1.0", mainNew));
write(path.join(line, "aztec-node.json"), pin("v1.0.0", lineNew));
git(root, "commit", "-q", "-am", "move the pins");

for (const [up, state] of [["main", docs], ["v1", line]]) {
execFileSync("git", ["clone", "-q", "--depth", "1", "--no-tags", `file://${path.join(base, up)}`, path.join(state, ".aztec-node/tree")]);
}
write(path.join(line, ".aztec-node/l1-artifacts/package.json"), '{"version":"1.0.0"}');
});
after(() => fs.rmSync(base, { recursive: true, force: true }));

function run(...args: string[]) {
const env = { ...process.env };
delete env.AZTEC_NODE_DIR;
return spawnSync("bash", [path.join(root, "docs/scripts/pin_doc_references.sh"), ...args], { cwd: root, env, encoding: "utf8" });
}

const MAIN = [
"labs/yarn-project/a.ts -> docs/docs-developers/a.md, docs/docs-developers/e.md",
"labs/yarn-project/dir/* -> docs/docs-developers/b.md",
"labs/yarn-project/gone.ts -> docs/docs-operate/c.md",
"labs/yarn-project/old_name.ts -> docs/docs-operate/c.md",
"labs/yarn-project/q/* -> docs/docs-developers/b.md",
"",
].join("\n");

test("lists each reference whose files changed, fetching the old commit the checkout lacks", () => {
const tree = path.join(root, "docs/.aztec-node/tree");
assert.notEqual(spawnSync("git", ["-C", tree, "cat-file", "-e", `${mainOld}^{commit}`]).status, 0, "the old commit starts outside the checkout");

const r = run(mainOld);
assert.equal(r.status, 0, r.stderr);
assert.equal(r.stdout, MAIN);
});

test("defaults to each line's pin at the merge base with origin/next", () => {
const main = run();
assert.equal(main.status, 0, main.stderr);
assert.equal(main.stdout, MAIN);

const line = run("--line", "v1");
assert.equal(line.status, 0, line.stderr);
assert.equal(line.stdout, "labs/yarn-project/v1.ts -> docs/lines/v1/docs-developers/a.md\n");

const unmoved = run(mainNew);
assert.equal(unmoved.status, 0, unmoved.stderr);
assert.equal(unmoved.stdout, "");

assert.equal(run("HEAD").status, 2);
});
Loading
Loading