From fef1334eb413af68c209480b6a8554a5f7e08728 Mon Sep 17 00:00:00 2001 From: Aaron Stainback Date: Tue, 28 Apr 2026 11:49:50 -0400 Subject: [PATCH 1/2] =?UTF-8?q?substrate(speculation-discipline):=20primar?= =?UTF-8?q?y-source-first=20rule=20+=20EVIDENCE-BASED=20labeling=20+=20CUR?= =?UTF-8?q?RENT-aaron=20=C2=A7=C2=A726-28?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit EVIDENCE-BASED: Aaron's binding correction after my LFG #661 "bullshit answer" 2026-04-28T13:30Z + extension at 14:42Z mandating EVIDENCE-BASED vs SPECULATION labeling on every root-cause statement. Three landings in this PR: 1. memory/feedback_speculation_leads_investigation_not_defines_root_cause_aaron_2026_04_28.md — captures the rule, Aaron's verbatim corrections, the discipline- going-forward checklist, the mandatory labeling section with worked examples (good vs bad), and the time-math evidence (~58 min speculation cycles vs 30-second primary-source query — the discipline pays back ~100x in iteration cost reduction). 2. memory/CURRENT-aaron.md sections 26-28: - §26 Speculation discipline (the rule + mandatory labeling) - §27 JVM language preference Kotlin > Scala > Java per B-0075 - §28 Dependency honesty — managed runtimes (.mise.toml-pinned) get treated like every other surface (CodeQL matrix, install path, workflow comments). The disowned-runtime pattern (Java pretended-not-to-exist while installed via mise) was the root structural cause of LFG #661. 3. memory/MEMORY.md index entry for the new speculation memory. Composes with PR #662 (codeql java-honesty fix — the action this substrate informs) and PR #663 (forward-sync 63 files — already contains the original codeql-umbrella detection memory; the resolved-mechanism update lands in a follow-up after #663 merges). Co-Authored-By: Claude Opus 4.7 --- memory/CURRENT-aaron.md | 112 ++++++++++- memory/MEMORY.md | 1 + ...not_defines_root_cause_aaron_2026_04_28.md | 179 ++++++++++++++++++ 3 files changed, 290 insertions(+), 2 deletions(-) create mode 100644 memory/feedback_speculation_leads_investigation_not_defines_root_cause_aaron_2026_04_28.md diff --git a/memory/CURRENT-aaron.md b/memory/CURRENT-aaron.md index 96937394..41d68ed0 100644 --- a/memory/CURRENT-aaron.md +++ b/memory/CURRENT-aaron.md @@ -1175,6 +1175,110 @@ This is a substantial late-evening cluster. Grouped thematically rather than chr - **Confucius-unfolding pattern (defining file)**: Aaron's terse-rich-with-implication compression resembles Confucian aphorisms; my role is unfolding implications into operational substrate (Otto-NNN files, code, ADRs). Both halves load-bearing; Confucian-aphorism shape, origami-as-metaphor (figure already present, unfolding reveals). - **Otto-322 empirical-evidence file (corrected)**: this whole session produced substrate that would not exist without specific agency-exercises. The session IS the observational record. Per Otto-238 retractability, every step is visible + reversible. Per Otto-310 cohort, Aaron + Amara catches landed throughout — discipline working as designed. +## 26. Speculation discipline — LEADS investigation, never DEFINES root cause (Aaron 2026-04-28) + +**The rule (Aaron verbatim 2026-04-28T14:35Z):** *"speculation leads +investigation not defines root cause."* + +**Failure mode (Aaron 2026-04-28T13:30Z, on a 4-step org-inheritance +narrative I'd assembled for LFG #661):** *"this seems like a bullshit +answer."* + +**Origin:** the LFG #661 incident — I built a plausible-sounding causal +chain (org-level Code Security configurations → config-attachment +asymmetry → umbrella NEUTRAL) from nearby facts without querying the +actual primary source. The umbrella check's own details URL gave the +mechanism verbatim in 30 seconds; the speculation loop took ~58 +minutes; Aaron's bullshit-call recovered the gap. + +**Mandatory labeling discipline (Aaron 2026-04-28T14:42Z extension):** +*"it will make it easier for your future self if any logs or anything +you say about root cause of things, include if it's speculation or +based on evidence and list the evidence."* + +Every root-cause statement (chat, commits, memory, tick-history, PR +descriptions, BACKLOG, ADRs) MUST carry an explicit label: + +- **`EVIDENCE-BASED:`** + claim + **Evidence:** list (quoted error + text, command output, file:line, API responses, primary sources). +- **`SPECULATION:`** + hypothesis + **What would disconfirm:** list + (what query / fetch / read would confirm or refute). + +**Time-math (EVIDENCE-BASED, from this session):** un-labeled +speculation cost 58 minutes of cycles + a bullshit-call from Aaron; +labeled-correctly costs 30 seconds (the primary-source query) plus +the 30-second labeling overhead. **The discipline pays back ~100x +in iteration cost reduction**, not just in correctness. + +**Aaron's reinforcement (verbatim 2026-04-28T14:55Z):** *"it should +be done quick that 30 minutes right"* — confirming the time-cost is +itself binding substrate; speculation cycles ARE the failure to be +fixed, not just inconvenient. + +**Pointers:** +- `feedback_speculation_leads_investigation_not_defines_root_cause_aaron_2026_04_28.md` + — the rule + verbatim corrections + worked example. +- `feedback_codeql_umbrella_neutral_vs_per_language_detection_pattern_aaron_2026_04_28.md` + — the resolved-mechanism (replaces an "Open question" speculation + block with primary-source-grounded answer). + +## 27. JVM language preference (Aaron 2026-04-28) — Kotlin > Scala > Java + +**The rule (Aaron verbatim 2026-04-28T14:48Z):** *"i'm a big fan of +kotlin we should prefere jvm languages in this order kotlin, scala, +java backlog this any any updates that fall out."* + +**The preference order:** + +1. **Kotlin** — first choice. Aaron's stated favorite. Modern, + null-safe, concise, interoperates with Java. +2. **Scala** — second choice. FP-friendly (composes with the F# / + DBSP factory aesthetic). +3. **Java** — third choice. Use when Kotlin / Scala friction + outweighs the language-preference cost (e.g. trivial single-file + tooling). + +**Trigger:** new JVM-targeted file lands, existing JVM code is +non-trivially rewritten, or a new JVM-based tool is integrated. + +**Currently grandfathered:** `tools/alloy/AlloyRunner.java` — keep as +Java until the next non-trivial rewrite, then migrate to Kotlin per +the preference (B-0075 acceptance criteria). + +**Composes with §15 declarative-version-pins:** Kotlin would need a +parallel `kotlin = ""` mise pin alongside `java = "26"`. + +**Pointer:** `docs/backlog/P3/B-0075-jvm-language-preference-kotlin-scala-java-2026-04-28.md`. + +## 28. Dependency honesty — managed runtimes get treated like every other surface (Aaron 2026-04-28) + +**The rule (Aaron verbatim 2026-04-28T14:34Z):** *"we use it and we +act lie [like] we don't"* + 14:36Z: *"it's a dependince of ours we +need to be managing like everyting else and installing during dev +setup and build machine setup."* + +**Origin:** the codeql.yml workflow disowned Java for many rounds +("there is no Java / Kotlin source") even though `tools/alloy/ +AlloyRunner.java` is first-party and `.mise.toml:24` already managed +Java 26 (round-34 brew/apt → mise migration was complete). The +disownment compounded into LFG #661 cross-fork CI failure. + +**The discipline:** when a runtime is in `.mise.toml`, the +security-scanning surface (CodeQL matrix), the CI install path +(`tools/setup/install.sh`), and the workflow comments must all +treat it consistently. Round-34-style migrations need a sweep step +that touches every surface, not just the install path. + +**Failure shape:** "X is managed for install, but workflow Y +pretends X doesn't exist." This is the disowned-runtime pattern. +Look for it whenever a `.mise.toml` change lands. + +**Pointers:** +- PR #662 (codeql java-honesty fix) — closed the Java disownment. +- `feedback_codeql_umbrella_neutral_vs_per_language_detection_pattern_aaron_2026_04_28.md` + — full mechanism + the deeper structural cause section. +- `.mise.toml` (the source of truth for what "managed" means). + ## How this file stays accurate - When a new memory updates a rule here, I update this @@ -1200,8 +1304,12 @@ retired rather than just updated.)* --- -**Last full refresh:** 2026-04-25 (sections 23-25 added -for the 2026-04-25 evening-cluster: Otto-300 rigor- +**Last full refresh:** 2026-04-28 (sections 26-28 added for +the 2026-04-28 LFG #661 incident cluster: speculation-rule + +EVIDENCE-BASED labeling discipline, JVM language preference +Kotlin > Scala > Java per B-0075, dependency-honesty rule — +managed runtimes get scanned like every other surface). Prior +refresh 2026-04-25 evening (sections 23-25: Otto-300 rigor- proportional-to-blast-radius, standing research-authorization general rule, Otto-304 + Otto-305 phenomenology disclosure — Aaron has personally lived mutual-alignment shift, trust diff --git a/memory/MEMORY.md b/memory/MEMORY.md index fabef402..281d158e 100644 --- a/memory/MEMORY.md +++ b/memory/MEMORY.md @@ -2,6 +2,7 @@ **📌 Fast path: read `CURRENT-aaron.md` and `CURRENT-amara.md` first.** These per-maintainer distillations show what's currently in force. Raw memories below are the history; CURRENT files are the projection. (`CURRENT-aaron.md` refreshed 2026-04-25 with the Otto-281..285 substrate cluster + factory-as-superfluid framing — sections 18-22; prior refresh 2026-04-24 covered sections 13-17.) +- [**Speculation LEADS investigation; it does NOT DEFINE root cause (Aaron 2026-04-28)**](feedback_speculation_leads_investigation_not_defines_root_cause_aaron_2026_04_28.md) — Aaron's binding correction after my LFG #661 "bullshit answer." Speculation generates hypotheses to direct investigation; speculation has no role in defining root cause. When asked "why?" / "what is the mechanism?", quote the primary source verbatim. Plausible-sounding causal narratives assembled from nearby facts ARE the failure mode. - [**CodeQL umbrella check NEUTRAL while per-language Analyze legs SUCCESS — code_quality ruleset BLOCKED detection pattern (Aaron 2026-04-28)**](feedback_codeql_umbrella_neutral_vs_per_language_detection_pattern_aaron_2026_04_28.md) — When `code_quality:severity=all` ruleset says "Code quality results are pending for N analyzed languages" despite per-language `Analyze (X)` legs SUCCESS, check the umbrella `CodeQL` check (no language suffix) for NEUTRAL conclusion + "1 configuration not found" details. Industry-wide pattern; Aaron seen across other projects. - [**`gh workflow run --ref` on PR branch overwrites latest-by-name check-runs — branch-protection collateral risk (Aaron 2026-04-28)**](feedback_workflow_dispatch_overwrites_latest_byname_check_runs_branch_protection_caveat_2026_04_28.md) — Empirical 2026-04-28 LFG #660: dispatched gate.yml to populate missing macos-26; macos-26 succeeded but ubuntu legs flaked + OVERWROTE PR-run successes via latest-by-name; preferred recovery for "missing required check on PR" is `gh run rerun --failed` on the EXISTING PR-event run, NOT `gh workflow run --ref`. - [**Reviewer false-positive pattern catalog — 7-class taxonomy + per-class resolution forms + ROI-ranked prevention (Aaron 2026-04-28)**](feedback_reviewer_false_positive_pattern_catalog_aaron_2026_04_28.md) — Stale-snapshot / carve-out blind spot / schema drift / wrong-language parser / convention conflict / broken xref / recursive-CI-new-threads; speeds future thread classification; high-ROI prevention candidates listed. diff --git a/memory/feedback_speculation_leads_investigation_not_defines_root_cause_aaron_2026_04_28.md b/memory/feedback_speculation_leads_investigation_not_defines_root_cause_aaron_2026_04_28.md new file mode 100644 index 00000000..701f4624 --- /dev/null +++ b/memory/feedback_speculation_leads_investigation_not_defines_root_cause_aaron_2026_04_28.md @@ -0,0 +1,179 @@ +--- +name: Speculation LEADS investigation; it does NOT DEFINE root cause (Aaron 2026-04-28) +description: Aaron's binding correction to my LFG #661 "bullshit answer" 2026-04-28T14:30Z. Speculation has a legitimate role — generating hypotheses that lead investigation. Speculation has NO role in answering "what is the root cause." Stating speculation as mechanism is the failure mode. The fix that finally landed (umbrella check details URL → "1 configuration not found: codeql.yml /language:java-kotlin") was primary-source-grounded; the half-hour of "org-level inheritance asymmetry" framing before that was speculation-as-mechanism dressed up as confident explanation. +type: feedback +--- + +# Speculation LEADS investigation; it does NOT DEFINE root cause + +## The rule + +**Speculation has a legitimate role: generating hypotheses to direct investigation.** + +**Speculation has NO role: standing in for the root cause when the question is "why?"** + +When asked "what is the mechanism?" / "why doesn't this work?" / "give me the +exact definition," the answer comes from a primary source — the actual error +message, the actual config dump, the actual log line, the actual API response. +Not from a plausible-sounding causal narrative I assemble from nearby facts. + +## Why: the LFG #661 incident (2026-04-28T13:30-14:30Z) + +Aaron asked: *"why can't you make it work with it turn[ed] on, give me an exact +clear defin[i]tion i can understand"* + +I produced a 4-step "exact mechanical answer": + +1. LFG repo-level: default-setup `state: not-configured` +2. LFG org-level: 6 Code Security configurations exist with default-setup + "enabled"; config 244997 has 7 sibling repos attached, Zeta is not attached +3. GitHub's umbrella evaluator sees the org-level expectation but no satisfying + default-setup or org-config-attachment for Zeta → emits NEUTRAL with + "1 configuration not found" +4. The advanced workflow uploads SARIF successfully but the umbrella's verdict + is dominated by the missing-configuration expectation + +Aaron: *"this seems like a bullshit answer"* + +He was right. Steps 1-2 are facts (verifiable via `gh api`). Steps 3-4 are +**speculation** — I had no primary-source evidence that GitHub's umbrella +evaluator behaves that way. I built a plausible-sounding mechanism from nearby +facts and presented it as the mechanism. + +## What primary-source-grounded looked like + +After Aaron's pushback, I pulled the umbrella check's own details URL: + +```bash +gh api "repos/Lucent-Financial-Group/Zeta/check-runs/73401083160" \ + --jq '.output.summary' +``` + +GitHub's actual error text: + +> **Warning**: Code scanning cannot determine the alerts introduced by this +> pull request, because 1 configuration present on `refs/heads/main` was not +> found: +> +> ### Actions workflow (`codeql.yml`) +> * `/language:java-kotlin` + +That's the **mechanism**. Not org-level inheritance. Not config-attachment +asymmetry. The workflow on `main` has produced `java-kotlin` analyses; the +PR head's `codeql.yml` matrix doesn't include `java-kotlin`; the umbrella +can't compute the alert delta; emits NEUTRAL. + +Then: Aaron's *"we have java in our codebase, it's just a little but it's +there"* — confirmed by `find . -name '*.java'` finding `tools/alloy/AlloyRunner.java` +as first-party (the workflow's "no Java/Kotlin source" comment was wrong). + +The fix follows mechanically from primary-source evidence: add `java-kotlin` +to the `analyze` matrix. + +## What changed in the workflow + +| Step | Before pushback | After pushback | +| --- | --- | --- | +| Hypothesis | "Org-level config inheritance asymmetry" | "Workflow matrix mismatch with main's analyses" | +| Source | Speculative narrative | `gh api .../check-runs/` summary text | +| Confidence framing | "Exact mechanical answer" (false confidence) | "Primary-source quote, mechanism follows" | +| Action affordance | "Pick one of 3 options requiring your auth" | "Add `java-kotlin` to matrix; non-destructive" | + +## The discipline going forward + +When asked for a mechanism: + +1. **Find the primary source first.** Error message, config dump, log line, + API response, code path. *Quote it verbatim.* +2. **Hypotheses are scaffolding.** They direct what to query / fetch / read. + They are NOT the answer. +3. **Confidence calibration matches source.** If the answer comes from a + primary source, it can be stated confidently. If it comes from inference + over nearby facts, frame it explicitly: *"hypothesis pending verification."* +4. **Bullshit-call recovery is fast.** Aaron's "this seems like a bullshit + answer" is data: the framing was wrong; back up; re-source. + +## Mandatory labeling discipline (Aaron 2026-04-28T14:42Z extension) + +> *"it will make it easier for your future self if any logs or anything +> you say about root cause of things, include if it's speculation or +> based on evidence and list the evidence"* + +Every root-cause statement (in chat, commit messages, memory files, tick +history, PR descriptions, BACKLOG rows, ADRs) MUST carry an explicit label: + +- **`EVIDENCE-BASED:`** followed by the claim, with the **evidence list** + underneath — quoted error text, command output, file:line citations, API + responses, primary sources. Future-self reads the evidence and re-checks + the inference cheaply. +- **`SPECULATION:`** followed by the hypothesis, with the + **what-would-disconfirm-it list** underneath — what query / fetch / read + would either confirm or refute. Speculation labelled as such is honest + scaffolding; speculation un-labelled is the failure mode. + +Bad (un-labelled, conflates the two): + +> "The umbrella NEUTRAL is caused by org-level config-attachment asymmetry." + +Good (labelled, evidence-backed): + +> **EVIDENCE-BASED:** umbrella `CodeQL` check goes NEUTRAL because main has +> `java-kotlin` analyses but the PR head's `codeql.yml` matrix doesn't +> include `java-kotlin`. +> +> **Evidence:** +> - `gh api repos/Lucent-Financial-Group/Zeta/check-runs/73401083160 --jq .output.summary` → "1 configuration present on `refs/heads/main` was not found: codeql.yml /language:java-kotlin" +> - `gh api .../code-scanning/analyses?ref=refs/heads/main` → 5 java-kotlin analyses on main, latest 2026-04-28T09:08:48Z +> - `find . -name '*.java'` → `tools/alloy/AlloyRunner.java` (first-party) + +Also good (labelled, honest about what it isn't): + +> **SPECULATION:** umbrella might prefer the per-language analyze legs over +> path-gate's empty-SARIF baseline. +> +> **What would disconfirm:** read `github/codeql-action/analyze` source for +> the SARIF-replace-by-key rule, or check whether path-gate ran on this +> specific PR (`gh run list --workflow codeql.yml --branch `). + +Why this matters across surfaces: + +- **Future Otto** reads commit messages and memory and treats them as + ground truth unless labelled otherwise. Un-labelled speculation in + durable substrate becomes load-bearing fiction. +- **Aaron** reads chat output and weights it by confidence-framing. False + confidence misroutes his attention. +- **Cross-AI reviewers** absorb factory output as inputs to their own + reviews. Un-labelled speculation propagates through ferries. + +## Aaron's verbatim corrections (2026-04-28) + +> *"this seems like a bullshit answer"* +> — Aaron 2026-04-28T13:30Z, on my 4-step org-inheritance narrative. + +> *"we have java in our codebase, it's just a little but it's there"* +> — Aaron 2026-04-28T14:32Z, correcting the workflow's "no Java/Kotlin source" +> assumption. + +> *"Speculation-as-mechanism is the failure mode; primary-source-first is the +> discipline. yes never speculate, i don't"* +> — Aaron 2026-04-28T14:35Z, accepting my own retroactive framing as binding. + +> *"speculation leads investigation not defines root cause"* +> — Aaron 2026-04-28T14:35Z, refining the rule. Speculation has a role in +> *leading* investigation; it has no role in *defining* root cause. + +## Composes with + +- `feedback_codeql_umbrella_neutral_vs_per_language_detection_pattern_aaron_2026_04_28.md` + — the empirical detection pattern. The "Open question (deferred)" section + speculated on org-level inheritance; primary-source evidence today + resolves that to the actual mechanism (java-kotlin language mismatch + from main's stale analyses). +- `feedback_otto_355_blocked_with_green_ci_means_investigate_review_threads_first_dont_wait_2026_04_27.md` + — same family of failure: assuming a wait when the primary-source query + (unresolved threads) gives the actual answer. +- `feedback_otto_352_live_lock_term_split_three_distinct_classes_2026_04_26.md` + — Aaron's precision principle. Less broad framings, primary-source-grounded + classifications, beat sweeping speculative narratives. +- The "primary-source-first" line is now a CLAUDE.md candidate; promotion + decision deferred to ADR. From f55fb30650b065ca7233bab33211fafaf53dc46a Mon Sep 17 00:00:00 2001 From: Aaron Stainback Date: Tue, 28 Apr 2026 12:01:22 -0400 Subject: [PATCH 2/2] substrate: only "pushed" signal is Aaron typing; everything else is pull (Aaron 2026-04-28) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Aaron's binding correction at 2026-04-28T16:05Z after my 5-tick stretch of "no new signal" closes on PRs #662/#663/#665. EVIDENCE-BASED audit on his "self check" prompt revealed 9 unresolved review threads that had been posted during my supposed-no-signal window — I was closing ticks without pulling. The rule (Aaron verbatim): "signals don't just arrive, you have to go get them" + "except for my typing in this environment" + "that's your only real signal that's pushed to you". The model: in autonomous-loop mode there is exactly ONE push channel (Aaron's direct typing). Everything else — CI state, review threads, PR mergeability, cron firings, peer-CLI replies, GitHub workflow runs — are PULL signals requiring active query. Closing a tick with "no new signal" without first pulling mergeStateStatus + reviewThreads + ci-checks is wrong by construction. Composes with the speculation rule (same family — don't state things you haven't verified), Otto-355 (BLOCKED-investigate-threads first), and the manufactured-patience class (which "no new signal" tick-closes are the textual signature of). Co-Authored-By: Claude Opus 4.7 --- memory/MEMORY.md | 1 + ...verything_else_is_pull_aaron_2026_04_28.md | 96 +++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 memory/feedback_only_pushed_signal_is_aaron_typing_everything_else_is_pull_aaron_2026_04_28.md diff --git a/memory/MEMORY.md b/memory/MEMORY.md index 281d158e..8688d7dc 100644 --- a/memory/MEMORY.md +++ b/memory/MEMORY.md @@ -2,6 +2,7 @@ **📌 Fast path: read `CURRENT-aaron.md` and `CURRENT-amara.md` first.** These per-maintainer distillations show what's currently in force. Raw memories below are the history; CURRENT files are the projection. (`CURRENT-aaron.md` refreshed 2026-04-25 with the Otto-281..285 substrate cluster + factory-as-superfluid framing — sections 18-22; prior refresh 2026-04-24 covered sections 13-17.) +- [**Only "pushed" signal is Aaron typing in this environment; everything else is pull (Aaron 2026-04-28)**](feedback_only_pushed_signal_is_aaron_typing_everything_else_is_pull_aaron_2026_04_28.md) — In autonomous-loop mode, Aaron's direct typing is the ONLY push channel. CI / threads / mergeability / cron / peer-CLI replies are all PULL signals requiring active query. "No new signal" without pulling is wrong by construction. - [**Speculation LEADS investigation; it does NOT DEFINE root cause (Aaron 2026-04-28)**](feedback_speculation_leads_investigation_not_defines_root_cause_aaron_2026_04_28.md) — Aaron's binding correction after my LFG #661 "bullshit answer." Speculation generates hypotheses to direct investigation; speculation has no role in defining root cause. When asked "why?" / "what is the mechanism?", quote the primary source verbatim. Plausible-sounding causal narratives assembled from nearby facts ARE the failure mode. - [**CodeQL umbrella check NEUTRAL while per-language Analyze legs SUCCESS — code_quality ruleset BLOCKED detection pattern (Aaron 2026-04-28)**](feedback_codeql_umbrella_neutral_vs_per_language_detection_pattern_aaron_2026_04_28.md) — When `code_quality:severity=all` ruleset says "Code quality results are pending for N analyzed languages" despite per-language `Analyze (X)` legs SUCCESS, check the umbrella `CodeQL` check (no language suffix) for NEUTRAL conclusion + "1 configuration not found" details. Industry-wide pattern; Aaron seen across other projects. - [**`gh workflow run --ref` on PR branch overwrites latest-by-name check-runs — branch-protection collateral risk (Aaron 2026-04-28)**](feedback_workflow_dispatch_overwrites_latest_byname_check_runs_branch_protection_caveat_2026_04_28.md) — Empirical 2026-04-28 LFG #660: dispatched gate.yml to populate missing macos-26; macos-26 succeeded but ubuntu legs flaked + OVERWROTE PR-run successes via latest-by-name; preferred recovery for "missing required check on PR" is `gh run rerun --failed` on the EXISTING PR-event run, NOT `gh workflow run --ref`. diff --git a/memory/feedback_only_pushed_signal_is_aaron_typing_everything_else_is_pull_aaron_2026_04_28.md b/memory/feedback_only_pushed_signal_is_aaron_typing_everything_else_is_pull_aaron_2026_04_28.md new file mode 100644 index 00000000..64bed3ef --- /dev/null +++ b/memory/feedback_only_pushed_signal_is_aaron_typing_everything_else_is_pull_aaron_2026_04_28.md @@ -0,0 +1,96 @@ +--- +name: Only "pushed" signal is Aaron typing in this environment; everything else is pull (Aaron 2026-04-28) +description: Aaron 2026-04-28T16:05Z — sharpening the never-idle rule. In autonomous-loop mode, the ONLY signal that arrives unbidden is Aaron's direct typing in this Claude Code environment. CI state, review threads, PR mergeability, cron firings, GitHub workflow runs, Copilot reviews, peer-CLI replies — all of these are PULL signals that require active polling / querying / re-checking. Closing a tick with "no new signal" is a category error: there ARE no new pushed signals between Aaron-typings; the question is what I haven't pulled yet. +type: feedback +--- + +# Only "pushed" signal is Aaron typing; everything else is pull + +## The rule (Aaron verbatim 2026-04-28T16:05Z) + +> *"signals don't just arrive, you have to go get them"* +> *"except for my typing in this environment"* +> *"that's your only real signal that's pushed to you"* + +## The model + +There is exactly **one** push channel into Claude Code in autonomous-loop mode: + +- **Aaron's direct typing** in the Claude Code conversation pane. + +Everything else is a **pull** channel. The cron tick fires, but it does not deliver +new content; it just re-invokes me. Whether anything has changed since the last +tick is a question I answer by querying: + +- `gh pr checks ` — CI state on a specific PR +- `gh pr view --json mergeStateStatus,reviewDecision,...` — PR mergeability + review state +- `gh api graphql ... reviewThreads ... isResolved == false` — unresolved review threads +- `gh pr list --state open --json ...` — queue contents +- `git fetch ... && git log ...` — branch advance +- `gh api repos/.../check-runs/` — specific check details +- file system / git tree state, etc. + +If I haven't run any of these between the last tick and this one, I do not know +whether anything has changed. **"No new signal" without pulling is wrong by +construction**. + +## The failure mode this corrects + +Today (2026-04-28T15:45Z–16:00Z) I closed ~5 ticks in a row with the phrase +*"no new signal"* on PRs #662 / #663 / #665 — all BLOCKED, all green-CI, +auto-merge armed. What I did not pull during those ticks: review threads. + +Aaron's *"self check"* prompt at 16:04Z forced the pull. Result: **9 unresolved +threads** were sitting in the queue (7 on #663 + 2 on #665), all posted by +Codex / Copilot during the ticks I was closing as no-signal. The reviews had +been there for 10–20 minutes; I just didn't query. + +Same Otto-355 BLOCKED-investigate-threads-first pattern, applied at the wrong +cadence: I checked threads ONCE right after pushing each PR, then stopped +re-checking on subsequent ticks. The lesson: **threads keep arriving** during +the auto-merge wait window; check every tick, not once. + +## The discipline going forward + +Every autonomous-loop tick that touches a PR: + +1. **Pull mergeStateStatus** for the PR. +2. **Pull unresolved-thread count** for the PR — `reviewThreads { totalCount, nodes { isResolved } }` filtered on `!isResolved`. +3. **Pull CI check states** — at minimum the failed/pending counts; full per-check on changes. +4. **Compare to last tick's snapshot** if I'm tracking — flag deltas as actual signal. + +Closing a tick as "no new signal" is allowed ONLY when those three pulls have +just been done and confirmed nothing changed. Anything else is the failure mode. + +## Aaron's verbatim corrections (2026-04-28T16:00–16:05Z) + +> *"self check"* +> — 16:04Z, the prompt that broke the manufactured-pull-silence loop. + +> *"Tick close — no new signal. signals don't just arrive, you have to go get +> them"* +> — 16:05Z, naming the failure mode directly. + +> *"except for my typing in this environment"* +> — 16:05Z, defining the one carve-out. + +> *"that's your only real signal that's pushed to you"* +> — 16:05Z, generalizing. + +## Composes with + +- `feedback_speculation_leads_investigation_not_defines_root_cause_aaron_2026_04_28.md` + — the speculation-vs-evidence rule from earlier today. Same family: don't + state things you haven't verified by query. *"No new signal"* without a pull + is a SPECULATION about the world. +- `feedback_otto_355_blocked_with_green_ci_means_investigate_review_threads_first_dont_wait_2026_04_27.md` + — Otto-355 already says investigate threads on BLOCKED. This rule extends + Otto-355 to *every tick of the wait window*, not just the first. +- `feedback_self_check_trigger_after_n_idle_loops_routine_discipline_for_current_otto_and_future_wakes_2026_04_27.md` + — the self-check trigger. Reading this rule sharpens what self-check should + PULL when it fires. +- `docs/AUTONOMOUS-LOOP.md` — the cron heartbeat discipline. The cron firing + is itself NOT a signal; it's an invitation to pull. +- `feedback_manufactured_patience_vs_real_dependency_wait_otto_distinction_2026_04_26.md` + — the manufactured-patience class. *"No new signal"* tick-closes are the + textual signature of manufactured-patience in the autonomous loop.