From bc567195b4983953cf96708cff2d280831328cae Mon Sep 17 00:00:00 2001 From: Chris Feijoo Date: Fri, 28 Aug 2026 00:32:54 +0200 Subject: [PATCH 1/4] FE-1533: Add a petrinaut-shipping skill to the repo skills --- .agents/skills/petrinaut-shipping/SKILL.md | 65 ++++++++++++++++++++++ .claude/skills/petrinaut-shipping | 1 + .claude/skills/skill-rules.json | 25 +++++++++ 3 files changed, 91 insertions(+) create mode 100644 .agents/skills/petrinaut-shipping/SKILL.md create mode 120000 .claude/skills/petrinaut-shipping diff --git a/.agents/skills/petrinaut-shipping/SKILL.md b/.agents/skills/petrinaut-shipping/SKILL.md new file mode 100644 index 00000000000..06fc740afbe --- /dev/null +++ b/.agents/skills/petrinaut-shipping/SKILL.md @@ -0,0 +1,65 @@ +--- +name: petrinaut-shipping +description: "End-to-end procedure for shipping a change to the Petrinaut packages (libs/@hashintel/petrinaut, petrinaut-core, petrinaut-cli, apps/petrinaut-opt, apps/petrinaut-website): the verification gates per package, the changeset step, docs sync, pre-PR hygiene checks, and CI expectations from draft to ready. Use when implementing any change in these packages, when creating a PR for Petrinaut work, when running tests or lints for them, or when checking CI on a Petrinaut PR." +license: Apache-2.0 +metadata: + triggers: + type: domain + enforcement: suggest + priority: high + keywords: + - petrinaut + - changeset + - SDCPN + - petri net + intent-patterns: + - "\\b(implement|create|fix|add|ship|change)\\b.*?\\bpetrinaut\\b" + - "\\bpetrinaut\\b.*?\\b(PR|tests?|lint|CI|checks?)\\b" + files: + include: + - "libs/@hashintel/petrinaut*/**" + - "apps/petrinaut-opt/**" + - "apps/petrinaut-website/**" +--- + +# Shipping a Petrinaut change + +Standing conventions (changeset policy, docs and diagram placement, CI quirks, the petrinaut-opt boundary) live in `libs/@hashintel/petrinaut/AGENTS.md` and `apps/petrinaut-opt/AGENTS.md`. This skill is the procedure that applies them. + +## Gates + +Run for every touched package, after every increment: + +```sh +yarn fix:format >/dev/null 2>&1 +npx turbo run test:unit lint:tsc lint:eslint --filter @hashintel/petrinaut --filter @hashintel/petrinaut-core --filter @hashintel/petrinaut-cli --force --output-logs errors-only +yarn lint:format +``` + +- Trim the `--filter`s to the touched packages; add `--filter @apps/petrinaut-website` when it consumes the change. +- Structure changed (new folder, moved module): also `yarn workspace @local/petrinaut-arch-docs lint:arch-docs`, and add the layer declaration the AGENTS.md architecture section calls for. +- Arch-docs authored content or `content/diagrams/*.d2` changed: `lint:arch-docs` does not compile MDX or render D2. Run the site build once before pushing: `mise x -- yarn exec turbo run build --filter @apps/petrinaut-docs`. D2 labels containing `:` or `[` must be quoted. +- Python (`apps/petrinaut-opt`, `libs/@local/petrinaut-python`): `uv run pytest` in the package. +- Formatting is oxfmt via the yarn scripts; never run prettier directly. `yarn lint:format` prints its verdict before its final line, so check the exit code rather than the last line of output. + +## Changesets + +One `patch` changeset per PR covering the published packages the PR touches (`@hashintel/petrinaut`, `@hashintel/petrinaut-core`); none for pure refactors. Keep the text to one or two plain sentences. See the AGENTS.md conventions for the full policy. + +## Docs sync + +User-visible behaviour changes update the user guide in the same PR; new pages need registration and a raw import, both test-enforced. The steps are in the "User-facing docs" section of `libs/@hashintel/petrinaut/AGENTS.md`. Doc screenshots cannot be uploaded by an agent: produce candidate captures, list the exact pages and sections to re-capture, and flag "screenshots pending" in the PR body and the summary. + +## Pre-PR hygiene + +- Read `git diff --stat` against the base: no accidental directories, no unstaged leftovers, no generated output, no `mise.lock` churn. +- A `Bin` line in the stat for a text file means escape sequences became literal control bytes; fix it before pushing or the diff is unreviewable. +- A diff too large for one review gets split into stacked PRs, one concern per layer. + +## Draft, CI, ready + +- Open the PR as a draft, body per the repo PR template. +- Watch checks until none are pending: `until [ "$(gh pr checks NNNN 2>/dev/null | grep -c pending)" = "0" ]; do sleep 60; done; gh pr checks NNNN`. +- Judge failures against the CI bullet in the AGENTS.md conventions (Bench-CI non-blocking, the known flaky check, Vercel-side docs failures) before treating them as caused by the diff. +- Flip to ready only when checks are green. AI reviewers run at that point; triage their threads rather than leaving them unresolved. +- End any turn that changed the branch by stating what was committed and pushed, or that nothing was. diff --git a/.claude/skills/petrinaut-shipping b/.claude/skills/petrinaut-shipping new file mode 120000 index 00000000000..a58b8ebc99d --- /dev/null +++ b/.claude/skills/petrinaut-shipping @@ -0,0 +1 @@ +../../.agents/skills/petrinaut-shipping \ No newline at end of file diff --git a/.claude/skills/skill-rules.json b/.claude/skills/skill-rules.json index a0f1e1f71ab..1a927d1bf99 100644 --- a/.claude/skills/skill-rules.json +++ b/.claude/skills/skill-rules.json @@ -193,6 +193,31 @@ "blockMessage": "Skill is required to proceed", "skipConditions": {} }, + "petrinaut-shipping": { + "type": "domain", + "enforcement": "suggest", + "priority": "high", + "description": "End-to-end procedure for shipping a change to the Petrinaut packages (libs/@hashintel/petrinaut, petrinaut-core, petrinaut-cli, apps/petrinaut-opt, apps/petrinaut-website): the verification gates per package, the changeset step, docs sync, pre-PR hygiene checks, and CI expectations from draft to ready. Use when implementing any change in these packages, when creating a PR for Petrinaut work, when running tests or lints for them, or when checking CI on a Petrinaut PR.", + "promptTriggers": { + "keywords": ["petrinaut", "changeset", "SDCPN", "petri net"], + "intentPatterns": [ + "\\b(implement|create|fix|add|ship|change)\\b.*?\\bpetrinaut\\b", + "\\bpetrinaut\\b.*?\\b(PR|tests?|lint|CI|checks?)\\b" + ] + }, + "fileTriggers": { + "include": [ + "libs/@hashintel/petrinaut*/**", + "apps/petrinaut-opt/**", + "apps/petrinaut-website/**" + ], + "exclude": [], + "content": [], + "create-only": false + }, + "blockMessage": "Skill is required to proceed", + "skipConditions": {} + }, "rust-coding-style": { "type": "domain", "enforcement": "suggest", From 225647c828669ba63f907d910517f25d17f8833f Mon Sep 17 00:00:00 2001 From: Chris Feijoo Date: Mon, 31 Aug 2026 16:56:45 +0200 Subject: [PATCH 2/4] FE-1533: Narrow the skill's activation triggers --- .agents/skills/petrinaut-shipping/SKILL.md | 8 -------- .claude/skills/skill-rules.json | 8 ++------ 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/.agents/skills/petrinaut-shipping/SKILL.md b/.agents/skills/petrinaut-shipping/SKILL.md index 06fc740afbe..f84f54118e4 100644 --- a/.agents/skills/petrinaut-shipping/SKILL.md +++ b/.agents/skills/petrinaut-shipping/SKILL.md @@ -9,17 +9,9 @@ metadata: priority: high keywords: - petrinaut - - changeset - - SDCPN - - petri net intent-patterns: - "\\b(implement|create|fix|add|ship|change)\\b.*?\\bpetrinaut\\b" - "\\bpetrinaut\\b.*?\\b(PR|tests?|lint|CI|checks?)\\b" - files: - include: - - "libs/@hashintel/petrinaut*/**" - - "apps/petrinaut-opt/**" - - "apps/petrinaut-website/**" --- # Shipping a Petrinaut change diff --git a/.claude/skills/skill-rules.json b/.claude/skills/skill-rules.json index 1a927d1bf99..7b5114a9578 100644 --- a/.claude/skills/skill-rules.json +++ b/.claude/skills/skill-rules.json @@ -199,18 +199,14 @@ "priority": "high", "description": "End-to-end procedure for shipping a change to the Petrinaut packages (libs/@hashintel/petrinaut, petrinaut-core, petrinaut-cli, apps/petrinaut-opt, apps/petrinaut-website): the verification gates per package, the changeset step, docs sync, pre-PR hygiene checks, and CI expectations from draft to ready. Use when implementing any change in these packages, when creating a PR for Petrinaut work, when running tests or lints for them, or when checking CI on a Petrinaut PR.", "promptTriggers": { - "keywords": ["petrinaut", "changeset", "SDCPN", "petri net"], + "keywords": ["petrinaut"], "intentPatterns": [ "\\b(implement|create|fix|add|ship|change)\\b.*?\\bpetrinaut\\b", "\\bpetrinaut\\b.*?\\b(PR|tests?|lint|CI|checks?)\\b" ] }, "fileTriggers": { - "include": [ - "libs/@hashintel/petrinaut*/**", - "apps/petrinaut-opt/**", - "apps/petrinaut-website/**" - ], + "include": [], "exclude": [], "content": [], "create-only": false From 425d6c51f57dcca1d272fbf802f7c11d16e247d4 Mon Sep 17 00:00:00 2001 From: Chris Feijoo Date: Mon, 31 Aug 2026 17:19:01 +0200 Subject: [PATCH 3/4] FE-1533: Make the CI wait loop survive a PR with no checks yet --- .agents/skills/petrinaut-shipping/SKILL.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.agents/skills/petrinaut-shipping/SKILL.md b/.agents/skills/petrinaut-shipping/SKILL.md index f84f54118e4..080b0cdd6ee 100644 --- a/.agents/skills/petrinaut-shipping/SKILL.md +++ b/.agents/skills/petrinaut-shipping/SKILL.md @@ -51,7 +51,13 @@ User-visible behaviour changes update the user guide in the same PR; new pages n ## Draft, CI, ready - Open the PR as a draft, body per the repo PR template. -- Watch checks until none are pending: `until [ "$(gh pr checks NNNN 2>/dev/null | grep -c pending)" = "0" ]; do sleep 60; done; gh pr checks NNNN`. +- Watch checks until none are pending. Requiring the command to succeed matters: on a freshly opened PR it fails until GitHub schedules the checks, and treating that as "nothing pending" ends the wait before CI starts. + + ```sh + until gh pr checks NNNN >/dev/null 2>&1 && [ "$(gh pr checks NNNN | grep -c pending)" = "0" ]; do sleep 60; done + gh pr checks NNNN + ``` + - Judge failures against the CI bullet in the AGENTS.md conventions (Bench-CI non-blocking, the known flaky check, Vercel-side docs failures) before treating them as caused by the diff. - Flip to ready only when checks are green. AI reviewers run at that point; triage their threads rather than leaving them unresolved. - End any turn that changed the branch by stating what was committed and pushed, or that nothing was. From 9990f1a3e51023449dd7c1ce9691c52a71ce93f3 Mon Sep 17 00:00:00 2001 From: Chris Feijoo Date: Mon, 31 Aug 2026 18:23:13 +0200 Subject: [PATCH 4/4] FE-1533: Read check state from JSON so a failed run ends the wait --- .agents/skills/petrinaut-shipping/SKILL.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.agents/skills/petrinaut-shipping/SKILL.md b/.agents/skills/petrinaut-shipping/SKILL.md index 080b0cdd6ee..253c454ee1a 100644 --- a/.agents/skills/petrinaut-shipping/SKILL.md +++ b/.agents/skills/petrinaut-shipping/SKILL.md @@ -51,13 +51,19 @@ User-visible behaviour changes update the user guide in the same PR; new pages n ## Draft, CI, ready - Open the PR as a draft, body per the repo PR template. -- Watch checks until none are pending. Requiring the command to succeed matters: on a freshly opened PR it fails until GitHub schedules the checks, and treating that as "nothing pending" ends the wait before CI starts. +- Watch checks until none are pending, reading the JSON rather than the exit status. `gh pr checks` exits non-zero for three different situations: checks pending, checks failed, and no checks scheduled yet. Gating the loop on that status either ends the wait before CI starts or never ends it once a check fails. ```sh - until gh pr checks NNNN >/dev/null 2>&1 && [ "$(gh pr checks NNNN | grep -c pending)" = "0" ]; do sleep 60; done + while :; do + pending=$(gh pr checks NNNN --json bucket --jq '[.[] | select(.bucket == "pending")] | length' 2>/dev/null) + [ -n "$pending" ] && [ "$pending" -eq 0 ] && break + sleep 60 + done gh pr checks NNNN ``` + An empty result means the checks do not exist yet and the loop keeps waiting. A PR that never settles has not started CI at all. + - Judge failures against the CI bullet in the AGENTS.md conventions (Bench-CI non-blocking, the known flaky check, Vercel-side docs failures) before treating them as caused by the diff. - Flip to ready only when checks are green. AI reviewers run at that point; triage their threads rather than leaving them unresolved. - End any turn that changed the branch by stating what was committed and pushed, or that nothing was.