diff --git a/memory/MEMORY.md b/memory/MEMORY.md index 405a68073..83eba9e14 100644 --- a/memory/MEMORY.md +++ b/memory/MEMORY.md @@ -12,6 +12,7 @@ - [**Wake-time substrate or it didn't land — learnings must reach CLAUDE.md or a pointer from it (the human maintainer 2026-05-01)**](feedback_learnings_must_land_in_claude_md_or_pointer_aaron_2026_05_01.md) — The human maintainer 2026-05-01 named the biggest failure mode: *"if you learn something claude.md or a pointer from that file like the .claude/rules or some other pointers, you didn't learn it."* Wake-time-load is the test of "learned" — CLAUDE.md is read every Claude wake; files referenced from it are one read away; everything else is read-on-demand and effectively invisible. Discipline: every load-bearing learning must land as (1) CLAUDE.md bullet, (2) memory file + CLAUDE.md pointer, or (3) transitively via AGENTS.md/BP-NN/skill/agent. Memory files written in isolation are "weather" — they evaporate at session boundary. Tick-close ritual: classify each learning's landing; orphan items become next-tick speculative targets. Self-encoding test: this rule's own landing IS the CLAUDE.md bullet pointing at the memory file. Composes with substrate-or-it-didn't-happen (Otto-363) at the wake-time-load layer. - [**Otto-buddy spin-up when "wait" is the obvious answer + goldfish-ontology failure mode (Aaron 2026-05-01)**](feedback_otto_buddy_spin_up_when_waiting_aaron_2026_05_01.md) — Aaron 2026-05-01 — when Otto's obvious-next-action is "wait," that IS the buddy spin-up trigger (kill-switchable named-persona instance, mirror-language sense per `feedback_engagement_under_discipline_not_avoidance_*`). Existing `tools/peer-call/.sh` IS the buddy-spawn surface when Otto holds the PID. Mutual-improvement loop: bidirectional teaching stabilizes both substrates over iterations. Memo's own caused_by chain demonstrates the deeper failure mode Aaron named: **goldfish-ontology** — Otto builds rich ontologies (great at it) but never uses them >30 min before forgetting + recreating the same substrate; the buddy is the active-reminder layer that greps existing ontologies pre-authoring. - [**detect-changes pattern + multi-ruleset architecture — the sibling-repo external anchor as parallel-optimized external anchor (Aaron 2026-05-01)**](feedback_detect_changes_pattern_sibling_repo_parallel_optimized_external_anchor_aaron_2026_05_01.md) — Aaron 2026-05-01: *"`../no-copy-only-learning-agents-insight` is the best repo in github i've seen setup to be parallel."* Direct inspection (DST grade-A pull-to-sibling-repo + gh-api-on-host) revealed: detect-changes.yaml emitting per-change-class outputs (PRs only run relevant checks); 42 fine-grained workflows; bash+PS1 test parallelism pair; **5 concern-aligned rulesets** empirically validating B-0155 architecture; **branch protection effectively empty** (zero contexts, all migrated to rulesets) — proof B-0155 Phase 3 cleanup endpoint works at production scale. The sibling-repo external anchor uses Wiki not Pages; Aaron's prior Jekyll-on-Pages was a workaround, not preference (*"bun is probably enough"*). Attribution: the sibling-repo external anchor is deliberate-by-others (multi-engineer org-scale) vs Aaron-clicked-alone Zeta — high-credibility external anchor. (Distinct from ServiceTitan-the-employer references elsewhere in this index — `../no-copy-only-learning-agents-insight` is a separate sibling repo I inspected; ServiceTitan-related grandfathered memory files retain "ServiceTitan" in their descriptions.) +- [**TS dependencies-as-interface DI pattern — SQLSharp external anchor — super strongly typed not js-in-ts (Aaron 2026-05-01)**](feedback_ts_dependencies_as_interface_di_pattern_sqlsharp_anchor_aaron_2026_05_01.md) — Aaron 2026-05-01: *"`../SQLSharp` is a decent example... best bun/ts practices... super strongly typed... not js in ts failure mode."* SQLSharp (sibling repo, same maintainer) demonstrates the production-grade bun/ts pattern: every external call surface in a `Dependencies` interface (`typeof X`-keyed), defaulted via named const, injected through call chain — every function DST-able by construction. The `formatRepoDependencies` shape in `../SQLSharp/tools/automation/format/format-repo.ts` is the canonical worked example. Composes with the prefer-TS-over-bash rule (this is the form-factor target) + sibling-repo-deep-search discipline (SQLSharp is the bun/ts external anchor; `../no-copy-only-learning-agents-insight` is the parallel-optimization anchor). Non-DST-anchor — Aaron explicitly said "not super DST yet" for SQLSharp. Worked example: poll-pr-gate-batch.ts gap analysis + follow-up refactor target. - [**Prefer TS scripts over dynamic bash for conversation UX + DST achievability (Aaron 2026-05-01)**](feedback_prefer_ts_scripts_over_dynamic_bash_for_conversation_ux_dst_in_ts_aaron_2026_05_01.md) — Aaron 2026-05-01 *"a lot of red bash / pwsh failures"* damages conversation UX (most-humans concern, not Aaron specifically — he's calibrated). Default to pre-existing TS scripts; avoid ad-hoc dynamic bash except when prototyping. **DST is structurally unattainable in bash for general computation; achievable in TS** (seedable PRNG, time injection, native testing, stack traces). EXCEPTION: declarative-bootstrap bash like install.sh + tools/setup/manifests/ is "closest to DST" and is the legitimate-bash zone — Aaron called it *"our ace package management."* Non-install bash with general logic is the TS-port target. **Worked example (PR #1153 2026-05-01)**: `tools/github/poll-pr-gate.ts` (single-PR, v1 5-AI peer convergence) + `tools/github/poll-pr-gate-batch.ts` (multi-PR async parallel wrap) — canonical refresh-world-model tools, pointed at from CLAUDE.md wake-time disciplines. Carved blade: *"dynamic bash is forgotten bash, once useful but never amortized."* - [**Assumed-state vs actual-state — audit horizon must default to "everything currently open" not "what I touched recently" (Aaron 2026-05-01 somatic confirmation)**](feedback_assumed_state_vs_actual_state_audit_horizon_check_aaron_2026_05_01.md) — Aaron's *"fuck yes!!! this is great!!"* signal on the tick-1602Z-a7e1 finding (26 LFG PRs in flight vs 5 I'd been tracking). Distinct failure-class from Otto-363 substrate-or-it-didn't-happen (which guards against directives evaporating) and verify-before-deferring (deferred targets not existing). This rule guards the audit horizon itself: *"Assumed-state is what I touched recently. Actual-state is everything currently open. The horizon must default to actual."* Mechanizable via `gh pr list --state open` at-cold-start. Cross-surface (issues, branches, ferries, TaskList, cron triggers). - [**Same-model + different-harness produces different biases — Cursor vs Claude Code with Opus 4.7 (Aaron 2026-05-01)**](feedback_same_model_different_harness_produces_different_biases_cursor_vs_claude_code_opus_4_7_aaron_2026_05_01.md) — Empirical signal (single-source YouTube): Cursor + Opus 4.7 outperforms Claude Code + Opus 4.7 on some axis. Same model, different harness → different output. Aaron's framing: this IS a legitimate peer/buddy configuration. Bias-source decomposition: prompt + tools + context-mgmt + sampling + output-format + user-flow. Validates multi-harness peer-mode (rung 5 of parallelism ladder) — peer value compounds across model-axis AND harness-axis. Composes with agent-orchestra cluster (#324-339) + Otto-tasks #301/#303 + parallelism-scaling-ladder. diff --git a/memory/feedback_ts_dependencies_as_interface_di_pattern_sqlsharp_anchor_aaron_2026_05_01.md b/memory/feedback_ts_dependencies_as_interface_di_pattern_sqlsharp_anchor_aaron_2026_05_01.md new file mode 100644 index 000000000..1835ab210 --- /dev/null +++ b/memory/feedback_ts_dependencies_as_interface_di_pattern_sqlsharp_anchor_aaron_2026_05_01.md @@ -0,0 +1,242 @@ +--- +name: TS dependencies-as-interface DI pattern — SQLSharp external anchor — super strongly typed not js-in-ts — Aaron 2026-05-01 +description: Aaron 2026-05-01 — *"`../SQLSharp` is a decent example... of best practices not super DST yet the other repo but best bun/ts practices... super strongly typed... not js in ts failure mode."* The SQLSharp repo (sibling of Zeta) demonstrates the production-grade bun/ts pattern Otto should write toward when authoring new tools: every external dependency named in a typed interface (`typeof X`-keyed), defaulted via a named const, injected through the call chain. Every function is DST-able by construction. Composes with the dynamic-bash → TS migration trajectory; SQLSharp is the form factor poll-pr-gate*.ts should evolve toward. +type: feedback +caused_by: + - "Aaron 2026-05-01 nudge cluster after PR #1153 (poll-pr-gate-batch.ts + DST tests) landed: '../SQLSharp is a decent example' + 'of best practices not super DST yet the other repo but best bun/ts practices' + 'super strongly typed' + 'not js in ts failure mode'" + - "Inspection of `../SQLSharp/tools/automation/format/format-repo.ts` (sibling-repo path; absolute filesystem path host-specific) confirmed the pattern (FormatRepoDependencies interface + defaultFormatRepoDependencies const + DI through call chain)" + - "SQLSharp CLAUDE.md explicit rule: *'Prefer strong static types and generics across C#, F#, and TypeScript; push invariants into compiler-checked types and signatures when the design can carry them there.'*" +composes_with: + - feedback_prefer_ts_scripts_over_dynamic_bash_for_conversation_ux_dst_in_ts_aaron_2026_05_01.md + - feedback_dst_grade_a_dependency_source_inspection_pull_to_sibling_repo_for_deep_search_aaron_2026_05_01.md + - feedback_detect_changes_pattern_sibling_repo_parallel_optimized_external_anchor_aaron_2026_05_01.md +--- + +# Rule + +When authoring (or refactoring) a TS tool in Zeta: + +1. **Define a `Dependencies` interface** for every external + call surface — `spawn`, `readFileSync`, `process.exit`, + environment access, network, time, random. Type each via + `typeof X` against the production import. +2. **Define a `defaultDependencies` const** assembling the + production deps once. +3. **Functions take `(args, options, dependencies?)` triple** + where `dependencies` defaults to `defaultDependencies`. +4. **Tests pass synthetic dependencies** — fully deterministic, + no I/O, no clock, no spawn. +5. **No `any`. No implicit `any`.** Every value typed + precisely. Discriminated unions over `string`. `readonly` + on array params. Exhaustive switch / discriminant checks. + +This is the SQLSharp pattern. Aaron's framing — +*"super strongly typed... not js in ts failure mode"* — is +the discriminating axis: TS that's just JavaScript with a +`.ts` extension and `any` escapes is the failure mode; TS +where the type system carries the design invariants is the +target. + +# Why + +Aaron 2026-05-01 (verbatim, four-message clarification): + +> *"`../SQLSharp` is a decent example"* +> *"of best preactices not super DST yet the other repo but +> best bun/ts practices"* +> *"super strongly typed"* +> *"not js in ts failure mode"* + +The clarification stack is itself the lesson: SQLSharp is +**not** the DST anchor (some other repo carries that), but +IS the **bun/ts best-practices anchor** for this factory. +The "super strongly typed" + "not js in ts failure mode" +pair names what the pattern IS (super-strongly-typed) and +what the pattern AVOIDS (js-with-.ts-extension). + +## Why-1: TS without strong types is just JavaScript with extra steps + +The "js-in-ts failure mode" Aaron names is real: + +- `any`-typed values that propagate through the codebase +- `as` casts hiding shape mismatches +- Loose `Record` parameters where a + discriminated union would be clearer +- Optional chaining cascades (`a?.b?.c?.d`) hiding shape + uncertainty the type system could resolve +- Functions that return `Promise` instead of + precise return types +- Interfaces with optional fields everywhere because the + author didn't decide if the field is required + +Each of these defeats one of the type system's purposes. +A codebase saturated with these is "js-in-ts" — TS as +syntactic sugar, not as type-driven design. + +The SQLSharp form actively fights this: every interface is +intentional, every parameter is required-or-optional by +design (not by laziness), every union is exhaustively +discriminated, every spawn-class side effect is captured +in an injectable interface. + +## Why-2: Dependencies-as-interface unlocks DST without tooling + +The pattern the human maintainer points at — `format-repo.ts`, +the `FormatRepoDependencies` interface near the top of the +file — is structural DI without a DI framework. (External +line numbers drift; consult the current file in the sibling +repo via `git -C ../SQLSharp log` for canonical state.) Each +external call surface (process runner, file lister, settings +resolver) is a typed function in the interface. Tests +construct a synthetic interface instance with deterministic +stubs. Production uses a default `default*Dependencies` const +(in `format-repo.ts` named `defaultFormatRepoDependencies`) +that wires real implementations. + +Compared to monkeypatching, vi.mock, jest.fn — the structural +DI form is: + +- Compiler-checked (you can't omit a dep from the synthetic + interface; TS will complain) +- Self-documenting (the interface IS the surface area; you + see exactly what's external) +- DST-grade-A by construction (no global state to mock, + no hidden imports to intercept) +- Refactor-friendly (renaming a dep updates the interface; + consumers fail to compile) + +This is the load-bearing reason "TS is DST-achievable." The +DI pattern IS the achievability vehicle. Bash has no +analogue. + +## Why-3: SQLSharp is the closest live external anchor for the pattern + +Per `feedback_dst_grade_a_dependency_source_inspection_pull_to_sibling_repo_for_deep_search_aaron_2026_05_01.md`, +direct sibling-repo inspection IS the discipline for +calibrating against high-credibility external evidence. +SQLSharp: + +- Lives at `../SQLSharp` (relative to Zeta) — directly + inspectable +- Has explicit type-discipline rule in `CLAUDE.md` + (*"push invariants into compiler-checked types"*) +- Demonstrates the pattern in production code + (`tools/automation/format/format-repo.ts`, + `tools/automation/lib/repo-environment.ts`, + ~30+ TS files in `tools/automation/`) +- Uses `bunfig.toml` with strict test config + (`pathIgnorePatterns`, `coverageSkipTestFiles`) +- Same maintainer (Aaron) — internally-coherent rather + than copy-cargo-cult from random external repo + +The sibling-repo external anchor is high-credibility because +Aaron's pattern there has been refined over time on a real +production .NET library. The pattern transfers to Zeta as +the form factor TS tools should write toward. + +# How to apply + +When authoring or touching a TS tool in `tools/`: + +1. **Read the SQLSharp parallel** before authoring. If + SQLSharp has a similar tool (format, coverage, + environment, validation), match the shape. +2. **List external dependencies** of the tool: every spawn, + read, write, env access, network call, clock, random. +3. **Build a `Dependencies` interface** typed via `typeof` + against the production imports. +4. **Build `defaultDependencies` const** at module scope. +5. **Top-level functions take `(args, options, deps?)` triple**. +6. **Tests pass synthetic `deps`** in `bun test` form. +7. **Run lint + typecheck + tests** before commit to verify + zero `any`, zero implicit `any`, strict mode passing. + In this repo, the script names are `bun run lint:typescript`, + `bun run typecheck`, and `bun run test:typescript` (or + `bun test` for tools). Check `package.json` scripts for + the canonical names; don't trust generic command names + that may not exist. + +When the pattern is hard to apply — a function genuinely +needs no external deps, or the existing tool predates the +pattern — note it. The pattern is the target shape; not +every tool needs the full infrastructure overnight. + +# Worked example — how `poll-pr-gate-batch.ts` should evolve + +Current state (PR #1153 at `5848fa1`): + +- `pollFn` is injectable (the only DST-able boundary) +- Types exported (`GateReport`, `BatchSummary`, etc.) +- `summarize` is pure and testable + +Gaps vs. SQLSharp pattern: + +- `spawnSync` calls in `listOpenPRs` and `pollOne` are + hard-coded — no `runProcess: typeof spawnSync` in a + `Dependencies` interface +- `process.exit` calls scattered through `parseArgs`, + `listOpenPRs` — no `exit: (code: number) => never` + injectable +- `process.stdout.write` / `process.stderr.write` direct — + no `out: (s: string) => void` / `err: (s: string) => void` + injectable +- `new Date()` in `main` (queriedAt) — no `clock: () => Date` + injectable + +A follow-up refactor (separate PR, separate branch) should +extract these into `BatchPollDependencies` + `defaultBatchPollDependencies` +following format-repo.ts shape. That brings the entire +script under the DST-grade-A umbrella, not just `pollAllBounded`. + +# Composes with + +- `feedback_prefer_ts_scripts_over_dynamic_bash_for_conversation_ux_dst_in_ts_aaron_2026_05_01.md` + — the why-bash-fails layer; SQLSharp pattern is the + what-TS-does-instead concrete form. +- `feedback_dst_grade_a_dependency_source_inspection_pull_to_sibling_repo_for_deep_search_aaron_2026_05_01.md` + — the rule about reading sibling repos; SQLSharp is one + of the high-credibility instances of that rule. +- `feedback_detect_changes_pattern_sibling_repo_parallel_optimized_external_anchor_aaron_2026_05_01.md` + — `../no-copy-only-learning-agents-insight` is the + parallel-optimization external anchor; SQLSharp is the + TS-best-practices external anchor. Different anchors, + different domains, same discipline. +- `project_install_script_language_strategy_post_install_typescript_pre_install_bash_powershell_python_for_ai_ml_2026_04_27.md` + — TS is the post-install scripting target language; the + SQLSharp pattern is what good TS looks like at the + factory's quality bar. + +# What this rule does NOT do + +- **NOT a directive to refactor every existing TS tool + immediately.** The pattern is a target shape. Phase the + application: new tools follow the pattern; refactors + apply when touched. +- **NOT a ban on simpler TS for one-off prototypes.** + Aaron's prototype carve-out (per + `feedback_prefer_ts_scripts_over_dynamic_bash_*`) still + applies. Quick TS scripts that do a one-off don't need + full DI infrastructure. +- **NOT a claim SQLSharp is the only valid anchor.** Other + TS-strong repos exist (Effect-TS ecosystem, fp-ts, etc.). + SQLSharp is the *closest, sibling-repo* anchor with + consistent maintainer-discipline. External anchors + rotate as new evidence lands. +- **NOT a ban on `any` in third-party-shape parsing.** When + parsing JSON of unknown shape (e.g., `gh api` output that + GitHub may evolve), narrow types via runtime checks + + type guards. The `any` ban applies to *internal* types + not external-API-shape parsing where validation IS the + type-narrowing step. + +# Carved sentence (candidate, not seed-layer yet) + +*"Super-strongly-typed TS, not js-in-ts. Every external +call surface in an interface. Every function takes its +dependencies. The default const wires production; the test +constructs the synthetic. The pattern IS the DST achievability +vehicle."* (Aaron 2026-05-01.) + +(Marked candidate per CSAP. Has not been multi-domain-tested. +Promotes via Razor + CSAP under DST grading on cadence, not +by maintainer fiat.)