The gap
ytstack:init-project has two paths:
- Pitch present (
OFFICE-HOURS.md exists) → consume it, populate PROJECT.md.
- No pitch → write placeholder
PROJECT.md and tell the user to run office-hours.
The most common real-world case — an existing codebase with its own README.md, docs/, runbooks, CHANGELOG.md, sometimes docs/adr/ — is treated as case 2. The skill ships a useless placeholder, even though 80% of the answers (one-liner, runtime services, env vars, deploy target, decisions, runbooks) are already in the repo. Running office-hours against a shipped product to retroactively "validate the premise" is theater.
This bites the moment anyone adopts ytstack on a project they didn't start with it. We just hit it on a Next.js app that's been in production for months — full details + a written-up gap list at .ytstack/FRICTION-NOTES.md in that repo.
Proposal: third mode brownfield-import
Additive. No behavior change for existing greenfield users.
Detection
In the preamble, count brownfield signals:
_BROWNFIELD_SIGNALS=0
[ -f README.md ] && [ "$(wc -l < README.md)" -gt 30 ] && _BROWNFIELD_SIGNALS=$((_BROWNFIELD_SIGNALS+1))
[ -d docs ] && [ "$(ls docs/*.md 2>/dev/null | wc -l)" -gt 2 ] && _BROWNFIELD_SIGNALS=$((_BROWNFIELD_SIGNALS+1))
[ -f CHANGELOG.md ] && _BROWNFIELD_SIGNALS=$((_BROWNFIELD_SIGNALS+1))
[ -d docs/adr ] && _BROWNFIELD_SIGNALS=$((_BROWNFIELD_SIGNALS+1))
[ -f package.json ] && [ "$(git log --oneline 2>/dev/null | wc -l)" -gt 50 ] && _BROWNFIELD_SIGNALS=$((_BROWNFIELD_SIGNALS+1))
If BROWNFIELD_SIGNALS >= 2 AND PITCH = none → route to brownfield-import instead of greenfield-placeholder.
Backfill behavior
PROJECT.md one-liner — first non-heading paragraph of README.md as candidate.
KNOWLEDGE.md — auto-link every docs/*.md with a one-line summary read from the H1.
RUNTIME.md — derive from package.json scripts, .env.example keys, docker-compose.yml services, .github/workflows/deploy-*.yml target.
DECISIONS.md — if docs/adr/ or docs/DECISIONS.md exists, link/inherit instead of overwriting.
Other small things in scope
- The "Anti-Pattern" section at the top of the skill currently only addresses "too small for ytstack". Add a sibling clause: too mature for greenfield ceremony — use brownfield-import instead.
- Add a
tracker: annotation in STATE.md so projects whose issue-level execution lives elsewhere (Linear, GitHub Projects, Paperclip, Jira) don't get pestered by plan-milestone / reassess-roadmap to create milestones for BAU work.
Out of scope but worth a follow-up
The init-project sentinel ~/.ytstack/.init-project-<slug>-completed is keyed by basename(cwd), not by repo remote URL — two repos with the same folder name on the same machine collide. Edge case but real for collection directories (e.g. monorepo-of-repos layouts).
Happy to PR this if there's interest. The detection + backfill is mechanical, the bigger question is whether you want brownfield-import as a parallel third path or as a flag on the existing flow (--brownfield).
Real-world artifact: https://github.com/lx-0/SunoFlow/blob/main/.ytstack/FRICTION-NOTES.md
The gap
ytstack:init-projecthas two paths:OFFICE-HOURS.mdexists) → consume it, populatePROJECT.md.PROJECT.mdand tell the user to runoffice-hours.The most common real-world case — an existing codebase with its own
README.md,docs/, runbooks,CHANGELOG.md, sometimesdocs/adr/— is treated as case 2. The skill ships a useless placeholder, even though 80% of the answers (one-liner, runtime services, env vars, deploy target, decisions, runbooks) are already in the repo. Runningoffice-hoursagainst a shipped product to retroactively "validate the premise" is theater.This bites the moment anyone adopts ytstack on a project they didn't start with it. We just hit it on a Next.js app that's been in production for months — full details + a written-up gap list at
.ytstack/FRICTION-NOTES.mdin that repo.Proposal: third mode
brownfield-importAdditive. No behavior change for existing greenfield users.
Detection
In the preamble, count brownfield signals:
If
BROWNFIELD_SIGNALS >= 2ANDPITCH = none→ route tobrownfield-importinstead of greenfield-placeholder.Backfill behavior
PROJECT.mdone-liner — first non-heading paragraph ofREADME.mdas candidate.KNOWLEDGE.md— auto-link everydocs/*.mdwith a one-line summary read from the H1.RUNTIME.md— derive frompackage.jsonscripts,.env.examplekeys,docker-compose.ymlservices,.github/workflows/deploy-*.ymltarget.DECISIONS.md— ifdocs/adr/ordocs/DECISIONS.mdexists, link/inherit instead of overwriting.Other small things in scope
tracker:annotation inSTATE.mdso projects whose issue-level execution lives elsewhere (Linear, GitHub Projects, Paperclip, Jira) don't get pestered byplan-milestone/reassess-roadmapto create milestones for BAU work.Out of scope but worth a follow-up
The init-project sentinel
~/.ytstack/.init-project-<slug>-completedis keyed bybasename(cwd), not by repo remote URL — two repos with the same folder name on the same machine collide. Edge case but real for collection directories (e.g. monorepo-of-repos layouts).Happy to PR this if there's interest. The detection + backfill is mechanical, the bigger question is whether you want
brownfield-importas a parallel third path or as a flag on the existing flow (--brownfield).Real-world artifact: https://github.com/lx-0/SunoFlow/blob/main/.ytstack/FRICTION-NOTES.md