From 125c1e9777d66645cf23b30b3d2de1c91fb492aa Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Thu, 16 Jul 2026 13:24:24 -0500 Subject: docs(design): record the subproject-pattern proposal, defer promotion home proposed promoting its subproject pattern (a folded-in standalone project living as a self-contained subdir under a parent's scope) into the rules layer. The pattern reads as sound. I deferred it on evidence rather than merit, and preserved both the proposal and home's worked instance here so the decision has its source. Two findings drove the deferral. It's N=1: across all 27 agent scopes, home is the only project with subprojects, and all nine came from one fold. There's no second instance to say which parts are general and which are home-shaped. The placement also contradicts the proposal's own argument. Rules load into every session of every project, and the doc argues that layer is a tax paid whether or not it's relevant, with depth belonging one open away. At 282 lines it would be the third-largest rule and add ~11% to the layer, so every unrelated project would carry a one-project convention. I want to scout which projects would actually get subprojects, and why, before shaping anything. That evidence decides whether the pattern gets dropped or adjusted. Two things to fix if it ever promotes: the doc cites a privacy-model rule that doesn't exist (the real content is the gitignore-vs-track and public-reachability decision), and about half of it is home's instance rather than rule content. --- .../2026-07-15-subproject-pattern-proposal.org | 22 ++ ...-07-15-subprojects-convention-home-instance.org | 282 +++++++++++++++++++++ todo.org | 39 +++ 3 files changed, 343 insertions(+) create mode 100644 docs/design/2026-07-15-subproject-pattern-proposal.org create mode 100644 docs/design/2026-07-15-subprojects-convention-home-instance.org diff --git a/docs/design/2026-07-15-subproject-pattern-proposal.org b/docs/design/2026-07-15-subproject-pattern-proposal.org new file mode 100644 index 0000000..61ade18 --- /dev/null +++ b/docs/design/2026-07-15-subproject-pattern-proposal.org @@ -0,0 +1,22 @@ +#+TITLE: Proposal: promote the "subproject" pattern into the claude-r +#+SOURCE: from home +#+DATE: 2026-07-15 23:24:07 -0500 + +Proposal: promote the "subproject" pattern into the claude-rules layer. + +WHAT WE DID (in home, 2026-07-15) +We named and built a pattern for what happens when a standalone project is consolidated into another project. home absorbed nine former projects on 2026-06-11 (danneel, finances, jr-estate, kit, health, documents, clipper, elibrary, philosophy). We now call each folded-in unit a "subproject": a former standalone project that lives as a subdirectory, shares the parent's .ai/ scope (one session, one toolchain), but keeps its own files, assets, and history self-contained under its subdir. + +The pattern has four parts: +1. Vocabulary — parent project, subproject, consolidation (the process), subproject archiving. Terminology so we can talk precisely about where a subproject's documents/assets live and archive them cleanly. +2. Subproject brief — a read-first orientation doc at /-brief.org (situation, current state, reading list, and for deep ones cast/timeline/key-facts-with-verify-flags). The parent's notes.org holds a thin index + a read-first rule + pointers to urgent items only, never a copy of subproject substance ("one fact, one home"). +3. Lifecycle criteria — when to CREATE a subproject (consolidate: domain fit, low independent cadence, shared-scope safety re: privacy/remote posture, no independent collaborators), and when/how to ARCHIVE one cleanly (terminal state -> move the self-contained subdir to /archive/, reconcile pointers/links/tags, manifest note). +4. Instrumentation — a use/miss log, metrics weighted toward Craig-caught errors over self-report, review folded into task-audit, and a falsifiable kill criterion. + +WHY IT'S GENERAL (not just a home thing) +Consolidating a project into another drops what the former project's own startup used to auto-load (its full depth), so sessions start cold and re-read files. That failure recurs whenever ANY project folds into another. The pattern also gives consolidation and archiving a named, repeatable shape, and the self-contained-subdir rule is what makes archiving a move-plus-pointer-reconcile instead of an excavation. + +THE PROPOSAL +Promote this to a rulesets claude-rule (e.g. claude-rules/subprojects.md): the vocabulary, the brief convention, the parent-vs-subproject content criterion, and the create/archive criteria. Any parent/hub project would then inherit it. home's .ai/subprojects.org (attached next) becomes the local instance/index under the general rule. It's a companion to working-files.md (in-progress artifact layout) and docs-lifecycle.md (formal-doc lifecycle) — same family, different scope: this one governs whole-subproject orientation and lifecycle. + +Attached: the home instance .ai/subprojects.org as the reference draft to adapt. Apply your value gate; this is a proposal, not a synced-file edit. diff --git a/docs/design/2026-07-15-subprojects-convention-home-instance.org b/docs/design/2026-07-15-subprojects-convention-home-instance.org new file mode 100644 index 0000000..a1c4397 --- /dev/null +++ b/docs/design/2026-07-15-subprojects-convention-home-instance.org @@ -0,0 +1,282 @@ +#+TITLE: Subprojects — Convention +#+AUTHOR: Craig Jennings +#+DATE: 2026-07-15 + +# The reference spec for the subproject pattern: what a subproject is, when to +# create one (consolidation), how to keep it legible (the brief + content +# split), and how to archive one cleanly. Not read every session — the +# always-on parts (the subproject index + the read-first rule) live in +# notes.org and point here. Read this when consolidating a project, creating +# or maintaining a subproject brief, or archiving a subproject. + +* Vocabulary (say it the same way every time) + +The terminology is the point — it's what lets us talk precisely about where a +subproject's documents and assets live, and archive them cleanly. + +- *Parent project* (a.k.a. hub) — a top-level project that owns an =.ai/= + scope: its own protocols, session cadence, memory, inbox, todo. home, work, + rulesets, .emacs.d are parent projects. Reached by launching an agent + session in its directory. +- *Subproject* — a formerly-standalone project that has been *consolidated* + into a parent and now lives as a subdirectory of it (=danneel/=, + =finances/=, =kit/= …). A subproject shares the parent's =.ai/= tooling and + session — it is not a separate agent scope — but keeps its own working + files, assets, notes, and history self-contained under its one subdirectory. +- *Consolidation* — the process of turning a standalone project into a + subproject of a parent. (home's nine subprojects were consolidated on + 2026-06-11.) The inverse — promoting a subproject back to a standalone + project — is rare but allowed; it's just consolidation run backward. +- *Subproject archiving* — retiring a completed or abandoned subproject + cleanly. Because a subproject is self-contained under one subdirectory, + archiving is a move plus a pointer reconcile, not an excavation. +- *Subproject brief* — the read-first orientation doc for one subproject, at + =/-brief.org=. + +The cross-project boundary rule (=claude-rules/cross-project.md=) governs +*parent* projects, which are separate =.ai/= scopes. It does *not* apply +between a parent and its subprojects — they share one scope. + +* Why the pattern exists + +As a standalone project, each of these units auto-loaded its own notes.org — +its full depth — at every startup, so recall felt instant. Consolidated into a +parent, a subproject is one compressed section competing with the others, and +the parent's startup surfaces hub-wide state, not any one subproject's depth. +So a session starts cold on a given subproject and re-reads several files on +demand. This convention restores fast, accurate orientation without +re-bloating what loads every session — and gives consolidation and archiving a +named, repeatable shape. + +* Document & asset location (what makes clean archiving possible) + +Everything for a subproject lives under =/= — its =notes.org=, +=assets/=, working files, event log, briefs. Links *within* a subproject are +relative to the subproject dir, so the whole tree can move without breaking +them. The parent's own top-level =assets/= is for parent-level material only, +never a subproject's. This self-containment is exactly what lets archiving be +a single =mv= plus a pointer reconcile. Keep it strict: a subproject's asset +in the parent's shared =assets/= is a future broken link. + +* The two layers (parent vs subproject) + +- *Always-on layer* — the parent's notes.org. Read at every startup, so every + line is a tax paid whether or not it's relevant today. Holds only what must + be seen session-independently. +- *On-demand layer* — the subproject brief + the subproject's notes.org. + Loaded only when working that subproject. Holds the depth. + +The whole design is: sort content by *when it's needed*, keep the always-on +layer thin, put the depth one open away. + +* Creating a subproject (consolidation criteria) + +Consolidate a standalone project into a parent as a subproject when *all* hold: + +1. *Domain fit* — the project is a facet of a domain the parent already owns + (danneel is home life-admin; finances is home). +2. *Low independent cadence* — it no longer needs its own session rhythm. + You'd rather reach it from the parent than launch it standalone, and its + standalone startup/sync/session overhead now outweighs the isolation. +3. *Shared-scope safety* — it does not need a git/remote/visibility posture + distinct from the parent. A public code project, a team repo, or anything + with its own CI or gitignore-privacy posture *stays standalone* — folding + it would break the parent's privacy model (see + =claude-rules/git-hosting-privacy-model= and the gitignore-vs-track + decision). Personal/documentation units fold; code-with-a-public-remote + does not. +4. *No independent collaborators* depend on it as a standalone deliverable. + +Keep it standalone when any of those fail: active independent development, its +own team or remote, a distinct visibility/security posture, or activity high +enough that competing in the parent's hub would bury it. + +*The consolidation act itself* (mechanics, mirroring home's 2026-06-11 fold): +move the project tree under the parent as =//=; import its +tasks into the parent's todo with an area =:tag:= and a =:MIGRATED_FROM:= +property; fold its live reminders/decisions into the parent's notes as +pointers (see the content split); build the subproject brief; record the fold +in a consolidation manifest (=docs/consolidation-manifest-.org=). +Retire the source to =~/projects/.retired/= once parity is verified. + +* The subproject brief + +** Path (fixed — discovery is mechanical) + +=/-brief.org= (=danneel/danneel-brief.org=, +=finances/finances-brief.org=). The subproject name is the directory name, so +the brief name follows for free. One predictable name means the read-first +rule never has to hunt; put descriptive richness *inside*, not in the filename. + +** Spine (scales from light to deep) + +Required in every brief, even a fifteen-line one: +- *One-paragraph situation* — what this subproject is, in plain language. +- *Current state / open threads* — the live stuff. The only high-churn + section; everything else is stable. +- *Reading list* — the subproject's deeper files and what each holds. The + brief *points into* notes.org and the rest; it does not copy them. + +Add only where the subproject warrants it (danneel, jr-estate, finances earn +all of these; elibrary or documents may earn none): +- Cast / contacts. +- Timeline (for matters with history). +- Key facts / numbers, with explicit *verify* flags anywhere the underlying + record disagrees with itself. A brief that asserts a wrong number is worse + than no brief — flag, don't guess. + +** Read-first rule (the behavior) + +When a session's work targets a subproject — a file under =/=, its +=:tag:=, or Craig naming the topic — open =/-brief.org= +*first*, before touching anything else in it. If the subproject has no brief +yet, creating it is the first step of the work (lazy backfill), and the same +pass reconciles that subproject's parent-vs-subproject content. + +* Parent-vs-subproject content criterion + +The test for any piece of content: *if next session I'm working a different +subproject, do I still need to see this?* Three bins: + +1. *Yes, and it's a fact or policy* → hub-level → the parent's notes.org. + Machine names, mail policy, calendar access, the hub map, the subproject + index. +2. *Yes, but only because it's urgent* — a deadline or blocking status that + would be missed if it only lived where I might not look this week → the + parent holds a *one-line pointer* (item + date + "see the subproject + brief"); the substance stays in the subproject. +3. *No* → the subproject. Working depth: contacts, contract facts, case + theory, evidence, document index, and any reminder that isn't time-critical. + +One hard rule over both axes: *one fact, one home.* The parent never copies +subproject substance — it points. The parent holds the trigger; the subproject +holds the truth. Every parent↔subproject duplicate is a second surface that +goes stale. + +* Archiving a subproject (archiving criteria + clean process) + +Archive a subproject when it reaches a *terminal* state: +- *Complete* — the work is done and closed (a settlement signed, a probate + closed, a trip finished): no live threads, no open tasks, nothing + time-sensitive in the parent still pointing at it; or +- *Abandoned / superseded* — dropped, or replaced by other work. + +Clean archive process (self-containment is what makes each step a one-liner): +1. Close or settle its tasks in the parent's todo (DONE / CANCELLED), per the + todo completion rules. +2. Move the whole subproject tree to the parent's archive: + =/archive//= (keep it intact — archiving is reversible, + not deletion). +3. Update inbound =file:= links that pointed into it (grep first, per the + keep-links-current rule). +4. Move or retire its brief with it, and drop its row from the active + subproject index (or mark it =archived= there). +5. Strip its pointers/reminders from the parent's always-on layer, and retire + its =:tag:= from active use. +6. Record the archive in a manifest note + (=docs/archive-manifest-.org=): why, when, where it moved, + what links were repointed. Mirrors the consolidation manifest. + +The =:LAST_UPDATED:= on a brief plus "no open tasks under the tag" is the +signal a subproject is a candidate for archiving — surfaced at the review +cadence, never auto-archived. + +* Freshness + +- *Wrap-up hook*: at wrap-up, for each subproject touched this session, refresh + its brief's Current-state section and bump its =:LAST_UPDATED:= date. Stable + sections rarely change, so this is cheap. +- *Staleness nudge*: a brief whose =:LAST_UPDATED:= is old while its subproject + was recently active is worth surfacing at startup. + +* Self-improvement loop + +Every real use emits a signal, and the signal is *captured*, not silently +acted on: +- Brief answers the question → *hit*. +- Brief is missing something, stale, or wrong → *miss*, logged in + [[file:subprojects-log.org][subprojects-log.org]]. +- Each miss drives *two* updates: *local* (fix that brief) and, if the same + kind of miss recurs across subprojects, *structural* (fix this spine/spec, + not just the one file). The structural half is the actual self-improvement — + grow-and-refine from real use rather than rewriting from scratch (the ACE + idea behind the =codify= skill). + +* Metrics + +Split by who can trust them. + +*Process signals (I observe, cheaply):* +- *Orientation cost* — files/tool-calls before my first correct action in a + subproject. Target: ~1 (the brief), occasionally a second deep dive. +- *Brief hit rate* — fraction of subproject questions answered from the brief + alone. Should climb. +- *Freshness gap* — days between =:LAST_UPDATED:= and last subproject activity. + Target ~0. + +*Outcome signals (Craig is ground truth — weight these over the above):* +- *Craig-caught errors* — the real quality bar. Target: trend to zero. If + briefs work, Craig stops catching me. +- *Felt speed* — did dropping into the subproject feel fast and right. + +*Honesty caveat.* Most process signals are self-observed, and self-report is +biased toward "hit." So the external signals (Craig-caught errors, felt speed) +outrank mine, and the log is auditable so Craig can spot-check my self-grades. +The instrumentation must stay lighter than the briefs, or it rots like an +unmaintained brief. Small N, no clean A/B — this is directional evidence, not +proof. + +* Review cadence + +Fold a "subprojects health" check into the existing task-audit cadence: read +the log, look at the hit-rate / correction / freshness trends, flag any +subproject that's gone terminal (archive candidate), and check the +parent-vs-subproject criterion — anywhere the parent holds a copy where it +should hold a pointer. Decide continue / adjust / kill for the pattern itself. + +* Kill criteria (falsifiable) + +After ~6-8 subproject-sessions across ≥3 subprojects, drop or rework the +pattern if: +- the correction rate isn't falling, or Craig is still catching errors; or +- the freshness gap keeps reopening despite the wrap-up hook; or +- maintenance costs more time than the orientation it saves. + +Success is the mirror: orientation down to ~1 read, Craig catching ~nothing, +briefs current, and I'm right fast in any subproject cold. + +* Rollout + +- Define the convention (this file) + the index scaffold in notes.org. Done + 2026-07-15. +- *Lazy backfill*: the next session that touches a subproject with no brief + creates the brief as its first step — cost paid exactly when it's used. +- *Reconcile in the same pass*: building a subproject's brief includes + reconciling its parent-vs-subproject content — push substance down, leave + pointers up, drop dead reminders. +- *Promotion*: this pattern is home-instanced but general. Consolidation into + subprojects will recur whenever any project folds into another, so this is a + candidate to promote into the rulesets rules layer (proposed to rulesets + 2026-07-15). + +* Adoption status + +| Subproject | Brief exists | Reconciled | Notes | +|------------+--------------+------------+---------------------------------------| +| danneel | yes | yes | First worked instance, 2026-07-15. | +|------------+--------------+------------+---------------------------------------| +| clipper | no | no | Lazy backfill on next touch. | +|------------+--------------+------------+---------------------------------------| +| documents | no | no | Lazy backfill on next touch. | +|------------+--------------+------------+---------------------------------------| +| elibrary | no | no | No notes.org yet; lightest subproject.| +|------------+--------------+------------+---------------------------------------| +| finances | no | no | Deep; earns the full spine. | +|------------+--------------+------------+---------------------------------------| +| health | no | no | Has its own notes.org. | +|------------+--------------+------------+---------------------------------------| +| jr-estate | no | no | Deep; earns the full spine. | +|------------+--------------+------------+---------------------------------------| +| kit | no | no | Lazy backfill on next touch. | +|------------+--------------+------------+---------------------------------------| +| philosophy | no | no | Lazy backfill on next touch. | diff --git a/todo.org b/todo.org index 2a8a999..7c04560 100644 --- a/todo.org +++ b/todo.org @@ -48,6 +48,45 @@ triage-intake.org), live trial night on rulesets. Origin: work project's proposal, [[file:docs/design/2026-07-14-sentry-workflow-proposal.org][docs/design/2026-07-14-sentry-workflow-proposal.org]]. All nine design decisions resolved with Craig 2026-07-14 (recorded in the spec). +** TODO [#C] Subproject pattern — promote to claude-rules? :spec: +SCHEDULED: <2026-07-20 Mon> +home proposes promoting its subproject pattern (a former standalone project +folded into a parent, living as a self-contained subdir sharing the parent's +=.ai/= scope) into the rules layer: vocabulary, the read-first +=/-brief.org= convention, the parent-vs-subproject +content criterion ("one fact, one home"), and create/archive criteria. +Proposal + home's full instance: +[[file:docs/design/2026-07-15-subproject-pattern-proposal.org][proposal]], +[[file:docs/design/2026-07-15-subprojects-convention-home-instance.org][home's convention doc]]. + +Deferred 2026-07-16 rather than promoted. *Craig's framing:* he wants to scout +which projects would actually get subprojects, and why, before we shape a rule. +If he hasn't done that scouting by the time this comes up, offer to do it +together — brainstorm the candidates, then explore the reasons behind each. That +evidence decides it: either we drop the pattern, or we know enough to adjust it +so it's effective. Don't shape the rule before the scouting. + +*Review findings from the 2026-07-16 pass* (the inputs the decision needs): + +- *N=1.* home is the only project with subprojects, across all 27 =.ai= scopes; + its nine all came from the single 2026-06-11 fold. This is the fact the + scouting tests. +- *Placement contradicts the proposal's own principle.* =claude-rules/*.md= + loads into every session of every project. home's doc argues the always-on + layer is "a tax paid whether or not it's relevant today" and depth belongs + "one open away". At 282 lines the doc would be the third-largest rule and add + ~11% to the always-on layer, so every .emacs.d / takuzu / chime session would + carry a one-project convention. +- *Precedent for the shape:* =patterns.md= (29 lines, explicit "don't carry the + catalog in context") and =docs-lifecycle.md= (75 lines, depth in a spec). + Thin rule + on-demand depth is the established answer. +- *Dangling reference:* the doc cites =claude-rules/git-hosting-privacy-model= + as authority for its shared-scope-safety criterion. No such file exists — the + real content is the gitignore-vs-track and public-reachability decision in + =protocols.org=. Fix before any promotion. +- *Instance vs rule:* the metrics, self-improvement log, kill criteria, rollout + dates, and adoption table are home's instance, not rule content. + ** TODO [#D] Cross-host roam conflict surfacing :feature: Deferred from the sentry spec (Decision: host-local lock only). The roam-write lock serializes same-host agents; a true cross-host race still -- cgit v1.2.3