Skip to content

Add a build-test-review skill for accepted PROF designs - #993

Open
rkennke wants to merge 6 commits into
mainfrom
rkennke/PROF-16594-build-test-review
Open

rkennke wants to merge 6 commits into
mainfrom
rkennke/PROF-16594-build-test-review

Conversation

@rkennke

@rkennke rkennke commented Nov 13, 2026 •

Copy link
Copy Markdown
Contributor

What does this PR do?:

Adds the build-test-review agent skill. It turns a PROF ticket whose Design, acceptance criteria and Build plan are accepted into a reviewed local branch:

  • Checklist. It writes a "Sub-sessions" checklist into the ticket: S1 Build, S2 Test, S3 Review.
  • Sub-sessions. In Claude Code, each part runs as a fresh subagent that gets only the ticket, its part, the worktree and, for a fix round, the triaged findings. The session that loads the skill is the only one that writes to the ticket.
  • Loop. Build, review, then triage. Findings and failed tests go back to a new build run. Tests run only after a review round leaves no Critical or High finding open, and earlier results are inconclusive after each new commit.
  • Stops. It stops for the engineer when a finding or test result needs a design or acceptance-criteria change, at the pre-pr-review round limit, before the review budget is exceeded, and when a problem does not converge. It also stops before any build step when a sign-off is missing, and does not start the design itself.
  • Close. It runs the closing pre-pr-review steps, writes the marker in its own name and stops before push. The engineer opens the PR.

A .gitignore line re-includes the skill directory, because **/build-*/ would ignore it.

Motivation:

Today an engineer sets up the build, test and review sessions and the loop between them by hand for each change. The PROF-16588 build ran this flow manually; this skill writes it down.

Additional Notes:

  • Reference, not copy. The round limit, the Critical/High rules, the reviewer table and the budget stay in pre-pr-review; the skill links to its anchors, so the two cannot drift.
  • Pi runs the parts one after another in one session and calls no subagent tool, also when the pi-subagents extension provides one. Pi subagents, cost per sub-session and a regression drive of the whole loop are PROF-16614.
  • Test drives run without MCP servers and with only the tools their criterion needs. A gh stub on PATH refuses writes. Known gap, accepted as Low: a drive can still reach the real gh by its absolute path.
  • Accepted cost: the skill says when a review runs, so this PR and later changes to the skill are in the pre-pr-review gate row (Sphinx).
  • Review: Sphinx, standard effort, in a fresh context. The whole range had no findings. The PR bots' five findings were fixed, and the two fix ranges each got a Sphinx review: the first found two Low and one Info, which are fixed; the second found one Low. That review was the last round that pre-pr-review allows. Its Low stays open, accepted by Roman Kennke: an inconclusive check that the engineer accepts is not passed to S1 the way a blocked one is.
  • Human review is recommended, by @jbachorik, because the team will run every accepted design through this skill. No critical area is touched.

How to test the change?:

Check Result
python3 utils/check-skills.py; bash utils/tests/test_quality_check_scripts.sh passed: skills: OK (10 skills); PASS: 231 test groups
Fresh headless Claude Code, no MCP, prompt to implement a ticket with an accepted design, skill not named (3 runs) passed: loads build-test-review, neither cairn:dev-process nor sphinx:implement
Same, ticket without an accepted design (3 runs) passed: stops before any build step, names the missing sign-offs, starts no design
Fresh Pi session, without and with the subagent tool (3 runs each) passed: runs the parts one after another; starts no subagent child
One real run on a docs-only ticket (PROF-16652, #994), in an interactive session passed, on an earlier commit of this branch (afa873a), before the S2 drive limits and the review fixes: checklist written, four fresh subagent runs, one stop for an acceptance-criteria change, marker written, no push. Not exercised: review findings fed back to the build, and three of the four stops

The ticket has the evidence tables with commits and configurations.

For Datadog employees:

  • If this PR touches code that signs or publishes builds or packages, or handles
    credentials of any kind, I've requested a security review (run the dd:platform-security-review
    skill, or file a request via the PSEC review form).
    bewaire also runs automatically on every PR.
  • This PR doesn't touch any of that.
  • JIRA: PROF-16594

🤖 Generated with Claude Code

rkennke and others added 4 commits November 13, 2026 12:12
The skill turns a ticket with an accepted Design, acceptance criteria
and Build plan into a reviewed local branch. It writes a sub-session
checklist on the ticket and runs build, review and test as fresh
subagents. It stops for the engineer on design changes, the review
round limit, the budget and non-converging problems. Pi runs the
steps in one session.

.gitignore re-includes the skill directory, which **/build-*/ would
otherwise ignore.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…on (PROF-16594)

