Compare commits

..

18 Commits

Author SHA1 Message Date
Den Delimarsky
e3b456c4c8 Merge pull request #547 from stenyin/main
Add UTF-8 encoding to file operations in update-agent-context.ps1
2025-09-30 17:05:24 -07:00
Den Delimarsky
e04175b51e Merge pull request #686 from Charca/patch-1
Update URLs to Contributing and Support Guides in Docs
2025-09-30 17:04:46 -07:00
Maxi Ferreira
cc75a22e45 Update URLs to Contributing and Support Guides in Docs
## Problem

The links to the contributing and support guides at the bottom of [the docs site home page](https://github.github.com/spec-kit/index.html) currently take you to a 404 page.

## Solution

Update the links to the correct URLs, pointing to the guides that are currently in the repo's root directory rather than within the `docs` folder.
2025-09-30 11:11:41 -07:00
stenyin
b2f749ef41 fix: add UTF-8 encoding to file read/write operations in update-agent-context.ps1 2025-09-28 05:48:24 +08:00
den (work)
321edbc62e Update __init__.py 2025-09-25 14:05:15 -07:00
Den Delimarsky
fadd250a98 Merge pull request #568 from shyn/main
feat: Add emacs-style up/down keys
2025-09-25 12:53:47 -07:00
Den Delimarsky
9ff9c9fd8d Merge pull request #570 from brunoborges/specify_init_period
feat: support 'specify init .' for current directory initialization
2025-09-25 12:50:17 -07:00
Den Delimarsky
45f04abd38 Merge pull request #573 from tinesoft/fix/docs
docs: fix the paths of generated files (moved under a `.specify/` fol…
2025-09-25 12:40:19 -07:00
Den Delimarsky
1c0e7d14d5 Merge pull request #563 from danwashusen/plan-project-structure-fix
Refined wording in `plan-template.md` to ensure the Source Code section consistently works
2025-09-25 12:39:14 -07:00
Den Delimarsky
55555eb39e Merge pull request #590 from github/cli-fix
Spec Kit Updates
2025-09-25 12:28:51 -07:00
den (work)
6f3e450cd8 Update CONTRIBUTING.md 2025-09-25 12:27:37 -07:00
Bruno Borges
8bbacd4adb Update src/specify_cli/__init__.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-09-25 11:16:05 -07:00
Tine Kondo
6a3e81f813 docs: fix the paths of generated files (moved under a .specify/ folder) 2025-09-25 10:05:08 +02:00
Bruno Borges
eb3c63fe0f Update src/specify_cli/__init__.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-09-24 23:22:15 -07:00
Bruno Borges
68eba52a40 feat: support 'specify init .' for current directory initialization
Adds '.' as shorthand equivalent to --here flag while maintaining
full backward compatibility. Updates documentation and bumps to v0.0.18.
2025-09-24 22:41:50 -07:00
shyn
721ecc9bec feat: Add emacs-style up/down keys
get up/down with ctrl+p/n for emacs-keybinding convention
2025-09-25 13:23:38 +08:00
Dan Washusen
df3e4930cc Refine plan-template.md with improved project type detection, clarified structure decision process, and enhanced research task guidance. 2025-09-25 10:10:30 +10:00
Den Delimarsky 🌺
f1ddf33ac4 Update __init__.py 2025-09-23 18:29:15 -07:00
8 changed files with 119 additions and 42 deletions

View File

@@ -7,6 +7,12 @@ All notable changes to the Specify CLI will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [LATEST_VERSION] - RELEASE_DATE
### Added
- Support for using `.` as a shorthand for current directory in `specify init .` command, equivalent to `--here` flag but more intuitive for users
## [0.0.17] - 2025-09-22 ## [0.0.17] - 2025-09-22
### Added ### Added

View File

@@ -47,12 +47,40 @@ When working on spec-kit:
## AI contributions in Spec Kit ## AI contributions in Spec Kit
> [!IMPORTANT]
>
> If you are using **any kind of AI assistance** to contribute to Spec Kit,
> it must be disclosed in the pull request or issue.
We welcome and encourage the use of AI tools to help improve Spec Kit! Many valuable contributions have been enhanced with AI assistance for code generation, issue detection, and feature definition. We welcome and encourage the use of AI tools to help improve Spec Kit! Many valuable contributions have been enhanced with AI assistance for code generation, issue detection, and feature definition.
That being said, if you are using any kind of AI assistance (e.g., agents, ChatGPT) while contributing to Spec Kit,
**this must be disclosed in the pull request or issue**, along with the extent to which AI assistance was used (e.g., documentation comments vs. code generation).
If your PR responses or comments are being generated by an AI, disclose that as well.
As an exception, trivial spacing or typo fixes don't need to be disclosed, so long as the changes are limited to small parts of the code or short phrases.
An example disclosure:
> This PR was written primarily by GitHub Copilot.
Or a more detailed disclosure:
> I consulted ChatGPT to understand the codebase but the solution
> was fully authored manually by myself.
Failure to disclose this is first and foremost rude to the human operators on the other end of the pull request, but it also makes it difficult to
determine how much scrutiny to apply to the contribution.
In a perfect world, AI assistance would produce equal or higher quality work than any human. That isn't the world we live in today, and in most cases
where human supervision or expertise is not in the loop, it's generating code that cannot be reasonably maintained or evolved.
### What we're looking for ### What we're looking for
When submitting AI-assisted contributions, please ensure they include: When submitting AI-assisted contributions, please ensure they include:
- **Clear disclosure of AI use** - You are transparent about AI use and degree to which you're using it for the contribution
- **Human understanding and testing** - You've personally tested the changes and understand what they do - **Human understanding and testing** - You've personally tested the changes and understand what they do
- **Clear rationale** - You can explain why the change is needed and how it fits within Spec Kit's goals - **Clear rationale** - You can explain why the change is needed and how it fits within Spec Kit's goals
- **Concrete evidence** - Include test cases, scenarios, or examples that demonstrate the improvement - **Concrete evidence** - Include test cases, scenarios, or examples that demonstrate the improvement
@@ -72,6 +100,8 @@ The key is demonstrating that you understand and have validated your proposed ch
Contributors who consistently submit low-effort AI-generated changes may be restricted from further contributions at the maintainers' discretion. Contributors who consistently submit low-effort AI-generated changes may be restricted from further contributions at the maintainers' discretion.
Please be respectful to maintainers and disclose AI assistance.
## Resources ## Resources
- [Spec-Driven Development Methodology](./spec-driven.md) - [Spec-Driven Development Methodology](./spec-driven.md)

View File

@@ -150,13 +150,13 @@ The `specify` command supports the following options:
| Argument/Option | Type | Description | | Argument/Option | Type | Description |
|------------------------|----------|------------------------------------------------------------------------------| |------------------------|----------|------------------------------------------------------------------------------|
| `<project-name>` | Argument | Name for your new project directory (optional if using `--here`) | | `<project-name>` | Argument | Name for your new project directory (optional if using `--here`, or use `.` for current directory) |
| `--ai` | Option | AI assistant to use: `claude`, `gemini`, `copilot`, `cursor`, `qwen`, `opencode`, `codex`, `windsurf`, `kilocode`, `auggie`, or `roo` | | `--ai` | Option | AI assistant to use: `claude`, `gemini`, `copilot`, `cursor`, `qwen`, `opencode`, `codex`, `windsurf`, `kilocode`, `auggie`, or `roo` |
| `--script` | Option | Script variant to use: `sh` (bash/zsh) or `ps` (PowerShell) | | `--script` | Option | Script variant to use: `sh` (bash/zsh) or `ps` (PowerShell) |
| `--ignore-agent-tools` | Flag | Skip checks for AI agent tools like Claude Code | | `--ignore-agent-tools` | Flag | Skip checks for AI agent tools like Claude Code |
| `--no-git` | Flag | Skip git repository initialization | | `--no-git` | Flag | Skip git repository initialization |
| `--here` | Flag | Initialize project in the current directory instead of creating a new one | | `--here` | Flag | Initialize project in the current directory instead of creating a new one |
| `--force` | Flag | Force merge/overwrite when using `--here` in a non-empty directory (skip confirmation) | | `--force` | Flag | Force merge/overwrite when initializing in current directory (skip confirmation) |
| `--skip-tls` | Flag | Skip SSL/TLS verification (not recommended) | | `--skip-tls` | Flag | Skip SSL/TLS verification (not recommended) |
| `--debug` | Flag | Enable detailed debug output for troubleshooting | | `--debug` | Flag | Enable detailed debug output for troubleshooting |
| `--github-token` | Option | GitHub token for API requests (or set GH_TOKEN/GITHUB_TOKEN env variable) | | `--github-token` | Option | GitHub token for API requests (or set GH_TOKEN/GITHUB_TOKEN env variable) |
@@ -180,9 +180,13 @@ specify init my-project --ai windsurf
specify init my-project --ai copilot --script ps specify init my-project --ai copilot --script ps
# Initialize in current directory # Initialize in current directory
specify init . --ai copilot
# or use the --here flag
specify init --here --ai copilot specify init --here --ai copilot
# Force merge into current (non-empty) directory without confirmation # Force merge into current (non-empty) directory without confirmation
specify init . --force --ai copilot
# or
specify init --here --force --ai copilot specify init --here --force --ai copilot
# Skip git initialization # Skip git initialization
@@ -292,8 +296,12 @@ specify init <project_name>
Or initialize in the current directory: Or initialize in the current directory:
```bash ```bash
specify init .
# or use the --here flag
specify init --here specify init --here
# Skip confirmation when the directory already has files # Skip confirmation when the directory already has files
specify init . --force
# or
specify init --here --force specify init --here --force
``` ```
@@ -311,9 +319,14 @@ specify init <project_name> --ai opencode
specify init <project_name> --ai codex specify init <project_name> --ai codex
specify init <project_name> --ai windsurf specify init <project_name> --ai windsurf
# Or in current directory: # Or in current directory:
specify init . --ai claude
specify init . --ai codex
# or use --here flag
specify init --here --ai claude specify init --here --ai claude
specify init --here --ai codex specify init --here --ai codex
# Force merge into a non-empty current directory # Force merge into a non-empty current directory
specify init . --force --ai claude
# or
specify init --here --force --ai claude specify init --here --force --ai claude
``` ```
@@ -337,7 +350,7 @@ The first step should be establishing your project's governing principles using
/constitution Create principles focused on code quality, testing standards, user experience consistency, and performance requirements. Include governance for how these principles should guide technical decisions and implementation choices. /constitution Create principles focused on code quality, testing standards, user experience consistency, and performance requirements. Include governance for how these principles should guide technical decisions and implementation choices.
``` ```
This step creates or updates the `/memory/constitution.md` file with your project's foundational guidelines that the AI agent will reference during specification, planning, and implementation phases. This step creates or updates the `.specify/memory/constitution.md` file with your project's foundational guidelines that the AI agent will reference during specification, planning, and implementation phases.
### **STEP 2:** Create project specifications ### **STEP 2:** Create project specifications
@@ -376,6 +389,7 @@ The produced specification should contain a set of user stories and functional r
At this stage, your project folder contents should resemble the following: At this stage, your project folder contents should resemble the following:
```text ```text
└── .specify
├── memory ├── memory
│ └── constitution.md │ └── constitution.md
├── scripts ├── scripts

View File

@@ -55,8 +55,8 @@ Our research and experimentation focus on:
## Contributing ## Contributing
Please see our [Contributing Guide](CONTRIBUTING.md) for information on how to contribute to this project. Please see our [Contributing Guide](https://github.com/github/spec-kit/blob/main/CONTRIBUTING.md) for information on how to contribute to this project.
## Support ## Support
For support, please check our [Support Guide](SUPPORT.md) or open an issue on GitHub. For support, please check our [Support Guide](https://github.com/github/spec-kit/blob/main/SUPPORT.md) or open an issue on GitHub.

View File

@@ -21,6 +21,8 @@ uvx --from git+https://github.com/github/spec-kit.git specify init <PROJECT_NAME
Or initialize in the current directory: Or initialize in the current directory:
```bash ```bash
uvx --from git+https://github.com/github/spec-kit.git specify init .
# or use the --here flag
uvx --from git+https://github.com/github/spec-kit.git specify init --here uvx --from git+https://github.com/github/spec-kit.git specify init --here
``` ```

View File

@@ -124,7 +124,7 @@ function Extract-PlanField {
if (-not (Test-Path $PlanFile)) { return '' } if (-not (Test-Path $PlanFile)) { return '' }
# Lines like **Language/Version**: Python 3.12 # Lines like **Language/Version**: Python 3.12
$regex = "^\*\*$([Regex]::Escape($FieldPattern))\*\*: (.+)$" $regex = "^\*\*$([Regex]::Escape($FieldPattern))\*\*: (.+)$"
Get-Content -LiteralPath $PlanFile | ForEach-Object { Get-Content -LiteralPath $PlanFile -Encoding utf8 | ForEach-Object {
if ($_ -match $regex) { if ($_ -match $regex) {
$val = $Matches[1].Trim() $val = $Matches[1].Trim()
if ($val -notin @('NEEDS CLARIFICATION','N/A')) { return $val } if ($val -notin @('NEEDS CLARIFICATION','N/A')) { return $val }
@@ -215,7 +215,7 @@ function New-AgentFile {
$escaped_framework = $NEW_FRAMEWORK $escaped_framework = $NEW_FRAMEWORK
$escaped_branch = $CURRENT_BRANCH $escaped_branch = $CURRENT_BRANCH
$content = Get-Content -LiteralPath $temp -Raw $content = Get-Content -LiteralPath $temp -Raw -Encoding utf8
$content = $content -replace '\[PROJECT NAME\]',$ProjectName $content = $content -replace '\[PROJECT NAME\]',$ProjectName
$content = $content -replace '\[DATE\]',$Date.ToString('yyyy-MM-dd') $content = $content -replace '\[DATE\]',$Date.ToString('yyyy-MM-dd')
@@ -253,7 +253,7 @@ function New-AgentFile {
$parent = Split-Path -Parent $TargetFile $parent = Split-Path -Parent $TargetFile
if (-not (Test-Path $parent)) { New-Item -ItemType Directory -Path $parent | Out-Null } if (-not (Test-Path $parent)) { New-Item -ItemType Directory -Path $parent | Out-Null }
Set-Content -LiteralPath $TargetFile -Value $content -NoNewline Set-Content -LiteralPath $TargetFile -Value $content -NoNewline -Encoding utf8
Remove-Item $temp -Force Remove-Item $temp -Force
return $true return $true
} }
@@ -285,7 +285,7 @@ function Update-ExistingAgentFile {
if ($techStack) { $newChangeEntry = "- ${CURRENT_BRANCH}: Added ${techStack}" } if ($techStack) { $newChangeEntry = "- ${CURRENT_BRANCH}: Added ${techStack}" }
elseif ($NEW_DB -and $NEW_DB -notin @('N/A','NEEDS CLARIFICATION')) { $newChangeEntry = "- ${CURRENT_BRANCH}: Added ${NEW_DB}" } elseif ($NEW_DB -and $NEW_DB -notin @('N/A','NEEDS CLARIFICATION')) { $newChangeEntry = "- ${CURRENT_BRANCH}: Added ${NEW_DB}" }
$lines = Get-Content -LiteralPath $TargetFile $lines = Get-Content -LiteralPath $TargetFile -Encoding utf8
$output = New-Object System.Collections.Generic.List[string] $output = New-Object System.Collections.Generic.List[string]
$inTech = $false; $inChanges = $false; $techAdded = $false; $changeAdded = $false; $existingChanges = 0 $inTech = $false; $inChanges = $false; $techAdded = $false; $changeAdded = $false; $existingChanges = 0
@@ -327,7 +327,7 @@ function Update-ExistingAgentFile {
$newTechEntries | ForEach-Object { $output.Add($_) } $newTechEntries | ForEach-Object { $output.Add($_) }
} }
Set-Content -LiteralPath $TargetFile -Value ($output -join [Environment]::NewLine) Set-Content -LiteralPath $TargetFile -Value ($output -join [Environment]::NewLine) -Encoding utf8
return $true return $true
} }

View File

@@ -14,11 +14,13 @@ Specify CLI - Setup tool for Specify projects
Usage: Usage:
uvx specify-cli.py init <project-name> uvx specify-cli.py init <project-name>
uvx specify-cli.py init .
uvx specify-cli.py init --here uvx specify-cli.py init --here
Or install globally: Or install globally:
uv tool install --from specify-cli.py specify-cli uv tool install --from specify-cli.py specify-cli
specify init <project-name> specify init <project-name>
specify init .
specify init --here specify init --here
""" """
@@ -192,9 +194,9 @@ def get_key():
key = readchar.readkey() key = readchar.readkey()
# Arrow keys # Arrow keys
if key == readchar.key.UP: if key == readchar.key.UP or key == readchar.key.CTRL_P:
return 'up' return 'up'
if key == readchar.key.DOWN: if key == readchar.key.DOWN or key == readchar.key.CTRL_N:
return 'down' return 'down'
# Enter/Return # Enter/Return
@@ -747,7 +749,7 @@ def ensure_executable_scripts(project_path: Path, tracker: StepTracker | None =
@app.command() @app.command()
def init( def init(
project_name: str = typer.Argument(None, help="Name for your new project directory (optional if using --here)"), project_name: str = typer.Argument(None, help="Name for your new project directory (optional if using --here, or use '.' for current directory)"),
ai_assistant: str = typer.Option(None, "--ai", help="AI assistant to use: claude, gemini, copilot, cursor, qwen, opencode, codex, windsurf, kilocode, or auggie"), ai_assistant: str = typer.Option(None, "--ai", help="AI assistant to use: claude, gemini, copilot, cursor, qwen, opencode, codex, windsurf, kilocode, or auggie"),
script_type: str = typer.Option(None, "--script", help="Script type to use: sh or ps"), script_type: str = typer.Option(None, "--script", help="Script type to use: sh or ps"),
ignore_agent_tools: bool = typer.Option(False, "--ignore-agent-tools", help="Skip checks for AI agent tools like Claude Code"), ignore_agent_tools: bool = typer.Option(False, "--ignore-agent-tools", help="Skip checks for AI agent tools like Claude Code"),
@@ -781,7 +783,9 @@ def init(
specify init my-project --ai windsurf specify init my-project --ai windsurf
specify init my-project --ai auggie specify init my-project --ai auggie
specify init --ignore-agent-tools my-project specify init --ignore-agent-tools my-project
specify init --here --ai claude specify init . --ai claude # Initialize in current directory
specify init . # Initialize in current directory (interactive AI selection)
specify init --here --ai claude # Alternative syntax for current directory
specify init --here --ai codex specify init --here --ai codex
specify init --here specify init --here
specify init --here --force # Skip confirmation when current directory not empty specify init --here --force # Skip confirmation when current directory not empty
@@ -789,13 +793,18 @@ def init(
# Show banner first # Show banner first
show_banner() show_banner()
# Handle '.' as shorthand for current directory (equivalent to --here)
if project_name == ".":
here = True
project_name = None # Clear project_name to use existing validation logic
# Validate arguments # Validate arguments
if here and project_name: if here and project_name:
console.print("[red]Error:[/red] Cannot specify both project name and --here flag") console.print("[red]Error:[/red] Cannot specify both project name and --here flag")
raise typer.Exit(1) raise typer.Exit(1)
if not here and not project_name: if not here and not project_name:
console.print("[red]Error:[/red] Must specify either a project name or use --here flag") console.print("[red]Error:[/red] Must specify either a project name, use '.' for current directory, or use --here flag")
raise typer.Exit(1) raise typer.Exit(1)
# Determine project directory # Determine project directory
@@ -1058,18 +1067,27 @@ def init(
step_num += 1 step_num += 1
steps_lines.append(f"{step_num}. Start using slash commands with your AI agent:") steps_lines.append(f"{step_num}. Start using slash commands with your AI agent:")
steps_lines.append(" 2.1 [cyan]/constitution[/] - Establish project principles") steps_lines.append(" 2.1 [cyan]/constitution[/] - Establish project principles")
steps_lines.append(" 2.2 [cyan]/specify[/] - Create specifications") steps_lines.append(" 2.2 [cyan]/specify[/] - Create baseline specification")
steps_lines.append(" 2.3 [cyan]/clarify[/] - Clarify and de-risk specification (run before [cyan]/plan[/cyan])") steps_lines.append(" 2.3 [cyan]/plan[/] - Create implementation plan")
steps_lines.append(" 2.4 [cyan]/plan[/] - Create implementation plans") steps_lines.append(" 2.4 [cyan]/tasks[/] - Generate actionable tasks")
steps_lines.append(" 2.5 [cyan]/tasks[/] - Generate actionable tasks") steps_lines.append(" 2.5 [cyan]/implement[/] - Execute implementation")
steps_lines.append(" 2.6 [cyan]/analyze[/] - Validate alignment & surface inconsistencies (read-only)")
steps_lines.append(" 2.7 [cyan]/implement[/] - Execute implementation")
steps_panel = Panel("\n".join(steps_lines), title="Next Steps", border_style="cyan", padding=(1,2)) steps_panel = Panel("\n".join(steps_lines), title="Next Steps", border_style="cyan", padding=(1,2))
console.print() console.print()
console.print(steps_panel) console.print(steps_panel)
enhancement_lines = [
"Optional commands that you can use for your specs [bright_black](improve quality & confidence)[/bright_black]",
"",
f"○ [cyan]/clarify[/] [bright_black](optional)[/bright_black] - Ask structured questions to de-risk ambiguous areas before planning (run before [cyan]/plan[/] if used)",
f"○ [cyan]/analyze[/] [bright_black](optional)[/bright_black] - Cross-artifact consistency & alignment report (after [cyan]/tasks[/], before [cyan]/implement[/])"
]
enhancements_panel = Panel("\n".join(enhancement_lines), title="Enhancement Commands", border_style="cyan", padding=(1,2))
console.print()
console.print(enhancements_panel)
if selected_ai == "codex": if selected_ai == "codex":
warning_text = """[bold yellow]Important Note:[/bold yellow] warning_text = """[bold yellow]Important Note:[/bold yellow]

View File

@@ -15,7 +15,7 @@ scripts:
1. Load feature spec from Input path 1. Load feature spec from Input path
→ If not found: ERROR "No feature spec at {path}" → If not found: ERROR "No feature spec at {path}"
2. Fill Technical Context (scan for NEEDS CLARIFICATION) 2. Fill Technical Context (scan for NEEDS CLARIFICATION)
→ Detect Project Type from context (web=frontend+backend, mobile=app+api) → Detect Project Type from file system structure or context (web=frontend+backend, mobile=app+api)
→ Set Structure Decision based on project type → Set Structure Decision based on project type
3. Fill the Constitution Check section based on the content of the constitution document. 3. Fill the Constitution Check section based on the content of the constitution document.
4. Evaluate Constitution Check section below 4. Evaluate Constitution Check section below
@@ -69,8 +69,14 @@ specs/[###-feature]/
``` ```
### Source Code (repository root) ### Source Code (repository root)
<!--
ACTION REQUIRED: Replace the placeholder tree below with the concrete layout
for this feature. Delete unused options and expand the chosen structure with
real paths (e.g., apps/admin, packages/something). The delivered plan must
not include Option labels.
-->
``` ```
# Option 1: Single project (DEFAULT) # [REMOVE IF UNUSED] Option 1: Single project (DEFAULT)
src/ src/
├── models/ ├── models/
├── services/ ├── services/
@@ -82,7 +88,7 @@ tests/
├── integration/ ├── integration/
└── unit/ └── unit/
# Option 2: Web application (when "frontend" + "backend" detected) # [REMOVE IF UNUSED] Option 2: Web application (when "frontend" + "backend" detected)
backend/ backend/
├── src/ ├── src/
│ ├── models/ │ ├── models/
@@ -97,15 +103,16 @@ frontend/
│ └── services/ │ └── services/
└── tests/ └── tests/
# Option 3: Mobile + API (when "iOS/Android" detected) # [REMOVE IF UNUSED] Option 3: Mobile + API (when "iOS/Android" detected)
api/ api/
└── [same as backend above] └── [same as backend above]
ios/ or android/ ios/ or android/
└── [platform-specific structure] └── [platform-specific structure: feature modules, UI flows, platform tests]
``` ```
**Structure Decision**: [DEFAULT to Option 1 unless Technical Context indicates web/mobile app] **Structure Decision**: [Document the selected structure and reference the real
directories captured above]
## Phase 0: Outline & Research ## Phase 0: Outline & Research
1. **Extract unknowns from Technical Context** above: 1. **Extract unknowns from Technical Context** above: