mirror of
https://github.com/github/spec-kit.git
synced 2026-08-03 06:26:30 +08:00
ebd3097eb37b90143d4738e73cf4fec20ce74e10
8
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
490566847c |
feat(cli): honor SPECIFY_INIT_DIR in the specify CLI project resolver (#3186)
* feat(cli): honor SPECIFY_INIT_DIR in the specify CLI project resolver The shell resolver honors SPECIFY_INIT_DIR (#2892), but the Python CLI did not: it resolved the project as Path.cwd() + a .specify/ check and never read the override. So setup-plan.sh respected it while `specify integration install` ignored it, and you still had to cd into the member project. Route project resolution through a shared _resolve_init_dir_override() that applies the shell resolver's validation rules (relative to cwd, must exist and contain .specify/, hard error, no fallback, same error strings). It's wired into _require_specify_project() — the chokepoint for every project-scoped subcommand (integration/extension/workflow/preset/...) — and the `workflow run <file>` standalone path, which re-applies its symlinked-.specify guard on the override branch too. init is unchanged: it creates .specify/, so the must-pre-exist rule doesn't apply. The resolver canonicalizes symlinks via Path.resolve() while the shell keeps the logical path; they agree for non-symlinked paths (documented in the resolver). Tests in tests/test_init_dir_cli.py mirror the strict cases from test_init_dir.py through the CLI; conftest now strips SPECIFY_* for the whole suite so a stray export can't perturb the now-env-reading resolver. Docs note the CLI applies the same rules. Discussion: github/spec-kit#2834 (Disclosure: I used an AI coding agent to audit the call sites and resolver, draft the change, and run an adversarial code review; reviewed by me.) * fix(cli): honor SPECIFY_INIT_DIR for bundle commands Assisted-by: Codex (model: GPT-5, autonomous) * fix(bundler): refuse symlinked .specify on the SPECIFY_INIT_DIR override path find_project_root refuses a symlinked .specify (following it could read/write outside the tree, and a test pins that), but the SPECIFY_INIT_DIR override added for bundle commands returned early and skipped that guard: _resolve_init_dir_override validates .specify with is_dir(), which follows symlinks. So `specify bundle` accepted via the override a layout the cwd path rejects. Re-check the override result with the same guard, plus a regression test. (Disclosure: found via an AI code review and fixed with an AI coding agent; reviewed by me.) * fix(cli): keep SPECIFY_INIT_DIR strict for bundles Treat an explicit symlinked SPECIFY_INIT_DIR project as a hard bundle error instead of returning no project, which could initialize the current directory. Align the docs with the actual unset resolver behavior. Assisted-by: Codex (model: GPT-5, autonomous) * docs(core): note symlinked .specify handling differs across CLI surfaces A symlinked .specify is followed by integration/extension/workflow (matching the shell resolver) but refused by bundle and workflow run <file> (write confinement). Document the asymmetry so it reads as intentional. (Disclosure: AI-assisted; reviewed by me.) * docs(core): reframe symlinked .specify note around the override invariant Per maintainer feedback on #3186: SPECIFY_INIT_DIR relocates where the project is, not how a surface treats symlinks. Each surface keeps its cwd-path stance (write surfaces refuse a symlinked .specify, read/config surfaces follow it), so the split is one policy relocated, not an inconsistency. * docs: address Copilot review on resolver docstrings - _project.py: the error messages "mirror" the shell wording rather than "match" it (the CLI renders a Rich `Error:` line, the shell a plain `ERROR:`). - find_project_root: document that honoring SPECIFY_INIT_DIR when start is None can raise typer.Exit / BundlerError, so the Path | None signature isn't surprising to direct callers. * docs(bundler): note require_project_root inherits the override raise behavior find_project_root can raise typer.Exit / BundlerError under the SPECIFY_INIT_DIR override (start=None); require_project_root inherits that, so document it alongside its own BundlerError-on-missing-project. * docs: clarify symlinked project root behavior Assisted-by: OpenAI Codex (model: GPT-5, autonomous) * Address SPECIFY_INIT_DIR review feedback Assisted-by: OpenAI Codex (model: GPT-5, autonomous) * Route workflow JSON errors to stderr Assisted-by: OpenAI Codex (model: GPT-5, autonomous) |
||
|
|
a17a658bbd |
feat(scripts): add SPECIFY_INIT_DIR to target a member project from the repo root (#2892)
* feat(scripts): add SPECIFY_INIT_DIR to target a member project from the repo root Resolve an explicit SPECIFY_INIT_DIR project override once in the core get_repo_root / Get-RepoRoot, so a non-interactive / CI caller can target a member project (the directory containing .specify/) from a monorepo root without cd. Strict by design: the path must exist and contain .specify/, otherwise it hard-errors with no silent fallback. - Single resolver in core; the git feature-branch script inherits it by sourcing core, with no per-extension copies. - PS resolver verifies the resolved path is a directory (Resolve-Path also succeeds for files) so a file value errors as "not an existing directory". - get_feature_paths splits decl/assignment so a SPECIFY_INIT_DIR failure propagates instead of being masked by `local`. - create-new-feature-branch: when core is absent (only git-common loaded) and SPECIFY_INIT_DIR is set, hard-error rather than silently using the git root. - Document SPECIFY_INIT_DIR and SPECIFY_FEATURE_DIRECTORY in the core reference. - Tests for valid/relative/trailing-slash/file/missing/no-.specify targets, feature-axis composition, the no-core guard, and a PowerShell mirror. * fix: guard SPECIFY_INIT_DIR with stale core scripts * docs: clarify SPECIFY_FEATURE_DIRECTORY precedence wording * fix: normalize trailing slash in PowerShell SPECIFY_INIT_DIR resolver Resolve-Path preserves a trailing separator from its input, so a SPECIFY_INIT_DIR ending in a slash returned a root that didn't match the bash resolver (whose `cd && pwd` strips it). That broke test_ps_trailing_slash_tolerated on the CI runners, which do have pwsh. Trim it with TrimEndingDirectorySeparator (no-op on a bare root or a path with no trailing separator). Also fix the misleading test comment: the PowerShell mirror runs on the CI ubuntu/windows runners (they ship pwsh), it is not skipped there. * test: normalize bash path expectations on Windows * docs: clarify SPECIFY_INIT_DIR root helpers |
||
|
|
927f54feea |
feat: make git extension opt-in and remove --no-git at v0.10.0 (#2873)
* feat(init)!: make git extension opt-in and remove --no-git at v0.10.0 - Remove --no-git parameter from specify init command - Remove git extension auto-installation from init flow - Git repository initialization (git init) still runs when git is available - Remove --no-git from all test invocations across the test suite - Update docs to reflect opt-in git extension behavior - Replace TestGitExtensionAutoInstall with TestGitExtensionOptIn tests BREAKING CHANGE: specify init no longer auto-installs the git extension. Use `specify extension add git` to install it explicitly. The --no-git flag has been removed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * refactor(scripts): remove git operations from core scripts Git functionality is now entirely managed by the git extension. Core scripts only handle directory-based feature creation and numbering. - Remove has_git(), check_feature_branch(), git branch creation from core - Simplify number detection to use only spec directory scanning - Remove HAS_GIT output from get_feature_paths() - Remove git remote fetching and branch querying - Keep BRANCH_NAME output key for backward compatibility Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * refactor: remove all git operations from core - Remove is_git_repo() and init_git_repo() dead code from _utils.py - Remove --branch-numbering from init command - Remove git from 'specify check' (now extension-only) - Update docs: git is optional prerequisite, check command description - Fix tests to reflect no-git-in-core reality (fallback to main) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * refactor(scripts): remove directory scanning and branch fallback from core Core scripts now resolve feature context exclusively from: 1. SPECIFY_FEATURE env var (set by git extension) 2. .specify/feature.json (persisted by specify command) Removed find_feature_dir_by_prefix() and directory scanning heuristics — these are the git extension's responsibility. Scripts error clearly when no feature context is available. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat: introduce feature_numbering, deprecate branch_numbering in init-options - specify command template now reads feature_numbering (preferred) with fallback to branch_numbering (deprecated) from init-options.json - Git extension reads git-config.yml > feature_numbering > branch_numbering - init now writes feature_numbering: sequential to init-options.json - Deprecation warning emitted when branch_numbering is used as fallback Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: remove trailing whitespace in common.ps1 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * feat(scripts): persist SPECIFY_FEATURE_DIRECTORY env var to feature.json When SPECIFY_FEATURE_DIRECTORY is set, get_feature_paths() now writes the value to .specify/feature.json so future sessions without the env var can still resolve the feature directory. The write is idempotent — it skips when the file already contains the same value. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: address review feedback — error messages and docs - Update error messages in common.sh and common.ps1 to reference SPECIFY_FEATURE_DIRECTORY instead of SPECIFY_FEATURE (which no longer resolves feature directories) - Fix get_current_branch comment (returns empty string, not error) - Update upgrade.md to reference SPECIFY_FEATURE_DIRECTORY with correct example paths - Update local-development.md troubleshooting: replace stale 'Git step skipped' row with actionable git extension guidance Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(scripts): harden feature.json persistence - Use json_escape in printf fallback when jq is unavailable (common.sh) - Replace utf8NoBOM encoding with UTF8Encoding($false) for PowerShell 5.1 compatibility (common.ps1) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * refactor(scripts): remove dead feature_json_matches_feature_dir functions These guards are no longer needed since the branch-name validation they protected against has been removed from check-prerequisites. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * refactor(git-ext): rename create-new-feature to create-new-feature-branch The git extension's script only creates the git branch — rename it to reflect that responsibility. The core create-new-feature.sh/.ps1 handles feature directory creation and feature.json persistence. Also includes fixes from review feedback: - common.sh: _persist_feature_json uses json_escape fallback - common.ps1: Save-FeatureJson uses UTF8Encoding for PS 5.1 compat - common.ps1: case-sensitive path stripping on non-Windows - create-new-feature.sh/ps1: output both SPECIFY_FEATURE and SPECIFY_FEATURE_DIRECTORY - setup-tasks.sh: fix stale 'Validate branch' comment Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(tests): update references to renamed git extension scripts Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(tests): remove duplicate EXT_CREATE_FEATURE assignments Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Manfred Riem <mnriem@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |
||
|
|
b4b83be51b |
feat: add self-check tip to check output (#2574)
* feat: add self-check tip to check output * style: drop trailing period from self-check tip Aligns the new tip with the other `Tip:` lines in `specify check`, which don't end in a period. Per Copilot review feedback on #2574. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
e6afba9429 | feat: add version feature reporting (#2548) | ||
|
|
2d5e63005d |
fix: default non-interactive init to copilot integration (#2414)
* fix: default non-interactive init integration * chore: clarify non-interactive init default integration * Address non-interactive init review feedback * Fix interactive init test after fallback |
||
|
|
822a0e5c61 |
feat: emit init-time notice for git extension default change (#2165) (#2432)
Add a non-blocking Panel notice during `specify init` when the git extension auto-enables, informing users that starting in v0.10.0 this will require explicit opt-in via `specify extension add git`. - src/specify_cli/__init__.py: track successful git extension install and display yellow "Notice: Git Default Changing" panel - tests/integrations/test_cli.py: integration test validating notice content (v0.10.0 timeline, opt-in messaging, migration command) - docs/reference/core.md: user-facing NOTE about the upcoming change Closes #2165 |
||
|
|
697daec733 |
docs: add core commands reference and simplify README CLI section (#2245)
* docs: add core commands reference and simplify README CLI section - New docs/reference/core.md: reference for init (active options only, copilot as main example), check, and version commands - docs/toc.yml: add Core Commands under Reference - README.md: replace verbose CLI Reference section (init options table, 30+ per-agent examples, deprecated flags, env vars) with links to reference docs; use copilot as main example throughout * docs: add CLI reference overview page - New docs/reference/overview.md: explains each CLI surface area (core, integrations, extensions, presets, workflows) with key commands and links to detailed reference pages - docs/toc.yml: add Overview as first item under Reference - README.md: simplify CLI Reference to single link to overview page * docs: remove command references from overview, keep paragraphs only |