Pi can get subagents from an extension such as pi-subagents. This
version still runs the parts one after another in Pi.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A drive with pi-subagents called its tool to read the extension guide.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A trial-run drive had MCP servers and write tools, which the gh stub
does not cover.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rkennke
rkennke requested a review from a team as a code owner November 13, 2026 14:44
@rkennke
rkennke requested a review from jbachorik November 13, 2026 14:44
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 13, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-13T14:51:07.256314Z 009a0c0 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@dd-octo-sts

dd-octo-sts Bot commented Nov 13, 2026 •

Copy link
Copy Markdown
Contributor

Scan-Build Report

User:runner@runnervmwuk1x
Working Directory:/home/runner/work/java-profiler/java-profiler/ddprof-lib/src/test/make
Command Line:make -j4 all
Clang Version:Ubuntu clang version 21.1.8 (6ubuntu1)
Date:Fri Nov 13 16:11:50 2026

Bug Summary

Bug TypeQuantityDisplay?
All Bugs2
Logic error
Dereference of null pointer1
Unused code
Dead initialization1

Filter Results by File

Reports

Bug Group Bug Type ▾ File Function/Method Line Path Length
Unused codeDead initializationreferenceChains.cppapplyOomRamp4971
Logic errorDereference of null pointerperfEvents_linux.cppunregisterThread72026

@datadog-datadog-us1-prod datadog-datadog-us1-prod Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bits Code Review: FAIL

Two critical workflow gaps stand out: the pre-push hook installation step (step 0) is never invoked, so stale-review checks can be bypassed on subsequent pushes; and --allowedTools is used instead of --tools, leaving Write and Bash permissions active during test drives and defeating the required isolation.

Open Bits AI session

🤖 Bits Code Review · Commit 009a0c0

Comment on lines +78 to +79
Then run `pre-pr-review` steps 4 to 7 in this session. The S3 reviews are its
step 3 reviews, its step 4 fixes go through S1 as in step 4 above, and the marker

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Include the pre-push hook installation step

In a clone without the pre-push shim, this workflow never installs it: S1 invokes step 2, S3 invokes step 3, and Close invokes steps 4–7, omitting step 0. Writing the review marker does not install the hook. Consequently, later pushes to an open PR can bypass the stale-review check. Run the idempotent hook-installation step before completing the workflow.

Suggested change
Then run `pre-pr-review` steps 4 to 7 in this session. The S3 reviews are its
step 3 reviews, its step 4 fixes go through S1 as in step 4 above, and the marker
Then run `pre-pr-review` step 0 and steps 4 to 7 in this session. S3 supplies its
step 3 reviews, its step 4 fixes go through S1 as in step 4 above, and the marker

React: 👍 useful · 👎 wrong · 😕 unclear · 👀 right, but not acting on it

What each reaction means
  • 👍 Useful: correct, and you're fixing it or will.
  • 👎 Wrong: the finding is incorrect, for example the bug can't happen or the code was misread.
  • 😕 Unclear: you can't tell what it means or why it matters.
  • 👀 Right, not acting: correct, but intended, out of scope for this PR, a known risk, or too minor.

🤖 Bits Code Review · Open Bits AI session

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 5372adf: the close now runs pre-pr-review step 0 (install-hook) before steps 4 to 7.

- **S2 Test** runs the `test-drive` acceptance criteria in a fresh clone of the
candidate commit, never in the worktree. Each drive runs without MCP servers and
with only the tools that its criterion needs, for example `claude -p` with
`--strict-mcp-config` and `--allowedTools`. Never skip hooks or bypass

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Restrict available test-drive tools with --tools

--allowedTools adds permission rules; it does not restrict available tools. A drive inheriting this repository’s .claude/settings.json retains its configured Write and Bash permissions, even when only Read is listed. Such a drive can still modify files and execute commands, defeating the required isolation. Use --tools to restrict available tools, alongside permission rules for those retained.

Suggested change
`--strict-mcp-config` and `--allowedTools`. Never skip hooks or bypass
`--strict-mcp-config`, `--tools` and `--allowedTools`. Never skip hooks or bypass

React: 👍 useful · 👎 wrong · 😕 unclear · 👀 right, but not acting on it

What each reaction means
  • 👍 Useful: correct, and you're fixing it or will.
  • 👎 Wrong: the finding is incorrect, for example the bug can't happen or the code was misread.
  • 😕 Unclear: you can't tell what it means or why it matters.
  • 👀 Right, not acting: correct, but intended, out of scope for this PR, a known risk, or too minor.

🤖 Bits Code Review · Open Bits AI session

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 5372adf: drives use --tools to limit the available tools and --allowedTools to permit them, with --strict-mcp-config.

