3 Commits
Author SHA1 Message Date
Nick ca4f7593d7 feat(corrections): #314 defect fix, credential rotation, release guard, task lifecycle, route scoping, PL1 records + metrics
CORRECTION 1: #314 reopened — recall_with_associations mode field defect
CONFIRMED in current source and FIXED (mode: association_merged).

CORRECTION 3: Gitea credential removed from remote URL (credential helper).
TOKEN EXPOSED: yes (in diagnostic output). TOKEN ROTATED: not yet (requires
Gitea web UI access). Remote URL now shows username only, no secret.

CORRECTION 4: duplicate-release-commit defect ROOT CAUSE: convergence
computed warranted bump from commits-since-tag without checking if master
version already satisfies the bump. FIX: already-converged guard in
version_convergence.py (master version > last tag → no commit). Repo-aware
(args.repo passed to read_version/latest_tag).

CORRECTION 6: lifecycle terminalization — execution exception now
guarantees task terminalizes as failed with evidence (no immortal RUNNING).

CORRECTION 7: route instruction task-scoped on RuneTask.route_instruction
(NOT shared operator state). Read-only leading-verb override. Isolation
tests prove no cross-contamination between interleaved tasks.

PL1-01/02/03/05: pl1_records.py (route resolution, proof level, failure
class, candidate status), metrics with honest NOT_YET_MEASURABLE semantics,
route-instruction learning loop (PE-1789102658-0269 SEED).

1253 tests green; ratchet 352/80 (shrink); henxels clean.
2026-09-11 15:36:08 +01:00
Nick 31a3d42535 fix(D5.1-D5.3): mutation boundary tightening — content fingerprints, explicit per-stage allowlist, all-terminal-path verification
D5.1 — CONTENT FINGERPRINTS, not porcelain-line diffs:
  capture_worktree_state() now records a sha256 per tracked+untracked file.
  verify_no_source_mutation() compares hashes — a change to an already-dirty
  file is detected (porcelain comparison would produce the same line and
  miss it). require_clean_worktree() added for baseline methodology.

D5.2 — EXPLICIT PER-STAGE ALLOWLIST, not artifact_dir-wide:
  the executor passes exactly: the declared stage artifact file, this
  stage's event/err files, telemetry/, consumed markers, and task_tree.json
  (executor-owned — advance() writes it, not the worker). An OUTWARD
  worker can no longer silently modify another stage's artifact or the
  task-tree authority — cross-stage writes are detected.

D5.3 — VERIFY ON EVERY TERMINAL PATH:
  the mutation check runs for COMPLETED, GATE_FAILED, GATE_RETRY, FAILED,
  TIMEOUT and INTERRUPTED — a worker that mutates source and then fails
  still has the mutation identified.

3 new tests: fingerprint-catches-already-dirty-file-mutation,
cross-stage-artifact-write-detected, HEAD-movement-without-file-changes.

1168 tests pass; ruff clean.
2026-09-10 00:13:06 +01:00
Nick a997a0ae4c feat(D4+D5): executor-owned artifact targets + cognitive-stage mutation boundary (closes #298 scope)
D4 — ARTIFACT TARGET CONTRACT IS EXECUTOR-OWNED:
- _declared_artifact_path(stage): absolute path computed from artifact_dir +
  STAGE_ARTIFACT_FILES[stage]; injected verbatim into every worker prompt
  (APPLICABILITY/ADVERSARIAL/SYNTHESIS/INNOVATION/OUTWARD/QUALIFY)
- Worker never derives its own path — producer and consumer share one
  authoritative output location (the B3-v2 root cause: worker's prompt said
  research/issue-162/ but executor's artifact_dir was research/issue-162-b3v2/)
- Acceptance: nonstandard artifact_dir (issue-162-b3v2) now gets the correct
  path injected

D5 — COGNITIVE_STAGE_MUTATION_BOUNDARY:
- mutation_boundary.py: capture_worktree_state (status porcelain + HEAD)
  before cognitive stages; verify_no_source_mutation after; new changes
  outside declared artifact paths → UNAUTHORIZED_STAGE_MUTATION
- HEAD movement detected (cognitive stages must never commit)
- allowed paths: declared artifact + telemetry + consumed markers
- Wired into execute(): cognitive stages only (ISSUE/IMPLEMENT skip);
  failure → STAGE_FAILED, no advancement
- Tests: clean stage passes; source mutation detected → FAILED + no
  advancement + mutation visible for human review

BLE001 narrowed in mutation_boundary (git errors are OSErrors).

1164 tests pass; ruff clean.
2026-09-09 23:57:59 +01:00