diff --git a/src/cascadingdev/setup_project.py b/src/cascadingdev/setup_project.py index 8c2baa8..176f58d 100644 --- a/src/cascadingdev/setup_project.py +++ b/src/cascadingdev/setup_project.py @@ -246,13 +246,22 @@ def seed_process_and_rules(target: Path): copy_if_missing(t_rules_features, rules_dir / ".ai-rules.yml") def seed_initial_feature(target: Path, req_fields: dict | None): + """ + Create the initial feature request file. + + This function ONLY creates request.md - the automation system will generate + the discussion and summary files when request.md is committed. + + This avoids race conditions where setup tries to create files that the + pre-commit hook also wants to generate. + """ today = datetime.date.today().isoformat() feature_id = f"FR_{today}_initial-feature-request" fr_dir = target / "Docs" / "features" / feature_id disc_dir = fr_dir / "discussions" disc_dir.mkdir(parents=True, exist_ok=True) - # Gather values from Ramble result (if any) + # Gather values from the Ramble result (if any) fields = (req_fields or {}).get("fields", {}) if req_fields else {} # Load FR template + META fr_tmpl = INSTALL_ROOT / "assets" / "templates" / "feature_request.md" @@ -286,69 +295,21 @@ def seed_initial_feature(target: Path, req_fields: dict | None): **Meta**: Created: {today} """ + # Write ONLY request.md - let automation generate the rest (fr_dir / "request.md").write_text(render_placeholders(fr_body, values), encoding="utf-8") - # --- feature.discussion.md --- - disc_tmpl = INSTALL_ROOT / "assets" / "templates" / "feature.discussion.md" - d_meta, d_body = load_template_with_meta(disc_tmpl) - # Always include the front-matter for rules, then template body (or fallback) - fm = f"""---\ntype: discussion\nstage: feature\nstatus: OPEN\nfeature_id: {feature_id}\ncreated: {today}\n---\n""" - if not d_body.strip(): - d_body = ( - "## Summary\n" - f"Initial discussion for {feature_id}. Append your comments below.\n\n" - "## Participation\n" - "- Maintainer: Kickoff. VOTE: READY\n" - ) - (disc_dir / "feature.discussion.md").write_text(fm + render_placeholders(d_body, values), encoding="utf-8") - - # --- feature.discussion.sum.md --- - sum_tmpl = INSTALL_ROOT / "assets" / "templates" / "feature.discussion.sum.md" - s_meta, s_body = load_template_with_meta(sum_tmpl) - if s_body.strip(): - # use template - (disc_dir / "feature.discussion.sum.md").write_text(render_placeholders(s_body, values), encoding="utf-8") - else: - # your existing static content - (disc_dir / "feature.discussion.sum.md").write_text( - """# Summary — Feature - - -## Decisions (ADR-style) -- (none yet) - - - -## Open Questions -- (none yet) - - - -## Awaiting Replies -- (none yet) - - - -## Action Items -- (none yet) - - - -## Votes (latest per participant) -READY: 1 • CHANGES: 0 • REJECT: 0 -- Maintainer - - - -## Timeline (most recent first) -- {ts} Maintainer: Kickoff - - - -## Links -- Design/Plan: ../design/design.md - -""".replace("{ts}", today), encoding="utf-8") + # NOTE: We do NOT create feature.discussion.md or feature.discussion.sum.md here. + # The pre-commit hook automation will generate these files when request.md is committed. + # + # This approach: + # 1. Avoids race conditions (setup vs. hook both creating same files) + # 2. Actually exercises the automation system on first commit + # 3. Ensures generated files match current automation rules + # + # The automation flow will be: + # git commit → pre-commit hook → runner.py sees request.md + # → generates feature.discussion.md (AI-powered) + # → workflow.py generates feature.discussion.sum.md def copy_install_assets_to_target(target: Path):