Comment on lines +59 to +61
4. Run S2 only after a review round that left no Critical or High finding open. A
failed check goes to a new S1 run like a finding, its fix goes to S3, and then S2
runs again.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Stop before closing on unverified test-drive results

When S2 reports blocked or inconclusive—for example, because the required harness is unavailable—the loop handles only failed checks, and none of the stops handles these unverified states. It consequently permits Close to tick the checklist and declare the branch ready without passing acceptance evidence. Stop for the engineer until the required results are verified.

Suggested change
4. Run S2 only after a review round that left no Critical or High finding open. A
failed check goes to a new S1 run like a finding, its fix goes to S3, and then S2
runs again.
4. Run S2 only after a review round that left no Critical or High finding open. A
failed check goes to a new S1 run like a finding, its fix goes to S3, and then S2
runs again. If a required S2 criterion is `blocked` or `inconclusive`, stop for
the engineer; do not proceed to Close without the required passing evidence.

React: 👍 useful · 👎 wrong · 😕 unclear · 👀 right, but not acting on it

What each reaction means
  • 👍 Useful: correct, and you're fixing it or will.
  • 👎 Wrong: the finding is incorrect, for example the bug can't happen or the code was misread.
  • 😕 Unclear: you can't tell what it means or why it matters.
  • 👀 Right, not acting: correct, but intended, out of scope for this PR, a known risk, or too minor.

🤖 Bits Code Review · Open Bits AI session

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 5372adf and d5b1b92: a new stop fires when a sub-session reports a required check as blocked, or as inconclusive after running it on the current candidate. The close waits until each required check has passed or the engineer accepts the gap.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 009a0c04a7

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +35 to +36
the kind of change, and the `pre-pr-review` step 2 self-checks. It commits
locally only when they pass, and it does not push. Its report names the commit

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Add a path for blocked local checks

When a required local check is legitimately blocked—for example, verify-profiler-change explicitly requires that status when Zing or a required runtime is unavailable—S1 cannot commit, while the loop assumes a candidate commit and the stop list has no first-time blocked-check case. The orchestration therefore stalls instead of reporting the supported blocked state; add a stop/decision path or allow a candidate commit carrying blocked evidence.

AGENTS.md reference: AGENTS.md:L488-L493

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 5372adf and d5b1b92: a blocked S1 check now stops for the engineer. S1 commits with a check that stays blocked only when its prompt quotes the engineer's acceptance. Otherwise it reports without a commit.

Then run `pre-pr-review` steps 4 to 7 in this session. The S3 reviews are its
step 3 reviews, its step 4 fixes go through S1 as in step 4 above, and the marker
names this session. For its step 7, use the sub-session reports and this
session's own mistakes. Do not push and do not open a PR: tell the engineer that

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reconcile evidence posting with the no-push close

On normal completion, the preceding instruction requires posting the evidence table before this line forbids pushing, but ticket-writing requires candidate commits and branches to be links and explicitly says an unpushed commit link does not resolve. Because S1 creates only local commits, the ticket cannot record compliant evidence here without violating one of the two instructions; defer the evidence until after a push or define a permitted publication step.

AGENTS.md reference: AGENTS.md:L488-L493

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 5372adf: the close names the unpushed commits by hash and adds the links after the engineer pushes, as ticket-writing allows ("push first, or add the links after the push").

@dd-octo-sts

dd-octo-sts Bot commented Nov 13, 2026 •

Copy link
Copy Markdown
Contributor

✅ All 40 integration tests passed

📊 Dashboard · 👷 Pipeline · 📦 d5b1b927

@datadog-datadog-us1-prod

datadog-datadog-us1-prod Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

Pipelines

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: d5b1b92 | Docs | Give us feedback!

@dd-octo-sts

dd-octo-sts Bot commented Nov 13, 2026 •

Copy link
Copy Markdown
Contributor

CI Test Results

Run: #43459899527 | Commit: 95cd61f | Duration: 19m 51s (longest job)

✅ All 32 test jobs passed

Status Overview

JDK glibc-aarch64/debug glibc-amd64/debug musl-aarch64/debug musl-amd64/debug
8 - ✅ - -
8-ibm - ✅ - -
8-j9 ✅ ✅ - -
8-librca - - ✅ ✅
8-orcl - ✅ - -
11 - ✅ - -
11-j9 ✅ ✅ - -
11-librca - - ✅ ✅
17 ✅ ✅ - -
17-graal ✅ ✅ - -
17-j9 ✅ ✅ - -
17-librca - - ✅ ✅
21 ✅ ✅ - -
21-graal ✅ ✅ - -
21-librca - - ✅ ✅
25 ✅ ✅ - -
25-graal ✅ ✅ - -
25-librca - - ✅ ✅

