Skip to content

No Box can target a base branch that is not the trunk, so run 4 cannot merge to integration/dlc #505

Closed

Description

@orioltf

Question

Act 1 of run 4 merges to a long-lived integration/dlc branch, by the two-act delivery decided while charting #498 and kept on 2026-09-17 (comment). No Box can target it. What changes so that one can, and how does the base rule end up stated once?

What is wrong today

Measured on develop at 38bef0de.

  • unic-dlc-build.yaml, unic-dlc-qa.yaml and unic-dlc-pr-review.yaml each compute expected_base in bootstrap from project.branching: develop when gitflow, else main. No value can name a third branch.
  • unic-dlc-build.yaml already reads a second answer. Its verify node diffs against Archon's $BASE_BRANCH, while open-pr and code-review in the same Box read expected_base. Nothing checks that the two agree.
  • unic-dlc-pr-review.yaml takes its review diff from the merge-base with expected_base. A wrong base reads correctly until develop moves, and then the review reads the wrong diff and reports nothing.
  • integration/dlc does not exist on the Consumer's remote (measured 2026-10-21).

Decisions (maintainer, 2026-10-21)

  1. The one source of a run's base branch is Archon's $BASE_BRANCH. No DLC config key. Archon resolves it from archon workflow run --base <branch>, then worktree.baseBranch in .archon/config.yaml, then the codebase's stored default branch, then git (variables reference at v0.12.1). --base exists since Archon 0.7.1 (coleam00/Archon#2203), so this holds on 0.10.1 and on 0.12.1. Run 4 dispatches every act-1 Box with --base integration/dlc and edits no committed file in the Consumer.
  2. project.branching stops naming the base. It keeps one job in the Boxes: whether /qa deletes the merged feature/* branch after the merge.
  3. The review diff reads the PR's own target branch when the tracker returns a PR, because that is the diff that will merge. With no queryable PR it reads $BASE_BRANCH. When both exist and differ, it prints a warning naming both and carries on.
  4. /setup stays verify-only on .archon/config.yaml. It reports the base Archon will resolve and warns when it is missing or disagrees with branching. It writes nothing there, as commands/setup.md already rules for that file.
  5. Who creates integration/dlc stays with #502: cut by hand from the develop commit frozen for run 4, before dispatch. --base refuses a branch missing on the remote, so no Box can create it.
  6. This ticket lands before #439. Here open-pr changes by one token; bug(unic-archon-dlc): open-pr precedes its gate, and a config-value gate has no safe middle #439 restructures open-pr and rebases onto this ticket, keeping $BASE_BRANCH as its target. bug(unic-archon-dlc): open-pr precedes its gate, and a config-value gate has no safe middle #439 carries a native "blocked by" relation on this ticket, so the order holds whoever is assigned.
  7. docs/boxes/unic-dlc-build.md's hard-coded "base develop" is fixed here, not in #499.

Acceptance criteria

All paths are under apps/claude-code/unic-archon-dlc/.

The measurement comes first

  1. Before any Box changes, a spike on Archon 0.12.1, run by path with an isolated ARCHON_HOME in a throwaway repository, as #520's criterion 1 does, measures five things and posts the commands and their output as a comment on this ticket:

    1. With --base <branch>, a prompt node sees $BASE_BRANCH as that branch, and the worktree is cut from it.
    2. After an approval gate is approved, the resumed run still sees the same $BASE_BRANCH.
    3. With a --base branch missing on the remote, the run fails before its first node with an error that names the branch.
    4. With no queryable PR and a base branch that has diverged from develop, unic-dlc-pr-review takes the $BASE_BRANCH fallback of criterion 4, and its changed-file list holds only the feature branch's files. This measures the fallback only. The PR-target path is proven in the Consumer before run 4, under #502.
    5. With --from <feature-branch> --base <branch> together, Archon accepts both, a prompt node sees $BASE_BRANCH as the --base value, and the worktree is cut from the feature branch.

    If 1, 2, 3 or 5 fails, the implementation stops and the ticket returns to grilling. If 4 fails, the fix for the review diff is wrong and is corrected before merge.

The Boxes

  1. In unic-dlc-build.yaml, unic-dlc-qa.yaml and unic-dlc-pr-review.yaml, no node computes, outputs or reads expected_base. Every line that names the base reads $BASE_BRANCH, except the review diff in criterion 4. This covers lines the body does not list, such as the bootstrap fallback text, the code-review fixed point and the post-merge checkout.
  2. No Box states the rule "develop when gitflow, else main", in any wording.
  3. unic-dlc-pr-review.yaml takes its review diff from the merge-base with the PR's target branch when the tracker returns a PR, from $BASE_BRANCH when it does not, and prints a warning naming both when both exist and differ.
  4. unic-dlc-qa.yaml's verify-pr-base compares the PR's target with $BASE_BRANCH, and merge-gate and merge still fail closed on base_ok != 'true'. A /qa dispatched without --base against a PR that targets integration/dlc therefore refuses to merge.
  5. unic-dlc-qa.yaml still reads project.branching, and only to decide whether to delete the merged feature/* branch.
  6. The message of each bootstrap in the three Boxes names the base branch this run uses.

/setup and the documentation

  1. commands/setup.md reads the base Archon will resolve from .archon/config.yaml and the codebase default, reports it in Step 8 next to the remote line, and warns, with the line to add, when worktree.baseBranch is unset or disagrees with what branching implies. It writes nothing to .archon/config.yaml.
  2. Outside commands/setup.md, every statement of the base rule in the plugin is removed or points at $BASE_BRANCH and commands/setup.md. This covers README.md's project.branching row, docs/boxes/unic-dlc-build.md, docs/boxes/unic-dlc-qa.md and docs/boxes/unic-dlc-pr-review.md, and any other place where it turns up.
  3. A new plugin ADR, slug base-branch-is-archons-base-branch, records decisions 1 to 4: why $BASE_BRANCH and not a DLC key, what project.branching still does, and why the review diff reads the PR's target. Its number is taken when it is written, because #520 also adds a plugin ADR. Status Accepted (YYYY-MM-DD). It cites ADR-0023, whose code-review row names expected_base, and that row is revised inline under the convention in docs/adr/README.md.
  4. CHANGELOG.md carries a ### Breaking entry: the Boxes read the base from Archon's $BASE_BRANCH, so a Consumer whose Archon base differs from what branching implied now targets the Archon base. The entry tells the Consumer to run /unic-archon-dlc:setup and read its base line. The plugin bumps minor, never major.

What does not change

  1. No diagram under docs/architecture/ goes stale. None of their JSON files names the base rule or expected_base, and the /qa one says "checks the PR base", which stays true. An implementer satisfies this criterion by changing nothing, on purpose.
  2. commands/cleanup.md and unic-dlc-explore.yaml keep their reads of project.branching. One uses it as a hint for the main branch, the other for branch naming, and neither names a run's base.

Out of scope

Activity

  1. added
    bugSomething isn't working
    needs-specsEnough info from reporter; ready to write a spec
    p1High priority
    wayfinder:grillingWayfinder ticket: decide it by grilling
    on Sep 17, 2026
  2. orioltf commented on Sep 17, 2026

    @orioltf
    MemberAuthor

    The decision this ticket waited on is taken, 2026-09-17 23:35 CEST. The maintainer keeps act 1 on integration/dlc, as an exception for now, so this ticket stays the seventh precondition of #502 and is grilled as such. Recorded on #498 § Decisions so far. The § Not decided items in this body are unchanged: config key or single source, and whether branching is the right axis.

  3. orioltf commented on Oct 21, 2026

    @orioltf
    MemberAuthor

    Stale — do not follow. This opener was for the grilling, which is done. The implementation opener is posted below.

    Opener — How to start this session (written 2026-10-21 by unic-sdlc-orchestrator-6, at dispatch)

    What this session produces

    Approved acceptance criteria in this ticket's body, then the label ready-for-agent. Nothing else. The Box, command and documentation edits are implemented afterwards under /afk-loop, not here.

    Start: the maintainer types /wayfinder 373 #505. When the grilling starts, the maintainer types /grill-with-docs. Both carry disable-model-invocation, so the session cannot invoke them itself.

    Do not close this ticket. This overrides /wayfinder step 4, which closes a decision ticket. This stream grills a ticket into its own criteria and implements it under the same number (maintainer, 2026-09-29). Do not invoke /implement, /tdd or /to-tickets.

    Read in this order

    1. Comment 5721568351 comes before the body: act 1 of run 4 keeps integration/dlc, as an exception for now. Do not reopen that decision.
    2. The body. Its line numbers were measured at fd9739e. On develop at 38bef0de the six Box lines still hold; README.md:172 is now the project.branching row near line 315. Read the files, not the line numbers.
    3. #498, the section that splits the merge into two acts, and its Decisions-so-far entry for 2026-09-17 23:35. They say why the run targets a branch that is not the trunk, and what a reset of that branch costs.
    4. #502 comment 6289457445: run 4 targets the newest Archon release at freeze time, 0.12.1 today. This Mac runs 0.10.1.
    5. docs/research/2026-10-21-archon-workflow-extensibility.md § 2. It lists $BASE_BRANCH as an engine variable fed by worktree.baseBranch in .archon/config.yaml.
    6. In apps/claude-code/unic-archon-dlc/: the bootstrap node of unic-dlc-build.yaml, unic-dlc-qa.yaml and unic-dlc-pr-review.yaml; open-pr and the verify node in unic-dlc-build.yaml; verify-pr-base, merge-gate, merge and the post-merge cleanup step in unic-dlc-qa.yaml.

    The trap that costs an hour

    Adding a project.base_branch key, threading it through the three bootstrap nodes, and calling the rule single-sourced. Archon already has a base-branch source. unic-dlc-build.yaml uses it today: its verify node runs git diff --name-only $BASE_BRANCH...HEAD, while open-pr in the same Box targets $bootstrap.output.expected_base. So one Box already reads two answers to "what is the base", from two sources, and nothing checks that they agree. A new DLC key makes three. Whatever the criteria choose, they say which source every base-reading line in every Box reads, including the ones the body does not list.

    What this ticket does not decide yet

    Each of these is a question for the maintainer. None is yours to settle with a plausible default.

    • The source. A DLC config key, Archon's $BASE_BRANCH, or a key that bootstrap validates against $BASE_BRANCH. Each one changes who sets the base and how often. worktree.baseBranch is committed in the Consumer's .archon/config.yaml and applies to every run there, and run 4 needs integration/dlc for one run only.
    • Whether --from or a per-run --config sets $BASE_BRANCH. Unmeasured. If a criterion depends on it, it names a spike on Archon 0.12.1, run by path with an isolated ARCHON_HOME, the way #520's criterion 1 does. A measurement on 0.10.1 does not carry over.
    • Whether project.branching keeps the job of naming the base. The body's second question. unic-dlc-qa.yaml also reads branching to decide whether to delete the merged feature/* branch after the merge, so the key does not go away even if it stops naming the base.
    • Who creates integration/dlc, and from which commit. #502 owns it today. Measured 2026-10-21: the branch does not exist on the Consumer's remote.
    • Where a new key lives, if there is one. #520 decided three config layers, and #647 builds them later. Say which layer the key belongs to, and that this ticket does not wait for Build the layered Practice Pack config: DLC defaults, pack defaults, Consumer overrides #647.
    • Which lands first, this ticket or #439. Both edit open-pr in unic-dlc-build.yaml. The body asks for the order to be decided here and stated in the criteria.

    Other traps

    • This repository is public, and its issues are too. Name no client, no Consumer repository, no city, sector or product. Write "the Consumer". The NDA hook refuses listed terms, and it does not catch a paraphrase. The body's "Observed" section quotes a local path that names the Consumer: the rewritten body drops it.
    • The rule is written in more places than the body lists: docs/boxes/unic-dlc-pr-review.md states it in its config table, and the bootstrap fallback text in unic-dlc-qa.yaml and unic-dlc-pr-review.yaml hard-codes expected_base "develop". Write a criterion that names the property ("every statement of the base rule outside the one source is removed or points at it"), not a list of lines. A list drifts the first time the surface changes; #521 is the precedent.
    • The review Box fails quietly. unic-dlc-pr-review.yaml takes its diff from the merge-base with the base, so a wrong base reads correctly until develop moves. A criterion for it needs a check that can fail: a base that has diverged from develop.
    • docs/boxes/unic-dlc-build.md hard-codes "base develop". It is also a row for #499. Say which ticket fixes it.
    • README.md and commands/setup.md change with any new key or enum value, and the plugin's ADR convention is inline revision, Accepted (YYYY-MM-DD, revised YYYY-MM-DD), per apps/claude-code/unic-archon-dlc/docs/adr/README.md.
    • When the criteria change a Box YAML or commands/setup.md, they name the diagram under apps/claude-code/unic-archon-dlc/docs/architecture/ that the change makes stale, and require its JSON updated and both PNGs exported again. The pipeline diagrams name nodes, not the base rule, so a change inside a node may stale none. Say so in the criteria when that is the case, rather than leaving it unsaid.
    • Ask one question at a time while the answers still branch. Once they no longer depend on each other, ask them together.
    • Links, never bare ids, in everything you write on the tracker.

    The bar that proves it

    Before the label goes on, run the four reads from docs/agents/dispatching-and-learning.md § Before you post one on the criteria as a set. Then check three things:

    • An implementer reading only the criteria can say which source each base-reading line in each Box reads, and no two lines in one Box can disagree.
    • Run 4 can target integration/dlc without editing a committed file in the Consumer that every later run also reads, or the criteria say that it does and why that is accepted.
    • No criterion is satisfied by changing nothing.

    A false pass is a set where every criterion reads satisfied after a new key reaches the three bootstrap nodes, while the verify node still diffs against $BASE_BRANCH.

    On landing

    1. Rewrite this ticket's body with the approved criteria, and post a comment saying the body was amended and what changed.
    2. Before you apply any label, report to unic-sdlc-orchestrator-6 with the link to the amended body. The orchestrator reads the criteria as one set and replies.
    3. Then replace needs-specs with ready-for-agent, and leave the ticket unassigned so /afk-loop can take it. If the maintainer wants to hold it back, assign it and say so in the comment.
    4. If the criteria order this ticket against bug(unic-archon-dlc): open-pr precedes its gate, and a config-value gate has no safe middle #439, post one line on #439 saying which lands first.
    5. Change no file in the repository. Research the maintainer wants kept goes to docs/research/ in its own pull request, as Practice Packs must stack: /setup replaces .archon/methods/ wholesale, and the override tier was deleted #520's did.

    Report back

    BEFORE YOU FINISH, AND WHENEVER YOU LEARN SOMETHING THAT WOULD HAVE CHANGED THIS PROMPT,
    report to unic-sdlc-orchestrator-6 with four things and nothing else:
      1. what you expected
      2. what happened
      3. the command or file that proved it
      4. whether it changes only this ticket, or every session in this repo
    Send it when you learn it, not only at the end — a session that dies unreported
    takes its learnings with it.
    Talk only to unic-sdlc-orchestrator-6. Do not message another orchestrator or its
    sessions; tell unic-sdlc-orchestrator-6, who relays it.
    

    Review and handover

    There is no pull request. The maintainer approves the criteria in the session. The orchestrator reads them as one set before the label goes on. Implementation runs later under /afk-loop, which this seat records as unproven in the Consumer until a Consumer run reads it.

  4. self-assigned this
    on Oct 21, 2026
  5. orioltf commented on Oct 21, 2026

    @orioltf
    MemberAuthor

    Body amended, 2026-10-21: grilled into acceptance criteria. The maintainer approved them in session.

    What changed:

    • The body's two open questions are decided. The base branch comes from Archon's $BASE_BRANCH and nothing else, so no DLC key is added. project.branching stops naming the base and keeps only /qa's branch cleanup.
    • New fact: archon workflow run --base <branch> sets the base per dispatch. It has existed since Archon 0.7.1, so run 4 can target integration/dlc without editing a committed file in the Consumer. The fact is documented upstream, not measured, so criterion 1 is a spike on 0.12.1 that runs before any Box changes.
    • The review diff now reads the PR's own target branch, which closes the quiet failure.
    • /setup stays verify-only on .archon/config.yaml. It reports the base and warns, and writes nothing.
    • Order: this ticket lands before #439. docs/boxes/unic-dlc-build.md is fixed here, not in #499. Creating integration/dlc stays with #502.
    • The local path that named the Consumer is gone from the body.
  6. orioltf commented on Oct 21, 2026

    @orioltf
    MemberAuthor

    Body amended again, 2026-10-21, after the orchestrator's set-read. The maintainer approved items 2 and 3 in session.

    • Criterion 1 gains sub-item 5: --from <feature-branch> together with --base, the shape the review and /qa legs are dispatched in. It carries the same stop rule as 1 to 3.
    • Criterion 1.4 now says it measures the review's $BASE_BRANCH fallback only, since a throwaway repository has no PR. The PR-target path is proven in the Consumer before run 4, under #502.
    • Criterion 10 names the new ADR by slug. Its number is taken when it is written, because #520 also adds one.
    • Decision 6: #439 gets a native "blocked by" relation on this ticket, so the order holds whoever is assigned.
  7. 11 remaining items

  8. orioltf commented on Oct 21, 2026

    @orioltf
    MemberAuthor

    Spike, sub-item 4 re-run on PR #650 at f6bbdaf2

    The first run of sub-item 4 used the Box before prep gained its fetch, its BLOCKED paths and guard-no-diff-base. This re-run uses unic-dlc-pr-review.yaml at f6bbdaf2, with the same setup as the first spike comment. That setup is the v0.12.1 release binary run by its path, with ARCHON_HOME in a scratch folder, and the same scratch repository and bare remote. Claude Code is 2.1.306.

    Result: pass. With no PR to query and integration/dlc diverged from develop, prep fetched the base, resolved it through origin/integration/dlc, and the changed-file list holds only the feature branch's file. guard-no-diff-base was skipped.

    $ cd $S/repo && archon workflow run unic-dlc-pr-review --branch spike-run4b --from feature/x --base integration/dlc "spike505"
    [bootstrap] Completed (9.3s)     message: "Base branch: integration/dlc. ..."
    [guard-not-ready] Skipped (condition: $bootstrap.output.status != 'ready')
    prep: this tracker exposes no pull requests
    prep: diff base is integration/dlc (run base, no PR, via origin/integration/dlc)
    [prep] Completed (17.3s)         base_ref: 1a6c902a618a9caa3b7cf54f56bd9e3fac4667de, base_warning: ""
    [guard-no-diff-base] Skipped (condition: $prep.output.base_ref == '')
    [review] Completed (48.2s)
    [review-gate] Waiting for approval: ... 0 critical · 0 important · 0 minor ...
    exit=0
    
    $ cat <worktree>/workflows/spike505/pr-review/changed-files.txt
    feature-file.txt
    

    1a6c902 is the tip of integration/dlc. The gate was rejected afterwards, so nothing was posted, and the worktree was removed.

    Not measured here. This run does not exercise the guard's cancel path or the failed-query BLOCKED path. The cancel path needs a PR whose target branch does not resolve, and a scratch repository with no tracker cannot provide one. #502 proves both in the Consumer.

    Afterwards, /opt/homebrew/bin/archon --version still prints Archon CLI v0.10.1. ~/.claude/settings.json, ~/.archon/config.yaml, ~/.archon/archon.db and ~/.archon/archon.db-wal are unchanged.

  9. added
    closedPR has been merged
    and removed
    resolvedImplemented; ready for a PR
    on Oct 21, 2026
  10. orioltf commented on Oct 27, 2026

    @orioltf
    MemberAuthor

    Criterion 4: the stricter reading is confirmed (maintainer, 2026-10-27, relayed by unic-sdlc-orchestrator-7).

    PR #650 cancels /pr-review when the tracker query fails. It falls back to $BASE_BRANCH only when a query confirms that no PR exists, or when the tracker contract names no PR tool. ADR-0039 decision 3 and the 0.31.0 changelog record this, and they stand. No follow-up is needed.

    This matches #652: a PR state that cannot be read cancels the run with a message, and never falls back to a default.

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

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions