<?xml version="1.0" encoding="UTF-8"?>
<gsl-prompt id="20250809T193452+0000" type="feat">
<gsl-header>

# OBK Generate Prompt Command
</gsl-header>
<gsl-block>

<gsl-purpose>
<gsl-label>

## 1. Purpose  
</gsl-label>    
<gsl-description>

Add a generator command to create a new prompt file and a matching task folder using **deterministic UTC-dated paths** and the **existing trace-id logic**.
</gsl-description>
</gsl-purpose>

<gsl-inputs>
<gsl-label>

## 2. Inputs
</gsl-label>
<gsl-description>

| Input | Notes |
| --- | --- |
| `src/obk/trace_id.py` | **Source of truth** for trace ID generation. Import and reuse exactly the same function used by `obk trace-id`. |
| `src/obk/project_path.py` | Provides `resolve_project_root()`. Must succeed before any generation can occur. |
| `src/obk/cli.py` | Typer app entry; add a `generate` group and `prompt` command (plus alias `generate-prompt`). |
| `src/obk/templates/prompt.xml` | **New programmatic template** packaged with the app (not an article). Loaded via `importlib.resources`. |
| `src/obk/xsd/prompt.xsd` | For optional/future validation. Do not block generation on validation in this increment. |
| `tests/test_generate_prompt.py` | **New** test file to cover acceptance cases. |
| `pyproject.toml` | Ensure the templates directory is included in the wheel (similar to how XSD is included). |
| `articles/prompt-template.md` | Reference-only parity with programmatic template; do **not** read this at runtime. |
| Libraries: `datetime` (UTC), `pathlib`, `importlib.resources`, `logging`, `typer` | Standard tools used by the implementation. |

</gsl-description>
</gsl-inputs>

<gsl-outputs>
<gsl-label>

## 3. Outputs
</gsl-label>
<gsl-description>


#### Command & UX

1. **Command name**
    
    * Primary: `obk generate prompt`
        
    * Alias: `obk generate-prompt`
        
    * Grouping under `generate` leaves room for future generators (e.g., `generate task`, `generate article`).
        
2. **Options (initial)**
    
    * `--date YYYY-MM-DD` (optional): override “today (UTC)” for deterministic paths.
        
    * `--id <TRACE_ID>` (optional): provide a precomputed trace id; otherwise compute internally using the same function as `obk trace-id`.
        
    * `--force` (optional): overwrite existing prompt file if it already exists.
        
    * `--print-paths` (optional): write the computed output paths to stdout (prompts file + tasks folder).
        
    * `--dry-run` (optional): show what would be created without writing files.
        
3. **Exit codes**
    
    * `0` on success.
        
    * Non-zero on: project root unset/invalid, template load failure, IO errors, path conflicts without `--force`.
        

#### Deterministic Pathing

4. **Base paths (relative to project root)**
    
    * Prompts: `prompts/<YYYY>/<MM>/<DD>/`
        
    * Tasks: `tasks/<YYYY>/<MM>/<DD>/`
        
5. **UTC and formatting**
    
    * Always derive the date in **UTC** (default: “now (UTC)”).
        
    * Zero-pad Month and Day: `MM`, `DD`.
        
    * Examples:
        
        * 2025-08-09 UTC → `prompts/2025/08/09/` and `tasks/2025/08/09/`.
            
6. **Naming**
    
    * **Trace ID** is used for:
        
        * Prompt file name: `<TRACE_ID>.md`.
            
        * Task folder name: `<TRACE_ID>/`.
            
    * The file and folder **must** live under the **same** deterministic UTC path.
        

#### Trace ID

7. **Source of truth**
    
    * Reuse the same implementation used by `obk trace-id` (import and call the exact function used by that command; do not duplicate logic).
        
    * If `--id` is supplied, validate the format (same rules as trace-id command) before use.
        

#### Project Root Resolution

8. **Root discovery**
    
    * Use existing `resolve_project_root()` (env `OBK_PROJECT_PATH` first, then config file). Fail with a clear error if not set/invalid.
        

#### Template (Programmatic, Packaged)

9. **Template source**
    
    * Create a **programmatic** template, separate from documentation/articles.
        
    * Store under package data (e.g., `src/obk/templates/prompt.xml`) and **package it** like the XSD (import via `importlib.resources`).
        
    * The template’s **layout and stubs must match** the article template; only the `id` attribute is filled with the generated trace id. (Type may remain a placeholder for the user to edit.)
        
10. **Packaging**
    

* Ensure `pyproject.toml` includes the templates directory in the wheel (similar to how the XSD is included).
    

#### File Generation Behavior

11. **Create targets**
    

* Ensure directories exist: `prompts/YYYY/MM/DD/` and `tasks/YYYY/MM/DD/`.
    
* Write the prompt file: `prompts/YYYY/MM/DD/<TRACE_ID>.md` **from the packaged template** with `<gsl-prompt id="...">` set to the trace id.
    
* Create the task folder: `tasks/YYYY/MM/DD/<TRACE_ID>/` (empty).
    