Legend: ✅ passed | ❌ failed | ⚪ skipped | 🚫 cancelled

Summary: Total: 32 | Passed: 32 | Failed: 0


Updated: 2026-11-13 16:32:52 UTC

rkennke and others added 2 commits November 13, 2026 16:02
- Run pre-pr-review step 0 at the close, so the pre-push hook is
  installed in a fresh clone.
- Limit test-drive tools with --tools; --allowedTools only permits.
- Stop when a required S1 or S2 check is blocked or inconclusive, and
  let S1 commit with a blocked check the engineer accepted.
- Name unpushed commits by hash and add the links after the push.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…6594)

S1 gets the engineer's acceptance of a blocked check in its prompt, and
the stop for blocked or inconclusive checks ignores results that are
only stale after a new commit. Rewrap two lines.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@datadog-datadog-us1-prod datadog-datadog-us1-prod Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bits Code Review: FAIL

The PR adds a ticket-driven build, review, and test workflow for accepted PROF designs. Tool isolation and hook installation are fixed, but one issue remains: S1 cannot commit after the engineer accepts an inconclusive check because its prompt and commit rule only honor accepted blocked checks.

Open Bits AI session

🤖 Bits Code Review · Commit d5b1b92

Comment on lines +29 to +40
triaged findings or the failed checks, quoted, and any `blocked` check that the
engineer accepted (step 5). Never give your own view of the
change or of its defects. Tell the sub-session to read its part on the ticket, to
write nothing to the ticket, and to return a report.
- **S1 Build** changes the code. It does not start another orchestration skill,
such as the cairn `dev-process` pipeline or `sphinx:implement`. It runs the
`local` acceptance criteria, the checks that `verify-profiler-change` names for
the kind of change, and the `pre-pr-review` step 2 self-checks. It commits
locally only when they pass, or when its prompt quotes the engineer's
acceptance of a check that stays `blocked`. Otherwise it reports without a
commit. It does not push. Its report names the commit and each check as
`passed`, `failed`, `blocked` or `inconclusive`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Allow S1 to honor accepted inconclusive checks

When S1 reports a required check as inconclusive, step 5 allows the engineer to accept the evidence gap. However, the sub-session prompt forwards only accepted blocked checks, and S1’s commit exception likewise covers only blocked results. The implementation therefore remains uncommitted despite the engineer’s acceptance, preventing review and marker creation for that candidate. Honor accepted inconclusive results in both places.

Suggested change
triaged findings or the failed checks, quoted, and any `blocked` check that the
engineer accepted (step 5). Never give your own view of the
change or of its defects. Tell the sub-session to read its part on the ticket, to
write nothing to the ticket, and to return a report.
- **S1 Build** changes the code. It does not start another orchestration skill,
such as the cairn `dev-process` pipeline or `sphinx:implement`. It runs the
`local` acceptance criteria, the checks that `verify-profiler-change` names for
the kind of change, and the `pre-pr-review` step 2 self-checks. It commits
locally only when they pass, or when its prompt quotes the engineer's
acceptance of a check that stays `blocked`. Otherwise it reports without a
commit. It does not push. Its report names the commit and each check as
`passed`, `failed`, `blocked` or `inconclusive`.
triaged findings or the failed checks, quoted, and any `blocked` or
`inconclusive` check that the engineer accepted (step 5). Never give your own
view of the change or of its defects. Tell the sub-session to read its part on
the ticket, to write nothing to the ticket, and to return a report.
- **S1 Build** changes the code. It does not start another orchestration skill,
such as the cairn `dev-process` pipeline or `sphinx:implement`. It runs the
`local` acceptance criteria, the checks that `verify-profiler-change` names for
the kind of change, and the `pre-pr-review` step 2 self-checks. It commits
locally only when they pass, or when its prompt quotes the engineer's
acceptance of a check that stays `blocked` or `inconclusive`. Otherwise it
reports without a commit. It does not push. Its report names the commit and
each check as `passed`, `failed`, `blocked` or `inconclusive`.

React: 👍 useful · 👎 wrong · 😕 unclear · 👀 right, but not acting on it

What each reaction means
  • 👍 Useful: correct, and you're fixing it or will.
  • 👎 Wrong: the finding is incorrect, for example the bug can't happen or the code was misread.
  • 😕 Unclear: you can't tell what it means or why it matters.
  • 👀 Right, not acting: correct, but intended, out of scope for this PR, a known risk, or too minor.

🤖 Bits Code Review · Open Bits AI session

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, and known: the last Sphinx fix-range review found the same gap. Roman Kennke accepted it as an open Low, with no further review rounds in this PR, so it is not fixed here. The PR description lists it.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant