Skip to content

Latest commit

 

History

History
61 lines (47 loc) · 4.1 KB

0004-project-scoped-instincts.md

File metadata and controls

61 lines (47 loc) · 4.1 KB

ADR 0004 — Scope learned instincts to the project by default, promote to global only on repeated evidence

Status: Implemented (v2.1 extension) · Area: continuous-learning-v2 · Skill: continuous-learning-v2

Problem

continuous-learning-v2 starts from an open-source base skill (origin: ECC) that captures tool-call observations via hooks and distills them into scored "instincts" — small, reusable learned behaviors. That base stored every instinct in a single global pool. In practice, that meant a convention learned in one project (a React component pattern, a project-specific test-naming rule) would surface as a "learned instinct" inside an unrelated Python or Rust project where it didn't apply — noise at best, actively wrong guidance at worst.

Options considered

Option Pros Cons
A. Keep a single global instinct pool (the inherited default) Simple; every instinct visible everywhere Cross-project contamination — instincts from one project's conventions leak into unrelated ones
B. Fully isolate instincts per project, no promotion path No contamination, ever Genuinely universal instincts ("always validate input at a boundary") have to be re-learned independently in every project
C. Project-scoped storage by default, with an explicit promotion path to global once evidence crosses a bar No contamination for project-specific instincts; universal ones still generalize, but only after proof Requires a project-identity mechanism that's stable across machines, and a promotion policy to design and tune

Decision

Option C. Each project gets its own instinct storage partition, keyed by a hash of its git remote URL (with any embedded credentials stripped before hashing, and a fallback to a repo-path hash for projects with no remote) — chosen specifically so the same repository checked out on two different machines still maps to the same project identity. Global-scope instincts still exist, but an instinct only reaches global scope through an explicit promote step, gated on being independently observed in two or more separate projects at a high average confidence — not on being merely useful once.

On load, project-scoped instincts take precedence over global ones with the same ID, so a project-specific override always wins over a generalized default.

Reasoning

  • Git-remote hashing solves the "same repo, different machine" identity problem that a raw filesystem path can't — a path-based identity would treat the same project checked out to two different laptops as two different projects, defeating the purpose of learning at all.
  • Requiring cross-project repetition before promotion is a deliberately conservative bar. A single project's convention is not evidence that a pattern is universal; the promotion gate exists specifically to prevent one project's idiosyncrasy from being generalized prematurely.
  • Credential-stripping before hashing is a small but real security detail — a remote URL can legitimately contain an embedded token, and hashing it unmodified would mean a credential rotation silently changes a project's identity (and, worse, means the raw credential briefly exists in memory on the way to becoming a hash input in an untrusted code path).

Consequences

  • A migration path was needed for existing instinct data that predated credential-stripping — the system detects when stripping changes a project's computed hash and renames the existing storage directory rather than orphaning old data.
  • Two directories now exist per learning system installation (project-scoped and global) instead of one — slightly more bookkeeping in the CLI, in exchange for isolation that has already prevented real cross-project noise.

Future reconsiderations

  • The two-project promotion threshold is a starting point, not a proven-optimal number; if it proves too conservative (genuinely universal instincts taking too long to generalize) or too loose (noise reaching global scope), it's a single tunable value to revisit — not a structural change.