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
112 changes: 110 additions & 2 deletions memory/CURRENT-aaron.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Comment thread
AceHack marked this conversation as resolved.
— the resolved-mechanism (replaces an "Open question" speculation
block with primary-source-grounded answer).
Comment thread
AceHack marked this conversation as resolved.

## 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 = "<version>"` 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
Expand All @@ -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
Expand Down
2 changes: 2 additions & 0 deletions memory/MEMORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

**📌 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 <PR-run-id> --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.
Expand Down
Original file line number Diff line number Diff line change
@@ -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 <N>` — CI state on a specific PR
- `gh pr view <N> --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 <ref>...<ref>` — branch advance
- `gh api repos/.../check-runs/<id>` — 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.
Loading
Loading