fix(planning): don't plan pure-auth slices the BoringStack starter already ships#109
Merged
Conversation
…lready ships Observed live: for a bookmark-manager build the planner proposed two slices, User and Bookmark. But BoringStack ships auth/users/sessions out of the box — the real login/signup code references locale keys under `auth.*`. The model, scoped to build a `features/user/**` slice, created a PARALLEL set of `features.user.errors.*` keys that were unused by construction (real usage is `auth.*`), so the i18n-locale-keys gate looped forever on "unused key" — add key (slice says build it) → gate says unused → remove → re-add. The build oscillated 80+ turns at 1 error on a slice that can never go green because it duplicates the built-in surface. Fix (defense in depth): - PLANNER_SYSTEM now states the stack already provides auth/users/sessions and must NOT propose a User/Account/Auth/Session/Login/SignUp/Profile slice — treat "a user" as an existing actor entities belong to. - Enforcement backstop: stripReservedSlices() drops any slice whose entity id is a reserved identity concept (RESERVED_ENTITY_IDS), applied to every proposePlan result. If stripping would empty the plan, the original is kept (an empty plan builds nothing — worse than one redundant slice). Tests: stripReservedSlices drops User keeps Bookmark; keeps all when every slice is reserved; proposePlan strips the exact live User+Bookmark collision to Bookmark; PLANNER_EXAMPLE proposes no reserved entity.
…odule, keep the generic planner clean The prior version hardcoded 'the stack already provides authentication' into the generic PLANNER_SYSTEM and stripped reserved slices on EVERY plan — leaking a BoringStack assumption into the core planner used for other/plain builds, where it would lie to the model and silently delete a legitimate User entity. - Generic planner is stack-agnostic again: proposePlan takes optional IPlanConstraints (now in plan-types.ts) — default = no guidance, NO stripping. A plain build keeps a User entity (regression-tested). - New boringstack-planning module (fully unit-tested) owns the stack specifics: looksLikeBoringstack (STRUCTURAL detection — apps/api + apps/ui + infra/compose, not a lone folder or a receipt a hand-clone lacks), the auth guidance, the pure-auth reserved set (ambiguous nouns Account/Session/Profile/Credential kept), and boringstackPlanConstraints (onStripped REQUIRED — drops are always surfaced, never silent). - repl uses ONE signal (looksLikeBoringstack) for BOTH the planning interception AND the constraints, closing the gap where a project was planned as boringstack but not given the rule. The ~100-line inline block is extracted to runGreenfieldPlanning, dropping the line handler's cognitive complexity back under 20. - stripReservedSlices takes the reserved set as a parameter; gen-plan scratch helper removed from the tree. Tests: stack-agnostic (no constraints keeps User, base prompt says nothing about auth); looksLikeBoringstack (all markers → true, apps/api-only → false); boringstackPlanConstraints (guidance/reserved + onStripped plumbed); onStripped surfaces drops; runPlanning forwards constraints; BoringStack strip/retry/null-on-all-auth.
3e4aa94 to
aa81a41
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Live: for a bookmark app the planner proposed
User+Bookmark. The stack ships auth/users/sessions, so the real login/signup code uses locale keys underauth.*— the model's parallelfeatures.user.*keys were unused by construction, thei18n-locale-keysgate looped forever, and the build parked (80+ turns). (Root-caused by the reviewer diagnose panel.)Fix (defense in depth)
PLANNER_SYSTEMstates auth/users/sessions already exist and must not be rebuilt (noUser/Auth/Login/SignUp/Logoutentity) — while explicitly permitting genuine domain entities that share a word (a billingAccount, a therapySession, a socialProfile).stripReservedSlicesdrops slices whose id is a reserved pure-auth term (user/users/auth/authentication/login(s)/signin(s)/signup(s)/logout(s)). Deliberately narrow — ambiguous domain nouns are NOT reserved, so those products keep their features.proposePlanretries once (temp 0.7 may yield real slices) and returnsnullonly if the retry is also all-auth — a finite planning failure, never a plan that re-emits the trap.Tests (typed fixtures, no
ascasts)Drops
Userbut keepsBookmark; drops case/plural variants (users/SignUp/LogIn/AUTH); keepsAccount/Session/Profile/Credential; strips on both the first and temp-0.7 retry path; all-auth on both attempts →null(call count pinned); an all-auth first attempt retries and recovers a real second plan.Review
Reviewer panel: PASS (after 3 iterations — the panel caught an
as-cast, an over-broad silent denylist, a trap-re-emitting fallback, and a prompt/code contradiction; all fixed). Fullbun run validategreen.