12. **Idempotency & collisions**
    

* If the prompt file already exists:
    
    * Without `--force`: error with a helpful message and suggested `--force`.
        
    * With `--force`: overwrite file.
        
* If the task folder already exists, that’s ok (ensure directory exists); no error unless `--strict` is later added (not required now).
    

13. **Line endings & encoding**
    

* Write prompt file as UTF-8, Unix newlines (`\n`), XML header preserved.
    
* Keep comments/placeholders as in the template.
    

#### Validation & Logging

14. **Optional validation (not required right now)**
    

* (Future) Add `--validate` to run schema validation immediately after generation and report issues.
    
* For this increment, no automatic validation is required.
    

15. **Logging**
    

* Reuse existing logging setup; info-level entries: computed date (UTC), trace id, created paths, and whether `--force` was used.
    

#### Cross-Platform

16. **Paths**
    

* Use `pathlib` throughout.
    
* Windows and POSIX compatible behavior (no assumptions about separators).
    
* Respect existing TOML/Windows path escaping rules if any config persistence is touched (not required for this feature).
    

#### Tests

17. **Unit/CLI tests (add/extend)**
    

* Generates correct paths for a fixed UTC date (stub datetime to UTC 2025-08-09).
    
* Creates both artifacts with matching names.
    
* Populates `id` attribute with the exact trace id.
    
* Honors `--id`, `--force`, `--dry-run`, `--print-paths`.
    
* Works when project root is resolved from env and from config.
    
* Windows path test for writing locations (e.g., drive letter paths).
    
* Negative tests: project root unset, template missing (simulate), collision without `--force`.
    

#### Docs & Help

18. **Help text**
    

* Add Typer help/usage with examples:
    
    * `obk generate prompt`
        
    * `obk generate prompt --date 2025-08-09`
        
    * `obk generate prompt --id <TRACE_ID>`
        
    * `obk generate prompt --print-paths`
        
* Brief README section (or `obk --help` is fine for the first cut).
    

* * *

</gsl-description>
</gsl-outputs>

<gsl-workflows>
<gsl-label>

## 4. Workflows
</gsl-label>
<gsl-description>

These are **user-facing** workflows for how to use the feature once it ships.



#### Primary daily workflow (UTC “today”)

1. Ensure project root is configured:

    ```bash
    obk set-project-path --here   # or: obk set-project-path --path <abs_path>
    ```

2. Generate a new prompt using UTC “now”:

    ```bash
    obk generate prompt
    ```

3. Result:

* Prompt file: `prompts/YYYY/MM/DD/<TRACE_ID>.md`
* Task folder: `tasks/YYYY/MM/DD/<TRACE_ID>/`

4. Open the prompt and fill in content (the `id` is already set).
5. (Optional) Validate later:

    ```bash
    obk validate-all
    ```

6. Commit:

    ```bash
    git add prompts/YYYY/MM/DD/<TRACE_ID>.md tasks/YYYY/MM/DD/<TRACE_ID>/
    git commit -m "feat: add prompt <TRACE_ID> for YYYY-MM-DD (UTC)"
    ```

#### Backdating (create for a past UTC date)

- Generate artifacts under a specific UTC date; trace-id still uses UTC unless you pass `--id`:

    ```bash
    obk generate prompt --date 2025-08-09
    ```

    Artifacts go under `*/2025/08/09/*` regardless of local timezone.

#### Precomputing or reusing a known ID

- When you already have a trace id (e.g., from a ticket, PR, or `obk trace-id`):

    ```bash
    obk generate prompt --date 2025-08-09 --id 20250809T130102+0000
    ```

    Ensures the filename and task folder match that exact id, and the prompt’s `<gsl-prompt id>` matches too.

#### Preview-only / scripting helpers

- **Dry run** (nothing written, just show what would happen):

    ```bash
    obk generate prompt --date 2025-08-09 --dry-run
    ```

- **Print resolved paths** (useful for piping into scripts):

    ```bash
    obk generate prompt --print-paths
    ```

#### Recovery / overwrite

- If a prompt file already exists and you want to regenerate from the template:

    ```bash
    obk generate prompt --date 2025-08-09 --force
    ```

#### Editing & follow-ups

* Fill in the generated prompt’s sections (purpose, inputs, workflows, acceptance tests).
* Drop supporting artifacts into the **matching** tasks folder (e.g., `tasks/YYYY/MM/DD/<TRACE_ID>/screenshots/...`).
* Validate when ready:

    ```bash
    obk validate-all
    ```

* Optionally run maintenance commands:

    ```bash
    obk harmonize-all
    ```

#### Git & PR flow (common pattern)

1. Create a branch: `feat/generate-prompt-<TRACE_ID>`
2. Generate, edit, validate.
3. Commit deterministic UTC paths.
4. Open PR with `<TRACE_ID>` in title/description for easy cross-referencing.
5. CI (if configured) can run `obk validate-all`.

#### Windows vs. Linux notes

