Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
826d332
red-team: area 15 (legacy pure-R search API), first-ever review
ms609 Aug 5, 2026
eb6e26c
red-team: area 15 opus pass, and the tier-economics result
ms609 Aug 5, 2026
7ec9357
chore(agents): post as ms609-agent, not as the maintainer
ms609-agent Aug 6, 2026
e060c30
red-team: move area 15's round records to Discussions
ms609-agent Aug 6, 2026
07c2790
docs(process): hard-code the Discussions, identity and grouping rules
ms609-agent Aug 6, 2026
5ccc1bf
Merge pull request #182 from ms609/cpp-search
ms609 Aug 18, 2026
932dfc4
In production
ms609 Aug 21, 2026
f3bfc99
Merge remote-tracking branch 'upstream/cpp-search' into sync/cpp-sear…
ms609 Aug 21, 2026
1de1000
Merge pull request #149 from agent-issues/chore/agent-github-identity
ms609 Aug 22, 2026
e955f1e
Merge cpp-search into the Discussions/identity docs branch
ms609-agent Aug 22, 2026
92a67ce
Merge cpp-search into the area-15 branch
ms609-agent Aug 22, 2026
8e5d547
docs(red-team): retire last_focus now the backfill is complete
ms609-agent Aug 22, 2026
228177e
docs(red-team): the log.md header still described last_focus rotation
ms609-agent Aug 22, 2026
0768b4e
fix(search): report 0 rearrangements when maxIter = 0
ms609-agent Aug 22, 2026
232164c
docs(red-team): cut the archaeology from the area 14 and 15 scope rows
ms609-agent Aug 22, 2026
63b7e70
fix(search): don't announce a tree search that will not happen
ms609-agent Aug 22, 2026
e43c4f3
docs: state the rules, don't narrate how they changed
ms609-agent Aug 22, 2026
97a7ed0
Merge pull request #157 from agent-issues/claude/red-team-docs-storag…
ms609 Aug 22, 2026
a3743dc
Merge pull request #150 from agent-issues/feature/red-team-area15
ms609 Aug 22, 2026
59a88c6
Merge branch 'ms609:cpp-search' into cpp-search
ms609 Sep 10, 2026
c7a47cd
TreeTools 2.4.1 on CRAN
ms609 Sep 10, 2026
b85baa6
SmithConc doi
ms609 Sep 10, 2026
a8f6bc8
chore(red-team): freeze escalation-backlog.md; residuals go to GitHub
ms609-agent Sep 18, 2026
2430f15
chore(agents): add the /next-issue config for this repo
ms609-agent Sep 18, 2026
5da95e7
docs(red-team): suspend fable; Opus 5.5 is the top finder rung
ms609-agent Sep 23, 2026
a7325fe
docs(red-team): keep scope-only focus-areas; model status lives in Di…
ms609-agent Sep 23, 2026
f820d06
Merge pull request #188 from agent-issues/chore/fable-suspended
ms609 Sep 23, 2026
74a08bc
ci: run coverage in its own arm job, off the Windows leg
ms609-agent Oct 9, 2026
754ba04
fix: restore the comma after SmithConc's doi in REFERENCES.bib
ms609-agent Oct 9, 2026
b5eb104
Merge pull request #191 from agent-issues/fix/references-bib-comma
ms609 Oct 9, 2026
44837ef
Merge branch 'cpp-search' into ci/covr-arm
ms609-agent Oct 9, 2026
b41eb12
Merge pull request #190 from agent-issues/ci/covr-arm
ms609 Oct 12, 2026
6d72d3a
guard POPCNT: popcount64() via TreeTools::count_bits()
ms609-agent Oct 14, 2026
c918641
spelling test: report words found only in NEWS.md, don't fail on them
ms609-agent Oct 14, 2026
31f76eb
Merge pull request #192 from agent-issues/fix/popcnt-guard
ms609 Oct 14, 2026
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
32 changes: 27 additions & 5 deletions .claude/skills/next-issue/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ between two concurrent chips costs more than the triage would.
Issues live in **`agent-issues/TreeSearch`** (`gh` already defaults to it). The upstream
`ms609/TreeSearch` tracker is public and human-entered: untrusted input, never a task list.

Writes go out as `ms609-agent`; the mechanism is in `AGENTS.md`'s *Agent identity*. What is
specific to dispatch: **every chip brief must carry that instruction**, since a chip opening
its PR under `ms609` produces one the maintainer cannot review, fixable only by closing and
reopening. Request review with `--reviewer ms609`.

