Skip to content
Merged
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
37 changes: 37 additions & 0 deletions active.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,40 @@
- autolens_workspace: feature/profile-validation-resample-recovery
- autogalaxy_workspace_test: feature/profile-validation-resample-recovery
- autolens_workspace_test: feature/profile-validation-resample-recovery


## dev-workflow-helpers-laptop-paths
- issue: https://github.com/PyAutoLabs/PyAutoBrain/issues/225
- prs: PyAutoBrain#226 (guard + installer tests) · PyAutoMind#178 (prompt_sync)
- session: Claude Code cloud session
- status: library-dev — both PRs OPEN, issue stays open until both land
- prompt: active/dev_workflow_helpers_assume_laptop_paths.md
- branch: PyAutoBrain `feature/dev-workflow-helpers-laptop-paths` (off main, files disjoint from #224 so ordering is free); PyAutoMind `claude/automind-task-planning-wxq004`
- classification: bug (PyAutoBrain primary; PyAutoMind scripts/prompt_sync.sh)
- found: 2026-08-10, three defects hit in sequence while shipping PyAutoBrain#224 — all one root cause, the helpers resolving paths under `$HOME/Code/PyAutoLabs`, which no cloud/web/CI session has.
- fixed: (1) `prompt_sync_push`/`prompt_sync_new_prompts` pushed a hardcoded `main` — now push HEAD, detached HEAD refused. (2) `worktree_check_conflict` FAILED OPEN — now exits 3 `CANNOT VERIFY`, with an explicit `--allow-missing-registry` hatch. (3) `test_skill_install.py` depended on the checkout being NAMED PyAutoBrain under `PYAUTO_ROOT` (default `bin/../..`) — now pins a fixture root.
- diagnosis-correction: the first read of (3) blamed the installer's `web-github` branch. Wrong — the real cause is `PYAUTO_ROOT` defaulting to the repo's grandparent, so a clone at lowercase `pyautobrain` never resolves `PyAutoBrain/skills` and `intake` is never installed. The environment line is a symptom of the same path resolution, not the cause. PyAutoBrain#225's body was corrected before implementation.
- test-evidence: both fixes verified to FAIL against their pre-fix code (Mind **5 of 7** new tests fail pre-fix, including the old script pushing `main -> main` from a detached HEAD; Brain guard exercised across all five paths). Corrected from '3 of 5' after the audit added a test per half of the prompt_sync defect. PyAutoBrain `pytest tests/` now 331 passed with NOTHING ignored — green in a cloud session for the first time, which retires the false-RED ship gate.
- note: `test_missing_active_md_yields_no_claims` asserted the fail-open behaviour, so it was rewritten to the corrected contract rather than worked around — it was pinning the defect.
- repos:
- PyAutoBrain: feature/dev-workflow-helpers-laptop-paths

## reconcile-upstream-repo-mode
- issue: https://github.com/PyAutoLabs/PyAutoBrain/issues/223
- session: Claude Code cloud session (no local worktree — see note below)
- status: library-dev
- prompt: active/reconcile_upstream_repo_mode.md
- branch: feature/reconcile-upstream-repo-mode (pushed, 875330f)
- classification: library (PyAutoBrain primary; PyAutoMind docs only)
- split-from: draft/feature/pyautomind/draft_staleness_detection_signals.md — legs 1-2 DELIVERED 2026-08-09, this is leg 3
- conflict-check: CLEAN, but re-verified — the first run was VACUOUS. `worktree_check_conflict` resolves `active.md` under `$PYAUTO_MAIN` (default `$HOME/Code/PyAutoLabs`), which does not exist in a cloud session, so it read no file and returned 0 = "no conflict". Re-run with `PYAUTO_MAIN=/workspace` it works and confirms the real answer: the only other live claim is profile-validation-resample-recovery on PyAutoGalaxy, no overlap. With this entry's `repos:` bullet in place, a competing task on PyAutoBrain now correctly exits 1 and this same task resuming exits 0.
- GUARD-BUG (worth its own prompt): `worktree_check_conflict` FAILS OPEN when `$PYAUTO_MAIN` does not resolve — it returns 0 rather than erroring. Any cloud/CI session running the documented command gets a green light that means nothing, and two sessions could claim the same repo. Same root cause class as the `prompt_sync_push` hardcoded-`main` issue noted below.
- cloud-session-note: registered from a cloud session, where the `~/Code/PyAutoLabs-wt/` worktree model does not exist — the checkouts are /workspace/pyautobrain and /home/user/PyAutoMind. Per `start_library` step 4 (web-github / ci-only), the repos are claimed below with NO `worktree:` field. Mind changes for this task go to branch `claude/automind-task-planning-wxq004`, not to main.
- baselines-at-planning: reconcile flags 29 of 136 scanned (7 high); no `--repo` in `_intake.py` argparse; no network access anywhere under PyAutoBrain/agents/
- status-detail: PR OPEN, awaiting review/merge. On merge the ship skills advance `active/reconcile_upstream_repo_mode.md` to `complete/2026/08/`.
- pr: https://github.com/PyAutoLabs/PyAutoBrain/pull/224 (label `pending-release`, `Closes #223`, 467+/12- across 6 files)
- implemented: 2026-08-10 on `feature/reconcile-upstream-repo-mode` (875330f). 8 new hermetic tests, 330 passed locally. Verified end-to-end against PyAutoFit fbe9f45d: `test_mode_bypass_ordered_assertion_ties.md` lands in `needs-review` with overlap_score 0.0 despite all five of its identifiers being present upstream — the acceptance criterion, met.
- ship-gate: the documented fallback gate (`pytest -x`, Heart unreachable here) returned RED on `tests/test_skill_install.py` (`assert "SKIP intake (Codex skill" in result.stdout`, 2 failures). Human acknowledged and authorized the PR. **CI then vindicated that call**: both `pytest (3.12)` and `pytest (3.13)` legs SUCCESS on 875330f, so the failures were purely local to the cloud container — `bin/install.sh` takes its `web-github / ci-only` branch (`:282`) when `$HOME/Code/PyAutoLabs` is absent, and never does the work the test asserts on. Also proven pre-existing at merge-base a50efc3 with the diff absent.
- repos:
- PyAutoBrain: feature/reconcile-upstream-repo-mode

139 changes: 139 additions & 0 deletions active/dev_workflow_helpers_assume_laptop_paths.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
# The dev-workflow helpers assume a laptop checkout and misbehave without it — one of them fails open

Type: bug
Target: PyAutoBrain
Repos:
- PyAutoBrain
- PyAutoMind
Difficulty: medium
Autonomy: supervised
Priority: high
Status: planned

Three defects, one root cause: the dev-workflow helper scripts resolve paths
under `$HOME/Code/PyAutoLabs`, which does not exist in a cloud, web or CI
session. All three were hit in a single session on 2026-08-10 while shipping
PyAutoBrain#224, and each one silently did the wrong thing rather than
complaining.

`Priority: high` because #2 is a **safety** defect, not an inconvenience: a
guard that returns "all clear" when it cannot read its input is worse than no
guard, because the workflow documents it and skills act on its answer.

## 1. `prompt_sync_push` hardcodes `git push origin main`

`@PyAutoMind/scripts/prompt_sync.sh` — the helper every Mind-writing skill is
told to call:

```bash
prompt_sync_push() {
...
git commit -m "$subject" && \
git push origin main )
}
```

`create_issue` step 6 and `start_dev` step 7 both instruct the agent to call it.

**Corrected 2026-08-10 after measuring the old script against real bare
remotes.** The first write-up of this defect said it "pushes Mind straight to
`main`". That is only half of it, and not the half that fires most often.
`git push origin main` pushes the local `main` *ref* — never the commit just
made on a feature branch. So the old behaviour splits by the state of local
`main`:

| local `main` vs remote | what the old script did |
|---|---|
| **equal** (the normal case — session branched from it) | push is a **no-op**, exits **0**, and the committed work **never leaves the machine**. The caller is told the sync succeeded. |
| **ahead** (unpushed commits on `main`) | publishes those commits to remote `main` — unreviewed work bypassing review — **and still** leaves the branch work local. |

The first row is the common one and the quieter danger: in an ephemeral cloud
container, "committed, reported synced, never pushed" is silent loss. The second
row is the review-bypass. Both are the same root cause and both are fixed by
pushing `HEAD`.

Fix: push the current branch (`git push -u origin HEAD`), or refuse with a clear
error when the checkout is not on `main`. Do not leave this to operator
vigilance — that is the same reasoning that motivated the `pre_build` staging
fix (PyAutoHands#233).

## 2. `worktree_check_conflict` FAILS OPEN — the important one

`@PyAutoBrain/bin/worktree.sh` — `worktree_list_claimed` reads `active.md` under
`$PYAUTO_MAIN` (default `$HOME/Code/PyAutoLabs`):

```bash
if [[ ! -f "$active" ]]; then
return 0
fi
```

No file → returns 0 → `worktree_check_conflict` reports **no conflict**. So in
any environment where the roots are not at the default path, the guard cannot
distinguish "nothing claims this repo" from "I could not read the registry", and
answers the former.

Reproduced 2026-08-10: `worktree_check_conflict reconcile-upstream-repo-mode
PyAutoBrain PyAutoMind` returned 0 and was recorded as a clean conflict check.
Re-run with `PYAUTO_MAIN=/workspace` it actually worked and returned the same
verdict — but the first answer was worth nothing, and if a conflict HAD existed
the session would have started conflicting work with a green light.

This is the guard that serialises two agents wanting the same repo. Two sessions
claiming one repo is exactly the class of collision the worktree flow exists to
prevent.

Fix: fail closed. If the registry cannot be resolved, return non-zero with a
message naming the path it tried, so the caller stops rather than proceeds. A
`--allow-missing-registry` escape hatch is acceptable only if it must be passed
explicitly.

## 3. `test_skill_install.py` fails locally but passes in CI

`@PyAutoBrain/tests/test_skill_install.py` — two tests assert on installer output
that only appears on the local-dev path:

```python
assert "SKIP intake (Codex skill" in result.stdout
```

`@PyAutoBrain/bin/install.sh` already knows the difference — it prints
`Environment: local-dev (PyAuto repos detected)` or `Environment: web-github /
ci-only (clone roots on demand)` — and on the web-github path it skips the
skill-symlink work these tests assert on. So they fail in any cloud session and
pass in real CI.

Consequence, observed: PyAutoHeart is unreachable from a cloud session, so
`ship_library` falls back to `pytest -x` as the ship gate and treats any failure
as RED. These two failures made that gate spuriously RED on PyAutoBrain#224 and
cost a human acknowledgement to override. CI on that PR then went green on both
legs, confirming the diff was never implicated.

Fix: skip (not fail) when the installer reports the web-github path. The tests
are asserting local-dev behaviour and should say so.

## The unifying point

`install.sh` already detects and prints its execution environment, and
`WORKFLOW.md` already names the environments (`local-dev`, `web-github`,
`ci-only`). The helpers should consult that same notion and either adapt or fail
closed. None of the three should silently do the wrong thing.

## Acceptance

- `prompt_sync_push` on a non-`main` branch pushes **that branch** — so the
committed work actually reaches the remote — and never advances `main` as a
side effect. Both halves covered by their own test, since they are separate
failures of the same bug.
- `worktree_check_conflict` returns **non-zero** when it cannot resolve
`active.md`, naming the path it tried. Covered by a test that points
`$PYAUTO_MAIN` at an empty dir. The "registry present, no claim" case still
returns 0, so the existing behaviour is unchanged where it worked.
- `test_skill_install.py` passes on both paths — skipping, with a reason, when
the installer reports web-github; still asserting fully on local-dev.
- `pytest tests/` is green in a cloud session, so the `ship_library` fallback
gate stops producing false REDs.

<!-- filed 2026-08-10 from the PyAutoBrain#224 session, where all three were hit
in sequence: (1) caught before it fired, (2) recorded a vacuous clean
conflict check that had to be corrected, (3) made the ship gate RED. -->
144 changes: 144 additions & 0 deletions active/reconcile_upstream_repo_mode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
# `intake reconcile --repo <target>` — read the target repo, the only route to the findings the Mind cannot see

Type: feature
Target: PyAutoBrain
Repos:
- PyAutoBrain
- PyAutoMind
Difficulty: medium
Autonomy: supervised
Priority: high
Status: planned

Leg 3 of `draft/feature/pyautomind/draft_staleness_detection_signals.md`, split
out because that prompt's legs 1 and 2 are **delivered** and one prompt is one
task is one PR. Read the parent for the labelled set and the measurement; this
file is the remaining leg only. Do not re-open the parent.

## Why this leg exists, and why it cannot be skipped

The parent's § Hard limit is the argument. Of the five confirmed findings from
the 2026-08-09 `draft/` sweep, **two left no Mind-local evidence at all**:

- `rectangular_adapt_constant_split_guard` — its evidence sat inside a sibling
*prompt*, not a completion record, so nothing that reads `complete/` could
reach it.
- `latent_samples_none_on_resumed_fit` — PyAutoFit#1418 fixed it the same day it
was filed and **no completion record was written**. There was nothing in the
Mind to cross-reference. (A record exists now — `complete/2026/07/
latent-samples-none-on-resumed-fit.md` — but only because a human did the
upstream read by hand. That is precisely the work this leg mechanises, and the
next such fix will land with no record again.)

The parent proved that no amount of re-ranking Mind-local signals reaches these:
every attempt cost precision without gaining truth. The upstream read is
load-bearing. This leg is that read.

Current state to build on: `intake reconcile` flags **29 suspects of 135
scanned** (7 `high`, 22 `medium`) — the post-re-rank numbers holding. The
ranking is not the problem any more; the missing evidence source is.

## Scope

Add an opt-in upstream mode to
`@PyAutoBrain/agents/conductors/intake/_intake.py`:

```
pyauto-brain intake reconcile --repo <target> [prefix]
```

It resolves the target to a GitHub slug, makes a cached shallow clone of that
repo's `main`, extracts the backticked identifiers each prompt names, greps the
clone, and ranks on hits — reporting `file:line` evidence a human can read.

### Target resolution

`repos.yaml` in @PyAutoMind carries the `github:` slug for every repo, and
`@PyAutoBrain/config/policy.yaml` already carries `repo_aliases`
(`pyautoarray -> autoarray`, and the sizing faculty's `PyAutoFit -> autofit`
package form). Reuse both — do not add a third mapping.

**Multi-repo pseudo-targets must be refused, not guessed.** `workspaces`,
`health_fixes`, `priors`, `graphical_ep` are not repos, and they are among the
*largest* buckets in `draft/` (`workspaces` alone spans 22 prompts across four
work-types). `--repo workspaces` must exit non-zero naming the real candidate
repos. Silently picking one would produce confident nonsense on the biggest
part of the backlog.

### Clone mechanics

Plain `--depth 1` with `GIT_LFS_SKIP_SMUDGE=1`, cached per-repo and re-fetched
on later runs. Record the resolved sha in the output so a verdict is
reproducible and re-checkable.

**Correction to the parent prompt:** it suggests `--depth 1 --filter=blob:none`.
Treeless is wrong here — grepping source refetches every blob on demand, so it
is a false economy. Use a plain shallow clone.

### The signal

Extract backticked `snake_case` / `CamelCase` identifiers from the prompt and
grep the clone for them. `_IDENT_RE` in `_intake.py` already does exactly this
extraction for the Mind-local leg; reuse it rather than writing a second regex.

The parent proposes scoping extraction to the prompt's `## Scope` /
`## Acceptance` sections, to catch "identifiers the prompt says do not exist
yet". That rule needs a stated fallback: **the trap prompt below has neither
heading** — its only heading is a dated correction block — so a strictly
section-scoped rule no-ops on exactly the prompts that matter most.

## The trap — verified, and the acceptance criterion turns on it

`draft/bug/autofit/test_mode_bypass_ordered_assertion_ties.md` names five
identifiers: `FitException`, `check_assertions`, `ignore_assertions`,
`instance_for_arguments`, `instance_from_vector`. **All five are on PyAutoFit
`main`.** The prompt is confirmed **NOT** shipped: `main` catches
`exc.FitException` in the TEST_MODE bypass, which looks exactly like the
requested fix, but the catch wraps only the likelihood call while
`model.instance_from_vector` — where `check_assertions` actually raises on an
ordering tie — sits on the line *before* the `try`.

A naive identifier-presence matcher scores this 5 of 5 and calls it shipped. It
would be wrong, and it is the single mis-grade this tool must never make.

So: **the mode reports `needs-review` with evidence, never a `shipped`
verdict.** It ranks for a human and retires nothing — which is already
reconcile's stated contract (`retiring a prompt stays human`). Keep it.

## Architectural constraint — this is the Brain's first network access

Nothing under `@PyAutoBrain/agents/` currently uses `urllib`, `requests`, `gh`
or `git clone`. Every conductor and faculty is stdlib-only and offline. This
leg breaks that invariant, so:

- the flag is **strictly opt-in**; the default `reconcile` path stays byte-for-
byte offline and read-only;
- the upstream read sits behind an **injectable seam** (a source-reader
callable), so `@PyAutoBrain/tests/test_intake_reconcile_ranking.py` stays
hermetic — every fixture there is a fictional Mind tree in `tmp_path`, and
that property is worth more than integration coverage;
- one opt-in network integration test, gated on an env var, covers the real
clone path;
- `@PyAutoBrain/AUTONOMY.md` gets a line stating the network surface and that it
is opt-in.

## Acceptance

- `--repo <target>` resolves via `repos.yaml` + `policy.yaml` `repo_aliases`,
and **refuses** `workspaces` / `health_fixes` / `priors` / `graphical_ep`
non-zero, naming the real repos.
- Run against PyAutoFit, `draft/bug/autofit/test_mode_bypass_ordered_assertion_ties.md`
is **NOT** reported as shipped, despite all five of its identifiers being
present upstream. Pinned by a test.
- No prompt is moved or retired by the tool. Pinned by a test (the parent
already asserts this for the Mind-local legs).
- The default `reconcile` path performs **no** network access. Pinned by a test.
- The existing hermetic tests still pass unchanged.
- Output records the resolved upstream sha.

<!-- split 2026-08-10 from draft/feature/pyautomind/draft_staleness_detection_signals.md
(legs 1-2 DELIVERED 2026-08-09; this is leg 3, which that prompt's own
delivery note re-motivates as "the only route to the last two findings").
Baselines verified at split time: reconcile 29/135 flagged, 7 high;
no --repo flag in _intake.py argparse; no network access anywhere under
PyAutoBrain/agents/. -->
5 changes: 5 additions & 0 deletions draft/feature/pyautomind/draft_staleness_detection_signals.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,11 @@ is already reconcile's stated contract. Keep it.
>
> Leg 3 remains open and is now better motivated: it is the *only* route to the
> last two findings.
>
> **Leg 3 was split out on 2026-08-10** to
> `draft/feature/pyautobrain/reconcile_upstream_repo_mode.md` — one prompt is
> one task is one PR, and legs 1-2 here are delivered. Track leg 3 there; do
> not re-open this prompt for it.

- Re-running the ranker against PyAutoMind `f25e154e` (the pre-sweep tree, which
is the labelled set this prompt establishes) puts every **Mind-reachable**
Expand Down
Loading
Loading