* Paths are platform-correct automatically.
* UTC-dated folder logic is identical across platforms.
* On Windows roots, paths look like `C:\…\prompts\YYYY\MM\DD\…`.

#### Common gotchas the command prevents

* No manual guessing of where to put files—deterministic UTC pathing is enforced.
* The prompt’s `<gsl-prompt id="…">` always matches its filename and the task folder.
* Backfills are trivial via `--date`, and scripted flows can rely on `--print-paths`.


</gsl-description>
</gsl-workflows>
<gsl-acceptance-tests>
<gsl-label>

## 5. Acceptance Tests
</gsl-label>

<gsl-acceptance-test id="1">
<gsl-performed-action>

1. When OBK project root is set, and I run `obk generate prompt` at 2025-08-09T12:00:00Z (UTC).
</gsl-performed-action>
<gsl-expected-result>

    Then the tool computes UTC date 2025-08-09 and a new trace id; a prompt file exists at `prompts/2025/08/09/<TRACE_ID>.md`; and an empty task folder exists at `tasks/2025/08/09/<TRACE_ID>/`. The file’s `<gsl-prompt id>` equals the same `<TRACE_ID>`. Exit code is 0.
</gsl-expected-result>
</gsl-acceptance-test>

<gsl-acceptance-test id="2">
<gsl-performed-action>

2. When I run `obk generate prompt --date 2025-08-09`.
</gsl-performed-action>
<gsl-expected-result>

    Then artifacts are created under `*/2025/08/09/*` regardless of local timezone; IDs and paths match the deterministic UTC date. Exit code is 0.
</gsl-expected-result>
</gsl-acceptance-test>

<gsl-acceptance-test id="3">
<gsl-performed-action>

3. When I run `obk generate prompt --id 20250809T130102+0000 --date 2025-08-09`.
</gsl-performed-action>
<gsl-expected-result>
    
    Then the prompt file name and the task folder name are exactly `20250809T130102+0000`, and the file’s `<gsl-prompt id>` attribute matches that value. Exit code is 0.
</gsl-expected-result>
</gsl-acceptance-test>

<gsl-acceptance-test id="4">
<gsl-performed-action>

4. When a prompt file already exists at the target path and I run `obk generate prompt --date 2025-08-09` without `--force`.
</gsl-performed-action>
<gsl-expected-result>

    Then the command exits non-zero with a clear message that the prompt file already exists and suggests using `--force`; the existing file remains unchanged and no new artifacts are created.
</gsl-expected-result>
</gsl-acceptance-test>

<gsl-acceptance-test id="5">
<gsl-performed-action>

5. When a prompt file already exists and I run `obk generate prompt --date 2025-08-09 --force`.
</gsl-performed-action>
<gsl-expected-result>

    Then the existing file is overwritten with the packaged template content and the correct `<gsl-prompt id>`; the task folder exists; and exit code is 0.
</gsl-expected-result>
</gsl-acceptance-test>

<gsl-acceptance-test id="6">
<gsl-performed-action>

6. When I run `obk generate prompt --dry-run --date 2025-08-09`.
</gsl-performed-action>
<gsl-expected-result>

    Then no files or folders are created or modified; the command prints the would-be prompt file path and task folder path; and exit code is 0.
</gsl-expected-result>
</gsl-acceptance-test>

<gsl-acceptance-test id="7">
<gsl-performed-action>

7. When I run `obk generate prompt --print-paths --date 2025-08-09`.
</gsl-performed-action>
<gsl-expected-result>

    Then the command prints absolute paths for the prompt file and task folder to stdout, creates the artifacts, and exits 0.
</gsl-expected-result>
</gsl-acceptance-test>

<gsl-acceptance-test id="8">
<gsl-performed-action>

8. When OBK project root is unset or invalid and I run `obk generate prompt`.
</gsl-performed-action>
<gsl-expected-result>

    Then the command exits non-zero with a clear error stating that the project root is not configured, and no files or folders are created.
</gsl-expected-result>
</gsl-acceptance-test>

<gsl-acceptance-test id="9">
<gsl-performed-action>

9. When I run `obk generate prompt --date 2025-08-09` on Windows with the project root set to `C:\work\obk-project`.
</gsl-performed-action>
<gsl-expected-result>

    Then artifacts exist at `C:\work\obk-project\prompts\2025\08\09\<TRACE_ID>.md` and `C:\work\obk-project\tasks\2025\08\09\<TRACE_ID>\`; paths use valid Windows separators; the prompt file is UTF-8 encoded; and exit code is 0.
</gsl-expected-result>
</gsl-acceptance-test>

<gsl-acceptance-test id="10">
<gsl-performed-action>

10. When I open the generated prompt file after a successful run.
</gsl-performed-action>
<gsl-expected-result>

    Then the XML header is present; line endings are `\n`; `<gsl-prompt id="...">` equals the folder/file name; and the structure matches the packaged programmatic template (differing only by the `id` substitution).
</gsl-expected-result>
</gsl-acceptance-test>

</gsl-acceptance-tests>

</gsl-block>
</gsl-prompt>