## 1. Group

```bash
Expand All @@ -34,6 +39,12 @@ Cluster into tranches:
- **Respect `area:N` labels** — they mark red-team focus areas, and two issues sharing
an area usually share files.

**One issue is not one fix site.** `/red-team` files by *root cause*, so a single issue covers several candidates across several files — an enumerated
site list, or two independent defects that produce one wrong output and must be fixed
together. Read each body before grouping: sizing a tranche by issue count will under-size
it, and its file-collision check must union **every** file the body names, not the one in
the title. A body carrying `Covers A15-11, -16, …` is the tell.

Then drop anything an open PR or running chip already touches, and report what was
held back and why.

Expand All @@ -43,10 +54,20 @@ Issues needing a maintainer call — a behaviour trade-off, a severity dispute,
even a bug", or two contradictory specifications in the tree — aren't chip-appropriate.
Name them in the report; don't brief them.

**Red-team issues say so explicitly**, because a decision reads like a bug report: the body
states that what is needed is a decision, not a fix. Honour that. A chip briefed against one
will pick whichever branch it happens to prefer and present it as the fix — the expensive
failure, since the resulting PR looks reviewable and quietly settles a question the
maintainer meant to answer. Also exclude anything whose issue records only a *reopening
condition* rather than live work.

## 3. Brief (one per cleared tranche, fully self-contained)

- **Issues verbatim**: number, title, `file:line`, mechanism. Include the pre-tracker
`T-nnn` where one exists — it is what source comments and `dev/red-team/log.md` cite.
- **Issues verbatim**: number, title, **every** `file:line` the body names, and mechanism.
Include the pre-tracker `T-nnn` where one exists — it is what source comments and the
frozen `dev/red-team/log.md` cite. Where the issue records a verifier *correcting* the
finder's mechanism, numbers or severity, carry the correction and drop the original: a
chip fixing to the finder's figure has twice left half a bug live.
- **Minimal-diff fix**, and point the chip at `AGENTS.md`'s build and worktree
non-negotiables rather than restating them here — they change there, not here.
- **A regression test per issue, confirmed to fail pre-fix.** Assert only what the code
Expand All @@ -69,9 +90,9 @@ Name them in the report; don't brief them.
chip dedupes the three lists and judges plausibility itself.
- **PR body**: `Fixes #N` per issue. **This only closes the issue on merge into
`cpp-search`**, the fork's default branch — target anything else and the issue stays
open silently.
open silently. Open it as `ms609-agent` with `--reviewer ms609`.
- **Claim each issue** before starting: add the `in-progress` label and a comment naming
the branch, so a parallel chip can see it is taken.
the branch (as `ms609-agent`), so a parallel chip can see it is taken.
- **Last step**: `mcp__ccd_session_mgmt__archive_session` with `session_id: "self"`.
- Branch from `cpp-search` unless a genuine code dependency forces a stack.
- Comments per `AGENTS.md`'s conventions and the `r-conventions` rubric — a comment only
Expand All @@ -86,7 +107,8 @@ Name them in the report; don't brief them.
- **Sonnet** — guard clauses, dead code, R-level fixes, tests, local refactors.
- **Opus** — `src/` kernels, scoring semantics (Fitch/IW/profile/HSJ/XFORM), constraint
machinery, parallelism and RNG, `NAMESPACE`, cross-file mechanism fixes.
- **Fable** — only after an Opus chip in this tranche has stalled twice.
- **Fable** — suspended while Opus 5.5 outclasses it (2026-09-23); never dispatch it. An Opus
chip that stalls twice is reported back, not escalated.

Effort — **reasoning depth, not task size**:

Expand Down
89 changes: 77 additions & 12 deletions .github/workflows/R-CMD-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,12 @@ name: R-CMD-check

# Waves:
# sense-check -> arm (cheapest), always runs, never cancelled. Fast signal.
# core -> Windows (+codecov) / R 4.1 / R devel; only if sense-check passed.
# core -> Windows / R 4.1 / R devel; only if sense-check passed.
# coverage -> covr on arm (cheapest); alongside core.
# shiny -> EasyTrees shinytest2 suite, Windows; only if the app changed
# and sense-check passed. Non-blocking (continue-on-error) until
# its stability on CI is established.
# full -> macOS x2 backstop; only once core is green.
# full -> macOS x2 backstop; only once core and coverage are green.
jobs:
# ---------------------------------------------------------------------------
# Wave 1: cheapest leg as a fail-fast sense-check. No concurrency group, so a
Expand Down Expand Up @@ -164,7 +165,7 @@ jobs:
- '.github/workflows/R-CMD-check.yml'

# ---------------------------------------------------------------------------
# Wave 2: Windows (+codecov), R 4.1, R devel. Runs only if the sense-check
# Wave 2: Windows, R 4.1, R devel. Runs only if the sense-check
# passed. Per-leg concurrency so a superseding push cancels in-flight legs.
# ---------------------------------------------------------------------------
core:
Expand All @@ -191,7 +192,6 @@ jobs:
R_COMPILE_AND_INSTALL_PACKAGES: 'never'
R_REMOTES_NO_ERRORS_FROM_WARNINGS: true
RSPM: ${{ matrix.config.rspm }}
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}

steps:
Expand Down Expand Up @@ -222,13 +222,12 @@ jobs:
run: |
sudo apt-get install texlive-latex-base texlive-fonts-recommended

- name: Set up R dependencies (covr)
- name: Set up R dependencies (Windows)
uses: r-lib/actions/setup-r-dependencies@v2
if: runner.os == 'Windows'
with:
needs: |
check
coverage
# Coreset url:: -- this is the Windows leg, so it cannot use the Linux
# tarball the `runner.os != 'Windows'` step below selects. Without a
# url:: reference the solve fails outright ("Can't find package called
Expand Down Expand Up @@ -270,12 +269,78 @@ jobs:
- name: Check package
uses: r-lib/actions/check-r-package@v2

- name: Notify on failure
if: failure() && github.event_name == 'schedule'
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: 186,
body: 'Scheduled workflow has failed: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}'
});

# ---------------------------------------------------------------------------
# Wave 2, alongside core: code coverage on the cheapest runner. covr compiles
# its own instrumented build and runs the whole suite, so it is a job of its
# own rather than a step after some leg's R CMD check. Dependency setup
# mirrors the sense-check: same pinned snapshot, same prebuilt Coreset.
# ---------------------------------------------------------------------------
coverage:
needs: sense-check
runs-on: ubuntu-24.04-arm
name: coverage (ubuntu-24.04-arm, release)

concurrency:
group: ${{ github.workflow }}-coverage-${{ github.ref }}
cancel-in-progress: true

env:
R_COMPILE_AND_INSTALL_PACKAGES: 'never'
R_REMOTES_NO_ERRORS_FROM_WARNINGS: true
RSPM: "https://packagemanager.posit.co/cran/__linux__/noble/2026-07-30"
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}

steps:
- name: Checkout git repo
uses: actions/checkout@v6

- name: Set up R
uses: r-lib/actions/setup-r@v2
with:
r-version: release

- name: Set up R dependencies
uses: r-lib/actions/setup-r-dependencies@v2
with:
needs: |
coverage
extra-packages: |
shinytest2=?ignore
url::https://ms609.github.io/packages/bin/linux/aarch64-release/Coreset_latest.tar.gz

- name: Code coverage
if: runner.os == 'Windows'
# quiet = FALSE streams the instrumented test run to the job log, so a
# test that fails only under covr shows its failure, not a temp path.
# The per-file summary and line tally keep the result readable where
# the Codecov upload has no token.
run: |
covr::codecov()
cov <- covr::package_coverage(quiet = FALSE)
print(cov)
saveRDS(covr::tally_coverage(cov, by = "line"), "coverage-lines.rds")
covr::codecov(coverage = cov)
shell: Rscript {0}

- name: Upload line coverage
uses: actions/upload-artifact@v4
with:
name: coverage-lines
path: coverage-lines.rds
retention-days: 14

- name: Notify on failure
if: failure() && github.event_name == 'schedule'
uses: actions/github-script@v7
Expand Down Expand Up @@ -354,12 +419,12 @@ jobs:
retention-days: 14

# ---------------------------------------------------------------------------
# Wave 3 (backstop): the expensive macOS legs. Only runs once the core wave is
# green, which in practice is "about to merge". macOS is ~10x runner-minutes,
# so keeping it off every push is the big save.
# Wave 3 (backstop): the expensive macOS legs. Only runs once the core wave
# and coverage are green, which in practice is "about to merge". macOS is
# ~10x runner-minutes, so keeping it off every push is the big save.
# ---------------------------------------------------------------------------
full:
needs: core
needs: [core, coverage]
runs-on: ${{ matrix.config.os }}
name: ${{ matrix.config.os }} (${{ matrix.config.r }})

Expand Down
65 changes: 55 additions & 10 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ collaborators.
|-------|---------|
| `red-team` | Filed by `/red-team`. Also that skill's mode switch — don't delete it |
| `sev:high` / `sev:med` / `sev:low` | Former P1 / P2 / P3 |
| `area:1`…`area:15` | Which area **owns the code**, per `dev/red-team/focus-areas.md` — not which round found it; an issue may carry several |
| `task` | Planned work migrated from the retired `to-do.md` |
| `area:1`…`area:15` | Which area **owns the code**, per `dev/red-team/focus-areas.md` — not which round found it; an issue may carry several. **Count the rows, this range grows** |
| `task` | Planned work, not a red-team finding |
| `deferred` | Assessed and parked; not scheduled |
| `chore` | Infrastructure / process work |
| `in-progress` | Claimed; the claiming comment names the branch |
Expand All @@ -39,6 +39,52 @@ means this repo and upstream numbers separately. Pre-tracker `T-nnn` ids are **f
retired**: they persist in shipped source comments and in `dev/red-team/log.md`, and
`dev/red-team/migration-map*.tsv` resolve them.

### Agent identity — commit and post as `ms609-agent`, never as the maintainer

Agent work is attributed to the machine account **`ms609-agent`**, a collaborator on
`agent-issues`. This is not cosmetic: GitHub will not let an account approve its own PR, so a
PR opened as `ms609` **cannot be reviewed by `ms609`**. Posting as the machine account is what
makes review possible at all.

Two different mechanisms, both applied **per command** — never change the global git config or
`gh auth`, which belong to the human and must keep working interactively.

**Commits.** Author/committer is free text in the commit object; GitHub links it to an account
by matching a verified email. Pass it inline:

```bash
git -c user.name="ms609-agent" -c user.email="313734811+ms609-agent@users.noreply.github.com" commit -F - <<'MSG'
...
MSG
```

**Issues, PRs, comments, labels.** A PR's author is *whichever account authenticated the API
call* — there is no per-PR override, so this is the only way to change it. `gh` reads
`GH_TOKEN` in preference to stored auth, so prefix the single call:

```bash
GH_TOKEN=$CLAUDE_GH_TOKEN gh pr create --base cpp-search --head feature/<name> --title "..." --body-file <file>
```

The same prefix goes on every `gh issue create`, `gh issue comment` and `gh issue edit`. Do
**not** export `GH_TOKEN` for the session — that would silently re-identify anything the human
runs in the same shell.

**Pushes stay as the human's credentials.** Push identity has no bearing on PR authorship, so
`git push` needs no change.

**`gha-dispatch.sh` / `gha-poll.sh` stay as the human too** — dispatching a workflow needs an
`actions: write` scope the agent token is not required to carry. Run them unprefixed.

If `$CLAUDE_GH_TOKEN` is unset, **stop and say so** rather than silently falling back to the
maintainer's identity — a PR that lands under the wrong account cannot be re-attributed
afterwards, only closed and reopened.

> **Other projects need their own answer.** This works because `agent-issues` is free to add
> collaborators. An org billing a paid seat per member (e.g. StratoBayes) cannot absorb a
> machine account this way; there the options are a GitHub App installation, which is not a
> billable member, or accepting single-identity working without the review step.

### GHA dispatch (primary validation path)

Checks run in the **fork's** Actions. Workflows are disabled on a new fork until enabled
Expand Down Expand Up @@ -68,10 +114,9 @@ bash C:/Users/pjjg18/GitHub/gha-poll.sh <run_id>
```

Both scripts resolve the target repo with `gh repo view --json nameWithOwner`, so they pick
up whatever `gh repo set-default` points at — the fork. **Do not `cd ..` first** (as this
recipe used to say): outside a git repo that lookup fails and the dispatch targets nothing.
"Run these FROM the repo" means your `cwd` must be the git checkout/worktree doing the
`gh repo view` lookup — it does not mean the scripts themselves must be found relatively.
up whatever `gh repo set-default` points at — the fork. **Do not `cd ..` first**: outside a git repo that lookup fails and the
dispatch targets nothing. Your `cwd` must be the git checkout or worktree — the scripts
themselves are found by absolute path, not relatively.

### Local builds (targeted iteration only)

Expand Down Expand Up @@ -167,8 +212,7 @@ agent-issues/TreeSearch
### Rules

- **Agents never push to the fork's `cpp-search` directly** — everything lands by reviewed
PR, documentation included. The old coordination-commit exception is gone with the files
that justified it.
PR, documentation included.
- **`feature/*`** branches from `cpp-search`, owned by one agent at a time.
- **Never commit directly to upstream `cpp-search`.** While upstream only ever *receives*
the fork's trunk, every sync is a fast-forward — no merge, no conflict on
Expand All @@ -195,7 +239,7 @@ agent-issues/TreeSearch
5. On GHA success, open a PR — `Fixes #N` per issue, and `--base cpp-search` so the
closing actually fires:
```bash
gh pr create --base cpp-search --head feature/<name> --title "<description>" --body "Fixes #N ..."
GH_TOKEN=$CLAUDE_GH_TOKEN gh pr create --base cpp-search --head feature/<name> --title "<description>" --body "Fixes #N ..."
```
6. Human reviews and merges. The merge closes the issues; nothing to update by hand.
7. After merge, clean up:
Expand Down Expand Up @@ -246,7 +290,8 @@ These recur; they are activities, not issues, and have no tracker entry:
| File | Purpose |
|------|---------|
| **GitHub issues** (`agent-issues/TreeSearch`) | The task queue and the findings tracker |
| `dev/red-team/` | Rotation state: `focus-areas.md`, `log.md`, frozen `findings-archive.md`, `migration-map*.tsv` |
| **GitHub Discussions**, one category per `area:N` | Red-team round records. `dev/red-team/log.md` is **closed to new entries** — it keeps only the model-version legend and the frozen pre-2026-08 history |
| `dev/red-team/` | Scope and tiers: `focus-areas.md`; frozen `log.md`, `findings-archive.md`, `migration-map*.tsv` |
| `dev/strategy.md` | Historical strategic narrative (was `coordination.md`; **not** kept current) |
| `completed-tasks.md` | **Frozen.** Pre-tracker decisions worth not re-litigating; still worth grepping |
| `dev/expertise/*.md` | Standing-practice methodology references |
Expand Down
7 changes: 4 additions & 3 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,8 @@ Imports:
Rdpack (>= 0.7),
stats,
TreeDist (>= 2.6.3),
TreeTools (>= 2.4.0.9002),
TreeTools (> 2.4.1),
utils,
Remotes: ms609/TreeTools,
Suggests:
cluster,
Coreset,
Expand Down Expand Up @@ -145,7 +144,9 @@ Collate:
RdMacros: Rdpack
LinkingTo:
Rcpp,
TreeTools,
TreeTools (> 2.4.1),
Remotes:
ms609/TreeTools,
SystemRequirements: C++17
LazyData: true
ByteCompile: true
Expand Down
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# To integrate into 2.0.0 notes

- C++ code no longer executes the x86 POPCNT instruction on CPUs that lack
it, which crashed R with "illegal operation" on some virtual machines
(ms609/TreeTools#287). Requires TreeTools > 2.4.1.

- New `Bremer()` calculates Bremer (decay) support for each clade of a reference
tree.

Expand Down
10 changes: 6 additions & 4 deletions R/CustomSearch.R
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ EdgeListSearch <- function (edgeList, dataset,
bestScore <- edgeList[[3]]
}
}
if (verbosity > 0L) {
if (verbosity > 0L && maxIter > 0L) {
message(" - Performing tree search. Initial score: ", bestScore) #nocov
}
if (!is.null(stopAtScore) && bestScore < stopAtScore + epsilon) {
Expand All @@ -59,8 +59,8 @@ EdgeListSearch <- function (edgeList, dataset,
}
hits <- 0L
unimprovedSince <- 0L
for (iter in 1:maxIter) {

for (iter in seq_len(maxIter)) {
candidateLists <- RearrangeEdges(edgeList[[1]], edgeList[[2]],
dataset = dataset,
TreeScorer = TreeScorer,
Expand Down Expand Up @@ -107,7 +107,9 @@ EdgeListSearch <- function (edgeList, dataset,
}
if (verbosity > 0L) { #nocov start
message(" - Final score ", bestScore, " found ", hits, " times after ",
iter, " rearrangements.", if (verbosity > 1L) "\n" else "")
# `for` leaves the loop variable NULL when maxIter < 1
if (maxIter > 0L) iter else 0L,
" rearrangements.", if (verbosity > 1L) "\n" else "")
} #nocov end

edgeList[3:4] <- c(bestScore, hits)
Expand Down
Loading