From f0b8830cff9b64ac422a62591c8ec1508a7d0b88 Mon Sep 17 00:00:00 2001 From: nullhack Date: Fri, 22 May 2026 14:33:45 -0400 Subject: [PATCH] cleanup: remove unnecessary artifacts tracked in git MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Untrack smith-managed files (AGENTS.md, .opencode/) — already in .gitignore - Delete root-level stale duplicates (domain_spec, glossary, product_definition) whose canonical versions live in docs/spec/ - Move interview notes from docs/ to .cache/interview-notes/ (gitignored) - Move event_storming.md from docs/spec/ to .cache/ - Move flow YAML fixtures from docs/flows/ to tests/fixtures/ --- .opencode/knowledge/workflow/flowr-spec.md | 221 --------------- AGENTS.md | 229 --------------- .../interview-notes/IN_20260422_cli_parser.md | 43 --- .../IN_20260422_initial_discovery.md | 63 ----- .../interview-notes/IN_20260426_cli_design.md | 61 ---- .../IN_20260426_condition_groups.md | 61 ---- .../IN_20260426_configurable_paths.md | 49 ---- .../IN_20260426_spec_design.md | 94 ------- .../IN_20260501_cli-flow-name-resolution.md | 55 ---- .../IN_20260501_session-management.md | 64 ----- .../IN_20260502_config-paths-gap.md | 55 ---- ...IN_20260505_subflow-transition-overhaul.md | 77 ----- .../IN_20260506_export-feature.md | 84 ------ .../IN_20260506_remove-fuzzy-match.md | 52 ---- .../IN_20260507_export-robustness.md | 38 --- docs/spec/event_storming.md | 264 ------------------ domain_spec.md | 244 ---------------- glossary.md | 38 --- product_definition.md | 38 --- .../flows => tests/fixtures}/arch-cycle.yaml | 0 .../fixtures}/feature-flow.yaml | 0 .../flows => tests/fixtures}/scope-cycle.yaml | 0 {docs/flows => tests/fixtures}/tdd-cycle.yaml | 0 23 files changed, 1830 deletions(-) delete mode 100644 .opencode/knowledge/workflow/flowr-spec.md delete mode 100644 AGENTS.md delete mode 100644 docs/interview-notes/IN_20260422_cli_parser.md delete mode 100644 docs/interview-notes/IN_20260422_initial_discovery.md delete mode 100644 docs/interview-notes/IN_20260426_cli_design.md delete mode 100644 docs/interview-notes/IN_20260426_condition_groups.md delete mode 100644 docs/interview-notes/IN_20260426_configurable_paths.md delete mode 100644 docs/interview-notes/IN_20260426_spec_design.md delete mode 100644 docs/interview-notes/IN_20260501_cli-flow-name-resolution.md delete mode 100644 docs/interview-notes/IN_20260501_session-management.md delete mode 100644 docs/interview-notes/IN_20260502_config-paths-gap.md delete mode 100644 docs/interview-notes/IN_20260505_subflow-transition-overhaul.md delete mode 100644 docs/interview-notes/IN_20260506_export-feature.md delete mode 100644 docs/interview-notes/IN_20260506_remove-fuzzy-match.md delete mode 100644 docs/interview-notes/IN_20260507_export-robustness.md delete mode 100644 docs/spec/event_storming.md delete mode 100644 domain_spec.md delete mode 100644 glossary.md delete mode 100644 product_definition.md rename {docs/flows => tests/fixtures}/arch-cycle.yaml (100%) rename {docs/flows => tests/fixtures}/feature-flow.yaml (100%) rename {docs/flows => tests/fixtures}/scope-cycle.yaml (100%) rename {docs/flows => tests/fixtures}/tdd-cycle.yaml (100%) diff --git a/.opencode/knowledge/workflow/flowr-spec.md b/.opencode/knowledge/workflow/flowr-spec.md deleted file mode 100644 index bdbe552..0000000 --- a/.opencode/knowledge/workflow/flowr-spec.md +++ /dev/null @@ -1,221 +0,0 @@ ---- -domain: workflow -tags: [fsm, state-machine, flow, yaml, flowr, transitions, conditions, session, config] -last-updated: 2026-05-06 ---- - -# Flowr Specification - -## Key Takeaways - -- Define flows as FSMs in YAML with states, transitions, guards, and exits; the flow YAML is the single source of truth for workflow routing. -- Declare `exits` on every flow as its contract with parent flows; parent `next` keys must match child `exits` exactly. -- Use `conditions` blocks on states to define named condition groups; reference them in transitions with `when`. -- Guarded transitions use `when` with expression strings (`==true`, `>=80%`); `when` accepts a dict, a named ref string, or a list mixing both; conditions are AND-combined with no inheritance. -- Carry runtime metadata in state-level `attrs` (agent, skills, input_artifacts, etc.); `attrs` is opaque to the engine and replaces flow-level attrs entirely (no merge). -- All CLI commands output **JSON by default** (structured, machine-parseable). Use `--text` flag for human-readable plain text. -- `next` command shows **all** transitions with status markers (`"open"` / `"blocked"`) and condition hints for blocked transitions. -- Sessions track workflow progress (flow, state, call stack) as YAML files in `.cache/sessions/` with atomic writes; `--session` on check/next/transition resolves flow/state automatically. -- Subflow exit names resolve through the parent flow's transition map (not used directly as state IDs). Enables subflow chaining and recursive entry up to 3 levels. -- Configuration reads `[tool.flowr]` from `pyproject.toml` (flows_dir, sessions_dir, default_flow, default_session); CLI flags override pyproject.toml which overrides defaults. -- Flow name resolution: commands accept short names (e.g., `architecture-flow`) resolved from the configured flows directory, or full file paths. -- Immutable loaded flows, closed evidence schema, isolated subflow context, filesystem wins over session on conflict. Extension fields (non-reserved keys) are allowed and not interpreted by the validator. - -## Concepts - -**YAML Flow Definitions**: Flows are finite state machines defined in `.flowr/flows/` as YAML files. Each flow has a name, version, exits, and states. The first state is the initial state. The flow YAML is the single source of truth for what happens at each state; agents read it to determine routing; skills define how to execute. - -**JSON-First Output**: All CLI commands return JSON by default for machine-parseable structured output. The `--text` flag provides human-readable plain text. JSON output includes structured keys for programmatic extraction: `check` returns `{"id", "attrs", "transitions"}`, `next` returns `{"state", "transitions": [{"trigger", "target", "status", "conditions"}]}`, `transition` returns `{"from", "trigger", "to"}`. - -**Exits as Contracts**: Every flow declares `exits`: the list of ways it can terminate. Parent flows reference these exit names in their `next` maps. This creates a typed contract between flows. Adding a new exit is a minor version bump; removing or renaming one is a major breaking change. - -**Conditions and Guards**: States may define `conditions` blocks containing named condition groups. Transitions reference these groups with `when` to create guarded transitions. The `when` field accepts three forms: a dict (inline condition-map), a string (reference to a named group), or a list (mix of named refs and inline dicts). All conditions are AND-combined. A named ref that does not match a group defined on the same state causes a validation error. Condition expressions use operators `==`, `!=`, `>=`, `<=`, `>`, `<`. Numeric extraction is applied to both sides (e.g., `>=80%` vs `75%` compares 80 vs 75). Plain strings without operators are treated as `==` (implicit equality). No inheritance; every condition is explicit on the transition where it applies. - -**State Attrs**: State-level `attrs` carry runtime metadata that the flowr engine ignores but agents and skills read. Common keys: `description`, `owner`, `skills`, `input_artifacts`, `edited_artifacts`, `output_artifacts`. State-level `attrs` replace flow-level attrs entirely (no merge, no deep merge). The `attrs` field is the designated extension point: implementations should place implementation-specific data inside `attrs` rather than as top-level keys. - -**Subflow Invocation**: A state with a `flow:` field becomes a subflow invocation. The parent's `next` keys must match the child's `exits` exactly. Subflows use a call-stack mechanism: push on entry, pop on exit. Context is isolated: only the current flow is visible. Cross-flow cycles are forbidden. - -**Subflow Exit Resolution (v1.0.0)**: Exit names resolve through the parent flow's transition map instead of being used directly as state IDs. This enables subflow chaining (atomic exit + re-enter next subflow) and recursive subflow entry up to 3 levels deep (e.g., define-flow → spec-validation-flow). Stack frames record the correct parent state (subflow wrapper, not pre-transition state). - -## Content - -### Top-Level Fields - -| Field | Required | Description | -|---|---|---| -| `flow` | yes | Unique name string, used for subflow references | -| `version` | yes | Semver (e.g., `1.2.0`) | -| `params` | no | List of parameter declarations (strings or `{name, default?}` objects) | -| `exits` | yes | List of exit names: the contract this flow offers to parent flows | -| `attrs` | no | Opaque dict for project-specific data; the library ignores this entirely | -| `states` | yes | Ordered list of state objects; first state is the initial state | - -### State Fields - -| Field | Required | Description | -|---|---|---| -| `id` | yes | Unique identifier within this flow | -| `next` | yes* | Trigger → target mapping; required unless exit-only | -| `flow` | no | If present, makes this state a subflow invocation | -| `flow-version` | no | Semver constraint for the referenced flow (e.g., `"^1"`) | -| `attrs` | no | Opaque dict; replaces flow-level attrs entirely (no merge) | -| `conditions` | no | Named condition groups for guarded transitions | - -*States must have `next` or be referenced only by exit targets. - -### Transition Format (`next` values) - -| Form | Syntax | Description | -|---|---|---| -| Simple | `approved: step-5` | String target, no conditions | -| Guarded | `approved: { to: step-5, when: {...} }` | Mapping with conditions | -| Mixed | Both in same `next` | Simple and guarded targets coexist | - -### Condition Syntax (`when` values) - -| Operator | Meaning | Example | -|---|---|---| -| `==value` | Equality match (implicit for plain values) | `==true`, `==BASELINED`, `approved` | -| `!=value` | Inequality match | `!=false` | -| `>=N` | Greater than or equal | `>=80%` (compares 80) | -| `<=N` | Less than or equal | `<=5`, `<=8` | -| `>N` | Greater than | `>0` | -| `=80" }` | Inline condition-map | -| String | `when: quality_gate` | Reference to a named condition group | -| List | `when: [quality_gate, { override: "==yes" }]` | Mix of named refs and inline dicts, AND-combined | - -Named refs must resolve to a condition group defined on the same state. Unknown references are validation errors. - -### Conditions Block - -States may define a `conditions` block (sibling of `attrs` and `next`) containing named condition groups: - -```yaml -conditions: - invest-passed: - independent: ==true - negotiable: ==true - valuable: ==true -next: - done: - to: next-state - when: invest-passed - partial: - to: review - when: - - invest-passed - - { override: "==yes" } -``` - -Named condition references in `when` clauses must resolve to a key in the same state's `conditions` block. Unknown references are validation errors. - -### Exit System - -- `exits` is a flat list at flow level, always required -- Any state can reference an exit name in its `next` map -- A `next` target that matches both a state id and an exit name is a validation error (ambiguous reference) -- Every `next` target must resolve to either a state id or an exit name -- Multiple exits can map to the same parent state - -### Subflow Model - -- `flow: ` on a state makes it a subflow (no `type` field needed) -- `flow-version: "^1"` constrains which versions are compatible -- Parent `next` keys must match child's `exits` list exactly -- Subflows use a call-stack: push on entry, pop on exit -- Context is isolated: only current flow visible -- Cross-flow cycles are forbidden (detected via DFS at load time) -- Exit names resolve through parent flow's transition map (not used directly as state IDs) -- Subflow chaining: atomic exit + re-enter next subflow without manual state manipulation -- Recursive entry: supports up to 3-level nesting (define-flow → discovery-flow, develop-flow → development-flow, etc.) -- Stack frames record the subflow wrapper state (not the pre-transition state) -- `.yaml` extension fallback: flow references without extension are resolved automatically -- `session init` auto-enters subflow when first state has a `flow:` field - -### Semver Conventions - -| Change | Version impact | -|---|---| -| Adding a new exit | Minor bump | -| Adding states or requirements | Patch (non-breaking) | -| Removing or renaming exits | Major (breaking) | - -### Validation Rules (Load-Time) - -A conforming validator MUST check all of the following at load time: - -1. Every `next` target resolves to a state id or exit name -2. No `next` target is ambiguous (matches both a state id and an exit name) -3. Parent `next` keys match child `exits` exactly -4. No cross-flow cycles (detected via DFS) -5. Exit names in `exits` are referenced by at least one state -6. Named condition references in `when` resolve to a group defined on the same state -7. Params without defaults are provided at flow invocation time - -### Conformance Levels - -| Level | Meaning | Requirement | -|---|---|---| -| MUST | Required for all conforming implementations | Immutable loaded flows, closed evidence schema, validation rules | -| SHOULD | Recommended but optional | Filesystem wins over session cache on conflict, semver for flows | -| MAY | Optional extension | Per-state attrs, flow params, Mermaid export | - -### Extension Fields and Reserved Keys - -A flow definition MAY contain fields not specified in the specification. Such extension fields are not interpreted by a conforming validator. The reserved keys are: `flow`, `version`, `params`, `exits`, `attrs`, `states`, `id`, `next`, `to`, `when`, `conditions`, `flow-version`. Implementations MUST NOT assign semantics to reserved keys beyond what the specification defines. Implementation-specific data SHOULD be placed inside `attrs`. - -### Session Model - -Sessions persist workflow progress as YAML files in `.cache/sessions/` with atomic writes (temp-file-then-rename). Each session tracks: - -| Field | Description | -|-------|-------------| -| `flow` | Current flow name | -| `state` | Current state id | -| `name` | Session identifier (used as filename stem) | -| `created_at` | ISO 8601 timestamp | -| `updated_at` | ISO 8601 timestamp (updated on every transition) | -| `stack` | List of `{flow, state}` frames for subflow nesting | -| `params` | Per-flow parameter overrides | - -Subflow entry pushes a `SessionStackFrame(flow, state)` onto the stack and updates the session's flow/state to the subflow. Subflow exit pops the frame and restores the parent flow/state. - -### Configuration - -flowr reads `[tool.flowr]` from `pyproject.toml`. Resolution priority: CLI flags > pyproject.toml > defaults. - -| Key | Default | Description | -|-----|---------|-------------| -| `flows_dir` | `.flowr/flows` | Directory containing flow YAML files | -| `sessions_dir` | `.cache/sessions` | Directory for session YAML files | -| `default_flow` | `define-flow` | Flow name used when none specified | -| `default_session` | `default` | Session name used with bare `--session` | - -### Design Principles - -1. **Immutable loaded flows**: edits produce copies -2. **Closed evidence schema**: keys must exactly match -3. **Isolated subflow context**: only current flow visible -4. **Session truth assumption**: filesystem wins over session on conflict -5. **Thin enforcement**: validate only, no execution -6. **No auto-rollback**: no transition limits -7. **Atomic session writes**: temp-file-then-rename prevents corruption -8. **JSON-first output**: structured data by default; `--text` for human-readable -9. **Complete transition visibility**: `next` shows all transitions with status markers -10. **Extension-friendly**: non-reserved keys are ignored by the validator; `attrs` is the designated extension point - -## Related - -- [[agent-design/principles]] -- [[skill-design/principles]] -- [[knowledge-design/principles]] \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md deleted file mode 100644 index b36fc40..0000000 --- a/AGENTS.md +++ /dev/null @@ -1,229 +0,0 @@ -## Golden Rules - -Post-mortem analysis shows these practices prevent most project failures. Violating them triggers costly rework. Defects caught later cost 10–100× more to fix (Boehm, 1981). - -1. **Never skip a flow state.** Every state boundary goes through flowr check → dispatch to owner → flowr transition. No shortcuts, no manual session edits, no jumping ahead. -2. **Never bypass owner dispatch.** Each state has an owner agent. The orchestrator dispatches to that agent with skills loaded. It never does the work itself. One agent, one hat at a time. -3. **Never collapse progressive gates.** Multi-step gates (review: design → structure) are separate for a reason. Each one can fail independently and send work back. Conventions (naming, docstrings, formatting) are enforced in a separate polish state after feature acceptance. -4. **Never decompose a feature without stakeholder approval.** If a feature is too large for INVEST, propose the split to the stakeholder with rationale. They decide what's core vs. deferred. -5. **Verify inputs exist before entering a state.** Every state's `in` artifacts must be readable on disk. If they're missing, stop and reconstruct them. Don't proceed with assumed knowledge. -6. **A feature is not done until every interview requirement is traced.** Every stakeholder Q&A must map to either a passing @id test or an explicit stakeholder deferral. Untraced requirements = incomplete delivery. -7. **Respect git branch discipline.** Every state declares `git: dev`, `git: feature`, or `git: main` in its attrs. **Verify the current branch matches `attrs.git` before starting any work.** If the branch is wrong, checkout or create the correct branch before proceeding. Never switch branches mid-state. Before exiting a project-phase flow (discovery, architecture, branding, setup), set `committed-to-dev-locally: ==verified` evidence. Changes must be committed to dev before advancing. -8. **Every feature branch must be merged back to dev.** A feature is not delivered until its commits are squash-merged into local dev and `task test-fast` passes on dev. The develop-flow exits to deliver-flow which handles the merge, but the orchestrator must never leave a feature branch dangling — if the session ends mid-feature, resume and complete the merge before starting new work. - -## Project Structure -- `.flowr/flows/`: YAML state machine definitions (source of truth for routing) -- `.cache/sessions/`: runtime session state -- `.templates/`: artifact templates (strip `.templates/` prefix and `.template` suffix → destination path) -- `.opencode/`: agents, skills, and knowledge - -## Artifact Templates - -When creating a document, use the template in `.templates/` that matches the artifact type. Strip the `.templates/` prefix and `.template` suffix to determine the destination path. For example: -- `.templates/docs/adr/ADR_YYYYMMDD_.md.template` → `docs/adr/ADR_20260430_my_decision.md` -- `.templates/docs/features/.feature.template` → `docs/features/my_feature.feature` -- `.templates/.cache/interview-notes/IN_YYYYMMDD_.md.template` → `.cache/interview-notes/IN_20260430_session_management.md` -- `.templates/.cache/sim/simulation_results_YYYYMMDDTHHMMSS.md.template` → `.cache/sim/simulation_results_20260517T143000.md` -- `.templates/.cache/acceptance/.md.template` → `.cache/acceptance/domain_value_objects.md` - -If no template exists for an artifact type, create the document without one. - -## Knowledge Resolution -`[[domain/concept]]` → `.opencode/knowledge/{domain}/{concept}.md` - -### Progressive Knowledge Loading - -Knowledge files use 4-section progressive disclosure. Choose the level that matches the task depth: - -| Fragment | Loads | When to Use | -|----------|-------|-------------| -| `#key-takeaways` | Frontmatter + Key Takeaways | Quick reference or reminders when knowledge is already familiar | -| `#concepts` | Frontmatter + Key Takeaways + Concepts | Understanding concepts without detailed examples or procedures | -| (no fragment) | Entire file | Performing evaluation, review, or implementation that needs detection heuristics, examples, tables, and procedures | - -**Rule of thumb:** If the agent needs to **find violations, detect patterns, or apply detailed criteria**, load the full document. If it only needs to **recall a principle or definition**, `#key-takeaways` is sufficient. - -### Extraction Commands - -```bash -sed '/^## Concepts/Q' file.md # Frontmatter + Key Takeaways only -sed '/^## Content/Q' file.md # Frontmatter + Key Takeaways + Concepts -cat file.md # Full document -``` - -Examples: -- `[[requirements/invest#key-takeaways]]`: quick reference for INVEST criteria -- `[[requirements/invest#concepts]]`: understanding what each letter means with context -- `[[software-craft/smell-catalogue]]`: full catalogue needed to detect code smells during review - -## Discovery -Do not enumerate files, as they go stale. Discover what exists at runtime: - -```bash -ls .opencode/agents/ # agent identity definitions -ls .opencode/skills/ # skill directories (each has SKILL.md) -find .opencode/knowledge -name '*.md' # knowledge files -find .templates -name '*.template' # artifact templates -find docs/research -name '*.md' # research source notes (cited by knowledge files) -``` - -## File Naming Conventions - -### Artifact Names in Flow Attrs - -Artifact names in `in` and `out` lists use these conventions: - -| Pattern | Meaning | Example | -|---------|---------|---------| -| `filename.md` | A specific document | `domain_spec.md`, `product_definition.md` | -| `dir/.ext` | A specific instance identified by parameter | `features/.feature`, `.cache/interview-notes/.md`, `adr/.md` | -| `dir/*.ext` | Multiple documents of that type available in `in` | `.cache/interview-notes/*.md`, `adr/*.md` | -| `conceptual_name` | A runtime artifact that passes between states within a flow | `typed-source-stubs`, `test-implementations` | - -Placeholders in template filenames and flow artifact paths use the `` pattern where **type** identifies the document kind and **_id** signals snake_case formatting. See template filenames for the canonical placeholder names. - -**File naming rule:** All filenames use **snake_case** (e.g., `domain_value_objects.feature`, `ADR_20260504_protocol_adapters.md`). **Cache folders** use kebab-case for multi-word names (e.g., `interview-notes/`, `post-mortem/`). **Python/test folders** use snake_case (e.g., `tests/features/`). - -**Wildcards (`*`)** in `in` indicate that multiple documents of that type are available. List the directory contents first, then read selectively based on the task. When a state creates a single instance, use a `` name instead. - -**Runtime artifacts** (not backed by files) use descriptive names that make their purpose clear: `typed-source-stubs` (source files with type signatures only), `test-skeletons` (test files with structure only), `test-implementations` (tests with bodies), `source-implementations` (production code with behavior), `refactored-source` (code after refactoring pass), `feature-commits` (git commits for one feature), `merged-commits` (commits merged to local main), `root-cause-analysis` (analysis findings), `polished-source` (code after convention application). - -**Cache artifacts** are persisted to `.cache/` for cross-session durability. They are not spec documents but process evidence that survives session boundaries: `.cache/acceptance/.md` (PO acceptance record with traceability matrix), `.cache/interview-notes/.md` (raw stakeholder input, archival after discovery), `.cache/sim/simulation_results_.md` (simulation evidence per iteration). - -**Environment artifacts** are produced by tooling rather than flow states: `coverage-reports` (test coverage output), `test-output` (test runner output), `linter-output` (linter output). These exist on disk after running the relevant tool and are referenced in `in` but not in any state's `out`. - -## Flowr Commands - -All commands output **JSON by default**. Use `--text` for human-readable output. All commands require the virtual environment: `source .venv/bin/activate`. See [[workflow/flowr-operations]] for full command reference, output formats, and workflow pattern. - -Commands accept short flow names (e.g., `planning-flow`) or full file paths. Use `--session ` to resolve flow/state from a session instead of specifying them explicitly. - -| Command | Purpose | -|---------|---------| -| `python -m flowr check ` | Show state attrs, owner, skills, and transitions | -| `python -m flowr check ` | Show conditions for a specific transition | -| `python -m flowr check --session` | Show current session state (read-only) | -| `python -m flowr check --session ` | Show conditions for a transition via session | -| `python -m flowr next [--evidence key=value]` | Show all transitions with status markers (`open`/`blocked`) | -| `python -m flowr next --session [--evidence key=value]` | Show transitions from session state with status | -| `python -m flowr transition [--evidence key=value]` | Advance to the next state | -| `python -m flowr transition --session [--evidence key=value]` | Advance using session (auto-updates session) | -| `python -m flowr validate []` | Validate flow definition(s) | -| `python -m flowr validate --session` | Validate the current (sub)flow from session | -| `python -m flowr states ` | List all states in a flow | -| `python -m flowr states --session` | List states in the current (sub)flow from session | -| `python -m flowr mermaid ` | Export flow as Mermaid diagram | -| `python -m flowr config` | Show resolved configuration with sources | -| `python -m flowr session init [--name ]` | Create a session at the flow's initial state | -| `python -m flowr session show [--name ]` | Display current session state and call stack | -| `python -m flowr session set-state [--name ]` | Manually update session state | -| `python -m flowr session list` | List all sessions | - -## Project Commands - -Check `pyproject.toml` for taskipy tasks and tool configuration. Common commands: - -| Command | Purpose | -|---------|---------| -| `task test` | Run tests with short tracebacks | -| `task test-fast` | Run fast tests only (excludes slow marker) | -| `task test-build` | Run full test suite with coverage, hypothesis stats, and HTML report | -| `task run` | Run the application | - -Linting and formatting: - -| Command | Purpose | -|---------|---------| -| `ruff check .` | Functional lint (bugs, security, complexity) | -| `task conventions` | Full lint (all rules including naming, docstrings, formatting) | -| `ruff format .` | Auto-format | - -## Session Protocol - -Every state transition must go through flowr. Do not skip steps or guess transitions. See [[workflow/flowr-operations]] for the full command reference. - -1. **State entry:** Run `python -m flowr check --session` to see current state, owner, skills, and available transitions (JSON output: parse `attrs.owner`, `attrs.skills`, `attrs.in`, `attrs.out`, `transitions`). Verify all `in` artifacts exist on disk. If any are missing, stop and flag rather than proceeding with assumed knowledge. Announce the state in one line, e.g. `→ specify-feature`. No preamble, no recap of how you got here. -2. **Dispatch to owner agent:** The state's `owner` field names the responsible agent. Call that agent as a subagent with the state's `skills` loaded, passing the state attrs as context. Owner mapping: `PO` → product-owner, `DE` → domain-expert, `SE` → software-engineer, `SA` → system-architect, `R` → reviewer, `Design Agent` → design-agent, `Setup Agent` → setup-agent. -3. **Do the work:** Load and execute the skill(s) listed in the state's `skills` field. Read all `in` artifacts before starting work — they are mandatory context. Write only to `out` artifacts. Commit changes to the branch indicated by the state's `git` attribute (`main` or `feature`). Never switch branches mid-state. -4. **State exit:** The anchor item in the todo handles this (see [[workflow/todo-anchor-protocol#key-takeaways]]). - -### Convention Boundary - -Convention checks (full lint via `task conventions`, `ruff format`, pyright, docstrings, type annotations) are **prohibited** during design-phase states (create-py-stubs, write-test, implement-minimum, refactor, review-gate). Only `task test-fast` is permitted. The default `ruff check .` runs functional rules only (bug-catching, security, complexity). Design changes invalidate convention work. Conventions are applied in the polish state after feature acceptance. - -When dispatching an agent during design phase: -- Do NOT include convention tool commands in the prompt -- Only include verification steps that the skill explicitly defines -- The skill's verification steps are the ceiling, not the floor - -Exception: The polish-code skill explicitly runs convention commands (`task conventions`, `ruff format`, `task static-check`) after feature acceptance. - -### Procedural Contract - -**One state = one dispatch.** Every state transition produces exactly one agent dispatch with exactly the skills listed in the state's `skills` field. Never combine multiple states into a single dispatch. The orchestrator's job is routing, not doing. See [[workflow/todo-anchor-protocol#concepts]] for the full protocol. - -### Todo-Driven State Execution - -At state entry, generate a procedural todo list using the todowrite tool. Format: `[X]` completed, `[ ]` pending, `[~]` anchor (always last). - -1. **Preparation** (`[ ]`): verify current branch matches `attrs.git` (checkout or create if wrong). List available `in` artifacts. -2. **Dispatch** (`[ ]`): dispatch to the owner agent listed in `attrs.owner` as a subagent with skills loaded. The orchestrator MUST NOT do the work itself — only route. Owner mapping: `PO` → product-owner, `DE` → domain-expert, `SE` → software-engineer, `SA` → system-architect, `R` → reviewer, `Design Agent` → design-agent, `Setup Agent` → setup-agent. -3. **Load skills** (`[ ]`): read every skill file listed in `attrs.skills` from `.opencode/skills//SKILL.md`. This step is MANDATORY — never skip it. -4. **Skill-derived work items** (`[ ]`): one todo item per numbered step in the skill, using the skill's own language verbatim. These are the substantive work items. Self-generated items are only permitted for infrastructure (read artifacts, commit) — never for the core procedure. -5. **Output** (`[ ]`): one per `out` artifact -6. **Verification** (`[ ]`): check constraints, run tests/lint if applicable -7. **Anchor** (`[~]`, always last): flowr next → pick transition → flowr transition → rewrite todo - -The todo is the execution contract. Every item must be marked `[X]` before the anchor fires. One state per todo; never span multiple states or collapse loop iterations. Full protocol: [[workflow/todo-anchor-protocol]]. - -**Todo discipline**: After completing ANY step, update the todowrite tool to mark it `[X]` and set the next step `[ ]` to `in_progress`. If the todo list is empty or missing, regenerate it immediately — working without a todo means working without a contract. Never let the todo go stale between steps. - -### Session Init - -Before starting a flow, create a session to track progress: - -```bash -python -m flowr session init --name -``` - -For project-level flows, use a descriptive name like `project`. For feature flows, use the feature name. The session tracks the current flow, state, call stack (for subflows), and params (including `feature-id`). When the first state has a `flow:` field, `session init` auto-enters the subflow. - -The three primary flows are independently invocable: -- `define-flow` — spec creation, validation, feature refinement, and architecture (discovery → spec-validation → refine-features → architecture) -- `develop-flow` — feature selection, example writing, TDD implementation, acceptance (per feature cycle) -- `deliver-flow` — squash-merge, publish decision, PR creation - -### Cross-Flow Routing - -When develop-flow exits `needs-architecture`, the orchestrator must re-enter define-flow at the `architecture` state. Start a new define-flow session and use `flowr session set-state architecture` to skip to the architecture state. The architecture-flow fast-path (`architecture-complete: ==verified`) means re-running is cheap when no changes are needed. - -When post-mortem-flow exits `needs-architecture`, follow the same procedure: re-enter define-flow at `architecture`. - -### Branch Discipline - -States declare their git context in `attrs.git`: -- `git: main`: all changes are committed to the local main branch -- `git: feature`: all changes are committed to the current feature branch - -Before exiting a project-phase flow (define, branding, setup), the exit transition requires `committed-to-dev-locally: ==verified` evidence. This guarantees project artifacts are persisted before advancing to the next phase. - -### Within a State - -Announce the state once at the top, then go quiet: - -- **Respect the artifact contract:** The state's attrs define what the owner agent may read and write: - - `in`: Mandatory context. All `in` artifacts must be read in full before starting work. For wildcard patterns (`*.md`), list the directory first, then read all discovered files. The `in` list defines what you *must* read — no skipping, no selective reading. - - `out`: May create or edit. Section sub-lists indicate which sections the state should produce or update. Follow the **out artifact protocol** (see below). - - Files not in `out` must not be written to. If findings affect an artifact outside the output contract, flag them in output notes and defer the change to the step that owns that artifact. - - The flow contract must always be followed unless the stakeholder explicitly asks to break it. - - **Cumulative editing:** When a flow loops back to a state that was previously executed (e.g., `needs-reinterview` → `stakeholder-interview` → `domain-discovery`), the `out` artifact is **edited**, not recreated. The agent reads the existing file, incorporates new information, and adjusts existing content. This is especially important for `domain_spec.md` and `glossary.md` which accumulate knowledge across multiple discovery iterations. -- **Out artifact protocol:** Before writing to any `out` artifact: - 1. Check if the file exists on disk. - 2. **If it exists** → read it, then edit only the sections declared in the flow's `out` section sub-lists. Preserve existing content outside those sections. - 3. **If it does not exist** → resolve the template path: take the destination path, prepend `.templates/`, append `.template` (e.g., `docs/spec/domain_spec.md` → `.templates/docs/spec/domain_spec.md.template`). Copy the template to the destination path, then edit the declared sections. Strip any template placeholders during editing. - 4. **If no template exists** for a non-Python file referenced in `in`/`out`, raise an error for the stakeholder to decide. - 5. **Environment artifacts** (e.g., `coverage-reports`, `test-output`, `linter-output`) are produced by tooling rather than flow states. They exist on disk after running the relevant tool and are referenced in `in` but not in any state's `out`. -- **Specification documents are read-only during development.** During TDD and review cycles, the SE and reviewer may ONLY modify production code and test code. Spec document inconsistencies must be FLAGGED in output notes, not fixed directly. Spec docs are owned by other flow states and can only be changed through the appropriate flow step, after code is reviewed and approved. -- **Flag issues with precise citations.** When flagging a problem during review or adversarial analysis, include file:line references (e.g., "domain_spec.md:23 conflicts with login.feature:15"). Vague findings create rework. -- **Do the work with the fewest, quietest commands.** Suppress verbose output. If a command can be scoped with a flag, pipe, or limit, use it. Don't dump full files or directory listings when a targeted query answers the question. -- **No narration between steps.** The command and its output are the conversation. Don't echo what you're about to do or what you just did. \ No newline at end of file diff --git a/docs/interview-notes/IN_20260422_cli_parser.md b/docs/interview-notes/IN_20260422_cli_parser.md deleted file mode 100644 index 5c99327..0000000 --- a/docs/interview-notes/IN_20260422_cli_parser.md +++ /dev/null @@ -1,43 +0,0 @@ -# IN_20260422_version_source — Version source decision - -> **Status:** COMPLETE -> **Interviewer:** SA -> **Participant(s):** Stakeholder -> **Session type:** Feature specification - ---- - -## General - -| ID | Question | Answer | -|----|----------|--------| -| Q1 | How should the --version flag read the version string at runtime? | importlib.metadata.version() — stdlib canonical API for installed package metadata | -| Q2 | What about reading pyproject.toml directly with tomllib? | Works but requires file path resolution and I/O; importlib.metadata is simpler | -| Q3 | Should we expose a __version__ constant in flowr/__init__.py? | No — creates a second source of truth that still needs importlib.metadata or hardcoding to populate | - ---- - -## Quality Attributes - -| ID | Attribute | Scenario | Target | Priority | -|----|-----------|----------|--------|----------| -| QA1 | Correctness | When --version is invoked, the version string matches pyproject.toml exactly | 100% match | Must | - ---- - -## Pain Points Identified - -- Hardcoded version strings drift from pyproject.toml over time - -## Business Goals Identified - -- Single source of truth for version information - -## Terms to Define (for glossary) - -- Package Metadata - -## Action Items - -- [x] Record decision as ADR_20260422_version_source -- [ ] Implement version retrieval via importlib.metadata \ No newline at end of file diff --git a/docs/interview-notes/IN_20260422_initial_discovery.md b/docs/interview-notes/IN_20260422_initial_discovery.md deleted file mode 100644 index f39b6d5..0000000 --- a/docs/interview-notes/IN_20260422_initial_discovery.md +++ /dev/null @@ -1,63 +0,0 @@ -# IN_20260422_initial_discovery — Initial project discovery - -> **Status:** COMPLETE -> **Interviewer:** PO -> **Participant(s):** Stakeholder -> **Session type:** Initial discovery - ---- - -## General - -| ID | Question | Answer | -|----|----------|--------| -| Q1 | Who are the users? | Python engineers starting a new project who want rigorous tooling without the setup cost. | -| Q2 | What does the product do at a high level? | Provides a fully configured Python project skeleton: CI, quality tooling, test infrastructure, and an AI-assisted five-step delivery workflow. | -| Q3 | Why does it exist — what problem does it solve? | Setting up a production-grade Python environment from scratch is expensive and often skipped; engineers then accrue quality debt from day one. | -| Q4 | When and where is it used? | At project inception — cloned once, then evolved as features are added via the built-in workflow. | -| Q5 | Success — what does "done" look like? | An engineer clones the template and ships a meaningful first feature within a single session, with all quality gates passing. | -| Q6 | Failure — what must never happen? | The template introduces more friction than it removes, or locks engineers into choices they cannot override. | -| Q7 | Out-of-scope — what are we explicitly not building? | Runtime infrastructure (databases, queues, cloud deployment), UI frameworks, domain-specific business logic. | - -## Runtime Behaviour - -| ID | Question | Answer | -|----|----------|--------| -| Q8 | Should the template ship with any working feature, or be purely empty? | It should ship with exactly one working demonstration feature so engineers see the full workflow end-to-end. | - -## Feature: cli-entrypoint - -| ID | Question | Answer | -|----|----------|--------| -| Q9 | Which behavioural areas are in scope for the template's own feature backlog? | Just one simple command in the base package — useful for any starting project, simple enough not to bloat the app, and showcasing the template's capabilities end-to-end. | -| Q10 | What kind of command would be "useful for any starting project"? | Stakeholder asked: "if I choose version, what will it add to my app/ folder?" — confirmed interest in version-style command after seeing the footprint (one file, ~10 lines, zero new dependencies). | -| Q11 | Three options presented: (A) --help only, (B) --version only, (C) --help + --version combined. Which option for the demonstration feature? | Option C — --help + --version combined. python -m flowr --help shows app name, tagline, and available options. python -m flowr --version shows flowr read from package metadata. Zero new dependencies, all code in flowr/__main__.py. | - ---- - -## Quality Attributes - -| ID | Attribute | Scenario | Target | Priority | -|----|-----------|----------|--------|----------| -| QA1 | Correctness | When the CLI entrypoint is invoked, it produces the expected output without errors | Zero errors on valid invocation | Must | - ---- - -## Pain Points Identified - -- Setting up production-grade Python environments is expensive and often skipped - -## Business Goals Identified - -- Engineers should ship a meaningful first feature within a single session with all quality gates passing - -## Terms to Define (for glossary) - -- CLI Entrypoint -- Package Metadata -- Demonstration Feature - -## Action Items - -- [x] Confirm demonstration feature choice (Option C: --help + --version) -- [ ] Write .feature file for cli-entrypoint \ No newline at end of file diff --git a/docs/interview-notes/IN_20260426_cli_design.md b/docs/interview-notes/IN_20260426_cli_design.md deleted file mode 100644 index a5c3090..0000000 --- a/docs/interview-notes/IN_20260426_cli_design.md +++ /dev/null @@ -1,61 +0,0 @@ -# IN_20260426_cli_design — CLI design session - -> **Status:** COMPLETE -> **Interviewer:** PO -> **Participant(s):** Stakeholder -> **Session type:** Feature specification - ---- - -## Feature: flowr-cli - -| ID | Question | Answer | -|----|----------|--------| -| Q34 | Should the CLI be purely one-shot or support an interactive mode? | One-shot only — each command is a separate invocation, no interactive/REPL mode. | -| Q35 | What should the check command show? | Multiple commands: check shows state details, next shows possible next states. check shows conditions for a specific transition. | -| Q36 | What should next show given state + evidence? | Show passing transitions only — evaluate guard conditions and show only transitions whose conditions pass. | -| Q37 | Should goto be stateless or session-based? | Stateless transition — compute the next state given current state + trigger + evidence, print result. No session file. | -| Q38 | For image, should the CLI call an external tool or just output Mermaid text? | SA decision — deferred to system-architect for implementation approach. | -| Q39 | Should validate be a subcommand? | Yes — a separate validate subcommand that checks a flow definition against the spec. | -| Q40 | What output format should CLI commands produce? | Text by default, JSON with a --json flag for programmatic use. | -| Q41 | How should evidence be provided to next and transition? | SA decision — deferred to system-architect for interface design. | -| Q42 | When transition leads to a subflow state, what happens? | Enter the subflow's first state — moving to a "flow state" starts the subflow at its initial state. | -| Q43 | Should the CLI support loading multiple flow definitions at once? | Yes — subflows are loaded automatically by reference from the root flow. | -| Q44 | Confirm the full list of CLI subcommands. | Confirmed list: validate, states, check, next, transition, mermaid, image. | -| Q45 | Alternative names for goto? | transition — chosen by stakeholder as the command name. | -| Q46 | How should the CLI find subflow files? | SA decision — deferred to system-architect for lookup strategy. | -| Q47 | Should next show what evidence each transition requires? | Yes — check shows required conditions. | -| Q48 | Should there be a states command? | Yes — a separate states command that lists all states in a flow. | -| Q49 | What should validate output? | SA decision — deferred to system-architect for output format. | -| Q50 | Should condition checking be part of check or a separate command? | Same command, different args — check shows state details, check shows conditions. | -| Q51 | When transition enters a subflow, should output show subflow name + first state or just first state? | SA decision — deferred to system-architect. | -| Q52 | Should CLI commands use exit codes for pass/fail? | SA decision — deferred to system-architect. | -| Q53 | Is the primary input for all commands a single YAML file path? | SA decision — deferred to system-architect for input interface design. | - ---- - -## Quality Attributes - -| ID | Attribute | Scenario | Target | Priority | -|----|-----------|----------|--------|----------| -| QA5 | Usability | When a developer runs a CLI subcommand, the output is unambiguous and actionable | Key-value text format with clear error messages | Must | - ---- - -## Pain Points Identified - -- Many design decisions deferred to SA for implementation approach - -## Business Goals Identified - -- A consistent, Unix-y CLI that is easy to script and pipe - -## Terms to Define (for glossary) - -- CLI Subcommand -- Flow Loading - -## Action Items - -- [ ] SA to resolve deferred decisions (Q38, Q41, Q46, Q49, Q51, Q52, Q53) -- [ ] Write .feature file for flowr-cli \ No newline at end of file diff --git a/docs/interview-notes/IN_20260426_condition_groups.md b/docs/interview-notes/IN_20260426_condition_groups.md deleted file mode 100644 index b230d7e..0000000 --- a/docs/interview-notes/IN_20260426_condition_groups.md +++ /dev/null @@ -1,61 +0,0 @@ -# IN_20260426_condition_groups — Named condition groups specification - -> **Status:** COMPLETE -> **Interviewer:** PO -> **Participant(s):** Stakeholder -> **Session type:** Feature specification - ---- - -## Cross-cutting - -| ID | Question | Answer | -|----|----------|--------| -| Q54 | Should flow-definition-spec validation rules be extended for the conditions field? | Yes, extend the flow-definition-spec validation. Bump a minor version. | -| Q55 | Should check display the resolved flat condition dict, the original named references, or both? | check displays the resolved flat condition dict. | -| Q56 | Should the Mermaid converter show named condition groups by name or as resolved conditions? | Mermaid shows resolved conditions (not named references). | -| Q57 | After inlining named references into a flat dict, does the closed evidence schema apply to the combined/resolved dict? | Yes, evidence must pass all the combined conditions for a state. | - -## Feature: named-condition-groups - -| ID | Question | Answer | -|----|----------|--------| -| Q58 | When a named reference and an inline dict in the same when list have overlapping keys, what happens? | Overlapping keys: later entries win. The when inline overrides the named reference's key. | -| Q59 | Can a named condition group reference another named group within the same conditions block? | No nesting — named groups cannot reference other named groups. Each group is a flat dict of condition expressions only. | -| Q60 | Can when contain multiple named references? | Yes, when can contain multiple named references and additional inline dicts. | -| Q61 | What happens if a state has an empty conditions block? | conditions is an optional keyword — useful when repeating conditions, but not required on every state. An empty block is valid but has no effect. | -| Q62 | What happens if a named condition group has an empty dict as its value? | Deferred to SA. | -| Q63 | Should the inlined result be visible to the user? | All conditions are flattened/combined. The user only sees the final list of conditions to verify. | -| Q64 | Should the validator check for unused named condition groups? | Deferred to SA. | -| Q65 | Pre-mortem: if a flow author writes when: reviewed (bare string), does it reference the named group? | when accepts three forms: bare dict (v1, unchanged), list (strings + inline dicts, AND-combined), and single string (shorthand for list with one named reference). when: reviewed is shorthand for when: [reviewed]. | - ---- - -## Quality Attributes - -| ID | Attribute | Scenario | Target | Priority | -|----|-----------|----------|--------|----------| -| QA6 | Backward Compatibility | When v1 flows with bare-dict when are loaded, they work unchanged | 100% backward compatible | Must | -| QA7 | Error Detection | When an unknown condition reference is used, a FlowParseError is raised | Zero unknown refs passing silently | Must | - ---- - -## Pain Points Identified - -- Repeating identical condition sets across multiple transitions is error-prone and hard to maintain - -## Business Goals Identified - -- Named condition groups allow flow authors to define reusable condition expressions at the state level - -## Terms to Define (for glossary) - -- Condition Inlining -- Condition Reference -- Named Condition Group - -## Action Items - -- [x] Record condition groups decisions -- [ ] SA to resolve deferred decisions (Q62, Q64) -- [ ] Write .feature file for named-condition-groups \ No newline at end of file diff --git a/docs/interview-notes/IN_20260426_configurable_paths.md b/docs/interview-notes/IN_20260426_configurable_paths.md deleted file mode 100644 index 3362565..0000000 --- a/docs/interview-notes/IN_20260426_configurable_paths.md +++ /dev/null @@ -1,49 +0,0 @@ -# IN_20260426_configurable_paths — Configurable paths session - -> **Status:** COMPLETE -> **Interviewer:** PO -> **Participant(s):** Stakeholder -> **Session type:** Scope refinement - ---- - -## Feature: configurable-paths - -| ID | Question | Answer | -|----|----------|--------| -| Q66 | What exactly should be configurable? Just flows dir and session dir, or more? | Just the flows dir for now. Keep it simple. | -| Q67 | Should flowr validate still accept a direct file path, or should it also support name-based lookup from the configured directory? | Direct file path only — no name-based lookup. The existing CLI interface stays unchanged. | -| Q68 | Should library functions (load_flow_from_file, resolve_subflows) use configured paths or stay explicit? | Library functions stay explicit — they take Path arguments. Configuration only affects the CLI layer. | -| Q69 | What should the exact defaults be for flows_dir? | SA decides — deferred. | -| Q70 | Should there be a flowr config CLI command? | Yes — flowr config prints current resolved configuration, showing each key, its value, and where it came from. | -| Q71 | Should configuration be overridable at the command line? | Yes — --flows-dir CLI flag overrides the pyproject.toml value for a single invocation. | -| Q72 | Should the session directory be configurable too? | SA decides — session directory is deferred. | -| Q73 | Pre-mortem: what happens with misconfigured paths? | SA decides — misconfigured path handling is deferred. | - ---- - -## Quality Attributes - -| ID | Attribute | Scenario | Target | Priority | -|----|-----------|----------|--------|----------| -| QA8 | Simplicity | When a developer configures flows_dir, it requires only one line in pyproject.toml | Single-line configuration | Must | - ---- - -## Pain Points Identified - -- Hardcoded paths limit flexibility for non-standard project layouts - -## Business Goals Identified - -- Allow project-specific configuration of flow directory location without changing library API - -## Terms to Define (for glossary) - -- Flows Directory -- Configuration - -## Action Items - -- [ ] SA to resolve deferred decisions (Q69, Q72, Q73) -- [ ] Write .feature file for configurable-paths \ No newline at end of file diff --git a/docs/interview-notes/IN_20260426_spec_design.md b/docs/interview-notes/IN_20260426_spec_design.md deleted file mode 100644 index f1dadc2..0000000 --- a/docs/interview-notes/IN_20260426_spec_design.md +++ /dev/null @@ -1,94 +0,0 @@ -# IN_20260426_spec_design — Flow specification design session - -> **Status:** COMPLETE -> **Interviewer:** PO -> **Participant(s):** Stakeholder -> **Session type:** Domain walkthrough - ---- - -## General - -| ID | Question | Answer | -|----|----------|--------| -| Q12 | Who are the users of the flow definition specification? (Re-asked: project scope has shifted from "Python project template" to "flow specification format") | Two user groups: developers/engineers who write and validate flow definitions, and tool authors who build tooling (validators, converters, editors) that consume the specification format. | -| Q13 | What does the product do at a high level? (Re-asked: the product is now a specification, not a template) | Three capabilities: define (YAML format for non-deterministic state machine workflows), validate (reference validator that checks conformance), and visualize (Mermaid converter that produces diagrams from flow definitions). | -| Q14 | Why does it exist — what problem does it solve? | No existing standard covers defining non-deterministic state machine workflows in YAML. Existing standards (XState, SCXML, etc.) don't address flowr's core features: per-state agent assignment, AI-agent-as-runtime, and filesystem-as-source-of-truth. | -| Q15 | When and where is it used? | Both humans and machines write and validate flows. Humans author flow YAML files; machines (validators, converters) parse and check them. | -| Q16 | Success — what does "done" look like for v1? | Three deliverables: prose specification document, reference validator (Python module), and Mermaid converter. No JSON Schema. | -| Q17 | Failure — what must never happen? | Ambiguity — the specification must not leave room for contradictory implementations. | -| Q18 | Out-of-scope for v1 — what are we explicitly not building? | No runtime engine and no session tracking in v1. | - -## Specification Semantics - -| ID | Question | Answer | -|----|----------|--------| -| Q19 | The spec says state-level attrs "override/extend" flow-level attrs. What are the merge semantics? | Replace entirely. State-level attrs completely replace flow-level attrs — no merge, no deep merge, no extension. | -| Q20 | The ~=value condition operator is defined as "approximate match". What's the exact matching rule? | **Revised at architecture:** The ~= operator applies ONLY to numeric values with 5% tolerance. String fuzzy matching was removed as too complicated. See ADR_20260426_fuzzy_match_algorithm. | -| Q21 | Does numeric extraction strip % from both condition value AND evidence value? | Yes. Numeric extraction strips from both condition AND evidence. | -| Q22 | What happens when a next target matches both a state id AND an exit name? | Validation error. A next target that matches both is ambiguous and must be rejected at load time. | -| Q23 | Are within-flow cycles allowed? | Within-flow cycles are allowed. Only cross-flow cycles (parent→child→parent) are forbidden. | -| Q24 | Can params have default values? | Params are declarations with optional default values. A param without a default value is required; missing required params are validation errors. | -| Q25 | Evidence values in conditions — are they typed? | **Resolved at architecture:** All evidence values are coerced to strings before comparison. YAML booleans become lowercase, YAML numbers become numeric strings. See ADR_20260426_evidence_type_system. | - -## Validation & Conformance - -| ID | Question | Answer | -|----|----------|--------| -| Q26 | Should v1 define conformance levels? | Yes. Two conformance levels: MUST (required for all conforming implementations) and SHOULD (recommended but not mandatory). | -| Q27 | Should v1 include a JSON Schema? | No JSON Schema. The prose specification plus the Python reference validator are sufficient. | -| Q28 | Should v1 include a reference validator implementation? | Yes — include a reference validator as a Python module. Part of the v1 deliverable. | -| Q29 | Should transition counts be tracked? | Remove transition counts from the v1 spec. They add complexity without clear value. | - -## Feature: flow-definition-spec - -| ID | Question | Answer | -|----|----------|--------| -| Q30 | What is the minimal v1 deliverable? | All deliverables: prose specification, Python reference validator, and Mermaid converter. JSON Schema removed per Q27. | -| Q31 | Should the existing flow YAML files serve as reference examples? | Yes. They are reference examples that v1 must validate correctly. | -| Q32 | Are immutable flows and filesystem truth behavioral requirements? | Immutable loaded flows is a MUST requirement. Filesystem truth is a SHOULD guideline. Session behavior is out of scope for v1. | -| Q33 | Should the specification use "flowr" branding? | Format-agnostic naming. The specification format has its own name independent of any implementation. | - ---- - -## Quality Attributes - -| ID | Attribute | Scenario | Target | Priority | -|----|-----------|----------|--------|----------| -| QA2 | Correctness | When a flow definition is validated, all MUST violations are reported | Zero false negatives on MUST rules | Must | -| QA3 | Unambiguity | When two conforming implementations interpret the same flow, they produce the same result | No contradictory interpretations | Must | -| QA4 | Extensibility | When a new condition operator is added, only the condition module changes | Single-module change | Should | - ---- - -## Pain Points Identified - -- No existing YAML standard covers non-deterministic state machine workflows with per-state agent assignment -- Existing standards (XState, SCXML) target execution engines, not specification/validation - -## Business Goals Identified - -- A declarative, validatable, toolable format for workflows that branch on evidence rather than control flow - -## Terms to Define (for glossary) - -- Flow Definition -- Flow Specification -- Guard Condition -- Evidence -- Exit -- Subflow -- Conformance -- Next Target Collision -- Cross-flow Cycle -- Within-flow Cycle -- Attrs -- Params -- Fuzzy Match -- Numeric Extraction - -## Action Items - -- [x] Record specification semantics decisions -- [ ] Write .feature file for flow-definition-spec -- [ ] Update glossary with new terms \ No newline at end of file diff --git a/docs/interview-notes/IN_20260501_cli-flow-name-resolution.md b/docs/interview-notes/IN_20260501_cli-flow-name-resolution.md deleted file mode 100644 index 2e16f73..0000000 --- a/docs/interview-notes/IN_20260501_cli-flow-name-resolution.md +++ /dev/null @@ -1,55 +0,0 @@ -# IN_20260501_cli-flow-name-resolution — CLI flow name resolution - -> **Status:** COMPLETE -> **Interviewer:** PO -> **Participant(s):** Stakeholder -> **Session type:** Feature specification - ---- - -## Feature: cli-flow-name-resolution - -| ID | Question | Answer | -|----|----------|--------| -| Q1 | What is the core problem with the current CLI flow argument? | The CLI `flow_file` argument only accepts literal file paths like `.flowr/flows/feature-development-flow.yaml`. Short flow names like `feature-development-flow` fail with "File not found" even though the YAML exists in the configured flows directory. | -| Q2 | Where does this mismatch cause friction? | Session YAML files store the flow name (not the full path). Documentation references flow names. Agents copy flow names from session YAML and pass them to CLI commands, which then fail. The session store and the CLI use different identifiers for the same flow. | -| Q3 | What is the proposed resolution mechanism? | Name resolution at the CLI layer: if the `flow_file` argument is not an existing file path, treat it as a flow name and resolve it by appending `.yaml` and looking in the configured `flows_dir`. Uses the existing `resolve_config()` infrastructure. | -| Q4 | Should library functions change? | No — library functions (`load_flow_from_file`, `resolve_subflows`) stay unchanged. They take `Path` arguments. Resolution is a CLI-layer concern only. | -| Q5 | What happens when a flow name doesn't match any file in `flows_dir`? | The CLI should report a clear, actionable error: the flow name was not found in the configured flows directory. No dead-end "File not found" that leaves the user guessing whether the name or the path was wrong. | -| Q6 | Should file paths still work? | Yes — absolute and relative file paths must continue to work exactly as before. If the argument resolves to an existing file, use it directly. Name resolution is a fallback, not a replacement. | -| Q7 | How does the `--flows-dir` flag interact with name resolution? | The `--flows-dir` global flag overrides the `pyproject.toml` `flows_dir` value for the current invocation. Name resolution uses whichever `flows_dir` is active (config or flag). | -| Q8 | Should the CLI try multiple extensions (`.yaml`, `.yml`)? | SA decision — deferred to system-architect for extension resolution strategy. | -| Q9 | Should name resolution be case-sensitive? | Yes — flow names are exact matches. Case-sensitive on all platforms. | -| Q10 | Pre-mortem: what happens if a flow name matches a file that also exists at a relative path? | File path takes priority. If the argument resolves to an existing file, use it. Name resolution only activates when the argument is not a valid file path. | - ---- - -## Quality Attributes - -| ID | Attribute | Scenario | Target | Priority | -|----|-----------|----------|--------|----------| -| QA1 | Usability | When a developer passes a short flow name to the CLI, the system resolves it to the correct file or reports a clear error identifying the flow name and the directory searched | Error message includes flow name and searched directory | Must | -| QA2 | Backward Compatibility | When a developer passes an existing file path (absolute or relative), the CLI behaves identically to the current version | Zero behavior change for existing file-path invocations | Must | - ---- - -## Pain Points Identified - -- CLI rejects short flow names that are valid identifiers in session YAML and documentation, forcing users to type or copy full paths -- Session store uses flow names but the CLI cannot accept them — the two subsystems use different identifiers for the same concept -- Agents that read flow names from session YAML and pass them to CLI commands get "File not found" errors with no guidance on how to fix the argument - -## Business Goals Identified - -- CLI and session store should use the same identifiers — a flow name that works in one context should work in the other -- Reduce friction for agents and humans by eliminating the need to construct file paths for flows that already have well-known names - -## Terms to Define (for glossary) - -- Flow Name Resolution — the CLI-layer process of converting a short flow name to a file path by looking in the configured flows directory -- flows_dir — the configurable directory containing flow definition YAML files (existing term, may need update to note CLI name resolution usage) - -## Action Items - -- [ ] SA to resolve deferred decision on extension resolution strategy (Q8) -- [ ] Write .feature file for cli-flow-name-resolution \ No newline at end of file diff --git a/docs/interview-notes/IN_20260501_session-management.md b/docs/interview-notes/IN_20260501_session-management.md deleted file mode 100644 index c00b643..0000000 --- a/docs/interview-notes/IN_20260501_session-management.md +++ /dev/null @@ -1,64 +0,0 @@ -# IN_20260501_session-management — Session management for CLI - -> **Status:** COMPLETE -> **Interviewer:** PO -> **Participant(s):** Stakeholder -> **Session type:** Feature specification - ---- - -## Feature: session-management - -| ID | Question | Answer | -|----|----------|--------| -| Q1 | What is the core problem with the current CLI? | Every CLI invocation is stateless — each command is independent with no memory of previous invocations. Agents must manually track which flow and state they are in, read session YAML files themselves, and construct the correct `flow_file` + `state` arguments for each command. | -| Q2 | How does the session YAML relate to this? | The session YAML already exists in `.flowr/sessions/` and stores the current flow name and state. But the CLI doesn't use it — agents have to read and update it manually, which is error-prone and creates friction. | -| Q3 | What subcommands should session management provide? | Three: `session init ` creates a new session at the flow's initial state; `session show` displays the current session's flow, state, and attrs; `session set-state ` updates the session's current state. | -| Q4 | How should existing commands become session-aware? | Add a `--session` flag to `next`, `transition`, and `check`. When present, these commands read the session file for the flow name and current state instead of requiring them as arguments. After a `transition`, the session file is auto-updated with the new state. | -| Q5 | Should `--session` require a session name or use a default? | `--session` takes an optional session name. If omitted, it uses the default session (the most recently created or explicitly selected session). SA decides the exact default resolution strategy. | -| Q6 | What output formats should session commands support? | `--format yaml|json` on `session show` and `session set-state`. Default is YAML for human readability, JSON for programmatic use. | -| Q7 | How should session state be persisted? | Write to the session YAML file in `.flowr/sessions/`. Use atomic writes (write to temp file, then rename) to prevent partial state corruption. | -| Q8 | What happens with subflows — does session track subflow state? | Yes — use a push/pop stack. When a transition enters a subflow state, push the parent flow+state onto the stack and track the subflow's current state. When the subflow exits, pop the stack and resume the parent at the exit target state. | -| Q9 | Should non-session CLI commands change? | No — commands without `--session` work exactly as before. Session awareness is opt-in via the flag. Backward compatibility is absolute. | -| Q10 | What if a session file is corrupted or manually edited incorrectly? | SA decision — deferred to system-architect for validation and error recovery strategy. | -| Q11 | Should `session init` accept params for the flow? | SA decision — deferred to system-architect for param passing mechanism. | -| Q12 | Should there be a `session list` command? | Yes — `session list` shows all sessions in the sessions directory with their flow, state, and last-updated timestamp. | -| Q13 | Pre-mortem: what happens if two processes write the same session file simultaneously? | SA decision — deferred to system-architect for concurrency strategy. Likely: last-write-wins with atomic writes is acceptable for single-user CLI usage. | - ---- - -## Quality Attributes - -| ID | Attribute | Scenario | Target | Priority | -|----|-----------|----------|--------|----------| -| QA1 | Reliability | When a session file is written, the write is atomic — no partial or corrupted state is possible even on crash or interrupt | Atomic write via temp-file-then-rename | Must | -| QA2 | Usability | When an agent or human runs a session-aware command, the CLI automatically reads and updates session state without manual file manipulation | Single `--session` flag enables session mode | Must | -| QA3 | Backward Compatibility | When a developer runs a CLI command without `--session`, the command behaves identically to the current version | Zero behavior change for non-session invocations | Must | -| QA4 | Usability | When a developer runs `session show`, the output clearly presents the current flow, state, and attrs in the requested format | YAML default with optional JSON via `--format` | Should | - ---- - -## Pain Points Identified - -- Every CLI invocation is stateless — agents must manually track which flow and state they are in across invocations -- The session YAML already stores workflow state but the CLI doesn't read or write it, forcing agents to do manual file I/O -- Copying flow names and state names from session YAML to CLI arguments is error-prone and creates friction in the workflow -- No push/pop mechanism for subflows means agents must manually track parent flow context when entering and exiting subflows - -## Business Goals Identified - -- Persistent workflow state across CLI invocations so agents and humans can resume where they left off without manual state tracking -- Eliminate the mismatch between session store identifiers and CLI arguments by making the CLI session-aware -- Enable subflow navigation with automatic push/pop so agents can enter and exit subflows without losing parent context - -## Terms to Define (for glossary) - -- Session — a persistent record of workflow state (flow name, current state, attrs) that survives across CLI invocations -- Session Store — the directory (`.flowr/sessions/`) containing session YAML files -- Session-Aware — a CLI command that reads and/or updates session state via the `--session` flag -- Subflow Push/Pop — the mechanism for tracking parent flow context when entering a subflow (push) and restoring it on exit (pop) - -## Action Items - -- [ ] SA to resolve deferred decisions (Q10, Q11, Q13) -- [ ] Write .feature file for session-management \ No newline at end of file diff --git a/docs/interview-notes/IN_20260502_config-paths-gap.md b/docs/interview-notes/IN_20260502_config-paths-gap.md deleted file mode 100644 index 1e072d2..0000000 --- a/docs/interview-notes/IN_20260502_config-paths-gap.md +++ /dev/null @@ -1,55 +0,0 @@ -# IN_20260502_config-paths-gap — Config introspection subcommand gap analysis - -> **Status:** COMPLETE -> **Interviewer:** PO -> **Participant(s):** Stakeholder -> **Session type:** Feature specification - ---- - -## Feature: configurable-paths (gap — Config introspection rule) - -The configurable-paths feature has 6 @id examples. Three (971ec591, 5e0dd562, 076da303) are already implemented by the cli-flow-name-resolution feature. The remaining three (2e301322, 36d41122, 9d4c4973) require a `flowr config` subcommand that does not yet exist. - -| ID | Question | Answer | -|----|----------|--------| -| Q74 | What should `flowr config` display? | Each resolved configuration key, its value, and the source of that value (default, pyproject.toml, or cli). | -| Q75 | Should `flowr config` show all config keys or only flows_dir? | All resolved keys in v1: flows_dir, sessions_dir, default_flow, default_session. | -| Q76 | What output format should `flowr config` use? | Human-readable table by default. The existing `--json` flag should produce JSON output (consistent with other commands). | -| Q77 | Should `flowr config` also show the project root? | Yes — show `project_root` with its resolved path and source (cwd or cli). This helps users debug path resolution. | -| Q78 | What happens when `--flows-dir` is passed to `flowr config`? | The overridden value is shown with source "cli" instead of "pyproject.toml" or "default". This is already covered by @id:9d4c4973. | -| Q79 | Should `flowr config` validate that configured directories exist? | No — it shows the resolved configuration, not whether the paths are valid. Path validation is a separate concern (handled by the commands that use those paths). | -| Q80 | What if pyproject.toml doesn't exist? | `flowr config` shows all keys with source "default" and their default values. This is covered by @id:36d41122. | -| Q81 | Pre-mortem: what if a key in [tool.flowr] has an invalid type? | ConfigError is raised with a clear message. The config command itself doesn't validate types beyond what `resolve_config()` already does. | - ---- - -## Quality Attributes - -| ID | Attribute | Scenario | Target | Priority | -|----|-----------|----------|--------|----------| -| QA9 | Consistency | When a user runs `flowr config`, the output format is consistent with `flowr check --json` | Same JSON structure pattern | Must | -| QA10 | Completeness | When all config keys are shown, no key is missing that affects CLI behavior | All 5 keys shown | Must | - ---- - -## Pain Points Identified - -- No way to verify which configuration values are in effect without running a command and observing behavior -- When `--flows-dir` overrides the config, there's no way to confirm the override took effect - -## Business Goals Identified - -- Provide visibility into resolved configuration for debugging and verification -- Complete the configurable-paths feature by implementing the only remaining rule (Config introspection) - -## Terms to Define - -- Config introspection — already defined in glossary as part of configurable-paths -- Config source — the origin of a configuration value: "default", "pyproject.toml", or "cli" - -## Action Items - -- [ ] Update configurable-paths.feature to mark covered examples -- [ ] Create BDD scenarios for the 3 remaining @id examples -- [ ] Create test stubs and implement `flowr config` subcommand \ No newline at end of file diff --git a/docs/interview-notes/IN_20260505_subflow-transition-overhaul.md b/docs/interview-notes/IN_20260505_subflow-transition-overhaul.md deleted file mode 100644 index e032842..0000000 --- a/docs/interview-notes/IN_20260505_subflow-transition-overhaul.md +++ /dev/null @@ -1,77 +0,0 @@ -# IN_20260505_subflow-transition-overhaul — Subflow mechanism and agent UX overhaul - -> **Status:** COMPLETE -> **Interviewer:** PO -> **Participant(s):** Stakeholder -> **Session type:** Feature specification - ---- - -## Feature: subflow-transition-overhaul - -| ID | Question | Answer | -|----|----------|--------| -| Q1 | What is the core problem discovered? | A full dry run of the main-flow revealed two critical bugs that make the entire subflow mechanism non-functional for real flows, plus multiple agent UX gaps that would prevent effective navigation even after the bugs are fixed. | -| Q2 | What is the first critical bug? | `resolve_subflows()` in `loader.py:39` constructs paths as `root_path.parent / state.flow`, but real flow references omit the `.yaml` extension (e.g., `flow: discovery-flow`). The resulting path `.flowr/flows/discovery-flow` doesn't exist, so subflows are never resolved. Tests pass because fixtures use explicit `.yaml` extensions. | -| Q3 | What is the second critical bug? | When a subflow exits, `pop_stack(target)` at `__main__.py:596` uses the exit name directly as the new state (e.g., `"complete"`), but it should resolve through the parent flow's transition map. In `main-flow`, `discovery` state maps `complete → architecture`, but the session ends up at the invalid state `main-flow/complete`. The agent is dead-ended. | -| Q4 | Does `session init` handle initial subflows? | No. When the first state has a `flow:` field (like `main-flow/discovery` which has `flow: discovery-flow`), `session init` sets the state but never pushes the subflow stack. The agent sits at the wrapper state without entering the subflow. | -| Q5 | What is the `next` command's output problem? | `next` shows only TARGET state names (e.g., `next: event-storming`), but agents need TRIGGER names to transition (e.g., `needs_full_discovery`). There is no combined view showing the trigger→target mapping. The agent must run both `check` (for trigger names) and `next` (for target states) and mentally map them. | -| Q6 | What about guarded transitions? | `next` filters out transitions whose conditions aren't met by the provided evidence. An agent that hasn't provided evidence sees fewer transitions — potentially zero — with no indication that guarded transitions exist or what evidence they need. This is especially dangerous at exit transitions like `scope-boundary`'s `done → complete` which requires `committed_to_main_locally=verified`. | -| Q7 | Does `check --session ` work? | No. The argparse captures the target argument as the `flow_file` positional (because `flow_file` is the first optional positional). So `check --session project approved` sets `flow_file="approved"` and `target=None`, showing state details instead of transition conditions. | -| Q8 | Can `set-state` cross flow boundaries for recovery? | No. `set-state` validates the target state exists in the current flow only. Subflow states aren't in the parent flow's state list, so you can't teleport into a subflow. And the stack isn't managed either. | -| Q9 | What about `--session` on other commands? | `--session` only exists on `check`, `next`, and `transition`. You can't run `states --session` to list states in your current (sub)flow, or `validate --session` to validate it. | -| Q10 | What design decisions were made? | (1) `next` should ALWAYS show all transitions including guarded/blocked ones, with status markers — agents need the full picture. (2) JSON output for `next` should be a clean break: replace `"next": [strings]` with `"transitions": [{trigger, target, status, conditions}]`. No backward compatibility needed. | -| Q11 | What is the proposed subflow exit fix? | When a subflow exit is detected: (1) load the parent flow from the stack frame, (2) look up the exit trigger in the parent state's `next` map, (3) use the resolved target as the new state, (4) check if the resolved target enters ANOTHER subflow (handle chaining). This requires passing `flows_dir` to `_apply_session_transition`. | -| Q12 | Should the `next` text output format change? | Yes. From `next: event-storming` to ` needs_full_discovery → event-storming` with inline condition hints: ` done → complete (needs: committed_to_main_locally=verified)` or ` done → complete (blocked: committed_to_main_locally=verified)`. | - ---- - -## Quality Attributes - -| ID | Attribute | Scenario | Target | Priority | -|----|-----------|----------|--------|----------| -| QA1 | Reliability | When a session transitions through a subflow exit, the parent transition is correctly resolved and the session lands on a valid state in the parent flow | Subflow exit always resolves through parent transition map | Must | -| QA2 | Reliability | When a flow references a subflow by name without `.yaml`, the subflow is resolved correctly | Try path as-is, then with `.yaml` appended | Must | -| QA3 | Usability | When an agent runs `next`, all available transitions are visible including guarded ones that need evidence | Always show all transitions with status markers | Must | -| QA4 | Usability | When an agent runs `next`, trigger names are visible alongside target states | Show `trigger → target` format | Must | -| QA5 | Discoverability | When an agent runs `next`, evidence keys required by guarded transitions are visible inline | Show condition key=value requirements in output | Must | -| QA6 | Backward Compatibility | Non-session commands continue to work identically | Zero behavior change for non-session invocations | Must | - ---- - -## Pain Points Identified - -- Subflow mechanism is completely non-functional for real flows — two critical bugs prevent any subflow from being entered or exited correctly -- `next` command hides critical information: trigger names, guarded transitions, and evidence requirements are all invisible -- Session can enter an invalid state (non-existent state ID) from which recovery requires manual YAML editing -- `session init` leaves the agent stranded at a wrapper state instead of entering the initial subflow -- No single command gives the agent a complete picture of where they are and what they can do -- `check --session ` silently ignores the target argument due to argparse capture -- Evidence keys are completely undiscoverable — the agent must read raw YAML to know what to provide -- Tests have a false-positive gap: fixtures use `.yaml` extensions in flow references, hiding the resolve_subflows bug - -## Business Goals Identified - -- Make the subflow mechanism actually work for real multi-level flow hierarchies -- Enable agents to navigate flows autonomously by making all navigation information visible from CLI commands -- Prevent sessions from entering invalid/broken states -- Support subflow→subflow chaining (e.g., main-flow → discovery-flow → exit → architecture-flow) - -## Terms to Define (for glossary) - -- Subflow entry — the push-stack operation when transitioning to a state with a `flow:` field -- Subflow exit — the pop-stack operation when a transition targets a name in the flow's `exits` list -- Exit resolution — resolving the exit name through the parent flow's transition map to get the actual target state -- Subflow chaining — entering a new subflow immediately after exiting one (e.g., discovery-flow exits → main-flow transitions → architecture-flow enters) -- Blocked transition — a guarded transition whose conditions are not met by the provided evidence - -## Action Items - -- [ ] Fix `resolve_subflows()` to handle missing `.yaml` extension -- [ ] Fix subflow exit to resolve parent transition target with chaining support -- [ ] Fix `session init` to auto-enter initial subflow -- [ ] Enhance `next` output to show trigger→target mapping with conditions -- [ ] Fix `check --session ` argparse dispatch -- [ ] Add `--session` to `states` and `validate` -- [ ] Add tests without `.yaml` extension in flow references -- [ ] Add tests for subflow exit resolution and chaining diff --git a/docs/interview-notes/IN_20260506_export-feature.md b/docs/interview-notes/IN_20260506_export-feature.md deleted file mode 100644 index ba5b5b7..0000000 --- a/docs/interview-notes/IN_20260506_export-feature.md +++ /dev/null @@ -1,84 +0,0 @@ -# IN_20260506_export-feature — Pluggable export adapters for flowr - -> **Status:** COMPLETE -> **Interviewer:** PO -> **Participant(s):** Stakeholder -> **Session type:** Feature specification - ---- - -## Pain Points - -1. **No export command.** flowr can validate, query, and generate Mermaid diagrams, but has no structured output format for external tooling (visualizers, analyzers, CI integrations). Tools must parse raw YAML and duplicate flowr's resolution logic. -2. **Mermaid is a standalone command.** `flowr mermaid` is a one-off subcommand, not part of a cohesive export system. Adding new formats means adding new subcommands with no shared pattern. -3. **No directory-level export.** Cannot export all flows from `.flowr/flows/` with cross-references resolved. Each flow must be exported individually. -4. **Issue #3 open.** The community has requested `flowr export --json` with a detailed proposal including JSON schema and use cases. - -## Business Goals - -1. Replace `flowr mermaid` with a unified `flowr export --format ` command backed by a pluggable adapter architecture. -2. Ship two built-in adapters: JSON (structured nodes/edges) and Mermaid (stateDiagram-v2). -3. Each adapter defines its own options (per-adapter CLI flags via `add_arguments()`). -4. Auto-detect file vs directory input — single flow export or multi-flow collection export. -5. Hardcoded registry for built-in formats (no entry points complexity). Third-party extensibility can be added later. - -## Terms to Define - -| Term | Definition | -|------|------------| -| **FlowExporter** | Protocol defining the adapter contract: `export()`, `export_directory()`, `format_name()`, `description()`, `supports_directory()`, `add_arguments()` | -| **ExportOptions** | Per-adapter options parsed from adapter-specific CLI flags (e.g. `--flat` for JSON, `--no-conditions` for Mermaid) | -| **Registry** | Hardcoded `EXPORTERS` dict mapping format name strings to FlowExporter instances | -| **Adapter** | A concrete implementation of the FlowExporter Protocol for a specific output format | -| **Directory mode** | Loading all YAML files from a directory, resolving subflow cross-references, and exporting as a collection | -| **Flat mode** | Flattening subflows into the parent flow's output rather than keeping them as separate entries | - -## Quality Attributes - -| ID | Attribute | Scenario | Target | Priority | -|----|-----------|----------|--------|----------| -| QA1 | Extensibility | A developer wants to add a new export format | Implement FlowExporter Protocol, register in EXPORTERS dict, CLI auto-discovers it | Must | -| QA2 | Adapter autonomy | JSON adapter needs `--flat` flag, Mermaid doesn't | Each adapter adds its own arguments via `add_arguments()` | Must | -| QA3 | Auto-detection | User passes a directory instead of a file | All YAML files loaded, subflows resolved, exported as collection | Must | -| QA4 | Backward compatibility | Existing `flowr mermaid` users | `flowr mermaid` removed entirely; `flowr export --format mermaid` replaces it | Must | -| QA5 | Correctness | JSON export must resolve named condition groups | Named refs expanded into flat condition dicts; consumers don't need to understand resolution logic | Must | -| QA6 | Zero new dependencies | Built-in adapters ship with core | No new pip dependencies for JSON or Mermaid export | Must | -| QA7 | Test coverage | 100% coverage maintained | All new code covered, `mermaid` subcommand removal tested | Must | - ---- - -## Adapter Specification - -### JsonExporter - -- **Subflow handling:** Nested by default — subflows appear as separate flow entries in the collection. `--flat` option inlines subflow states into the parent. -- **Directory mode:** Yes. Exports all flows as a collection with `defaultFlow` key. -- **Own flags:** `--flat`, `--no-attrs` -- **Output schema:** Follows the schema proposed in issue #3 (nodes with type state/subflow/exit, edges with kind transition/exit, resolved conditions, opaque attrs). - -### MermaidExporter - -- **Subflow handling:** Always flat — one stateDiagram-v2 per flow. Subflow references appear as notes. -- **Directory mode:** Yes. One diagram per flow, separated by `---`. -- **Own flags:** `--no-conditions` -- **Output:** Delegates to existing `to_mermaid()` in `flowr/domain/mermaid.py`. - ---- - -## Scope Confirmation - -| Artifact | Action | -|----------|--------| -| `flowr/domain/export.py` | New — FlowExporter Protocol | -| `flowr/exporters/__init__.py` | New — hardcoded EXPORTERS registry + `get_exporter()` | -| `flowr/exporters/json_exporter.py` | New — JsonExporter | -| `flowr/exporters/mermaid_exporter.py` | New — MermaidExporter (wraps `to_mermaid()`) | -| `flowr/__main__.py` | Add `export` subcommand, remove `mermaid` subcommand | -| `flowr/domain/mermaid.py` | Keep as-is (MermaidExporter delegates to it) | -| `tests/` | New tests per adapter, CLI integration tests, mermaid removal test | - -## Action Items - -- [ ] Transition stakeholder-interview with appropriate trigger -- [ ] Continue through discovery flow (event-storming, language, domain model, scope) -- [ ] Continue through architecture, planning, and development flows diff --git a/docs/interview-notes/IN_20260506_remove-fuzzy-match.md b/docs/interview-notes/IN_20260506_remove-fuzzy-match.md deleted file mode 100644 index 60ba189..0000000 --- a/docs/interview-notes/IN_20260506_remove-fuzzy-match.md +++ /dev/null @@ -1,52 +0,0 @@ -# IN_20260506_remove-fuzzy-match — Remove ~= operator from specification - -> **Status:** COMPLETE -> **Interviewer:** PO -> **Participant(s):** Stakeholder -> **Session type:** Feature specification - ---- - -## Feature: remove-fuzzy-match-operator - -| ID | Question | Answer | -|----|----------|--------| -| Q1 | What is changing? | Complete removal of the `~=` (APPROXIMATELY_EQUAL) operator from the flowr specification and reference implementation. The 5% tolerance numeric matching operator will no longer be a valid condition operator. | -| Q2 | Why remove it? | Unused in practice. Adds complexity to the specification and codebase without providing value. The concept is over-engineered for what flowr needs. | -| Q3 | What defines success? | `~=` removed from: `ConditionOperator` enum, `_OPERATOR_PREFIXES` list, `_compare_numeric` function, all tests, spec docs (`flow_definition_spec.md`), glossary (`glossary.md`), system.md, product_definition.md. Existing ADR gets a deprecation note. Flows using `~=` produce a clear `FlowParseError` following current error conventions. | -| Q4 | How should flows using ~= fail? | Clearest approach using current conventions. The `FlowParseError` pattern (e.g. `f"Unknown condition reference '{name}'..."`) should be followed. After removal, `~=` will simply not be recognized as a valid operator prefix, so `parse_condition` will treat it as a bare value (implicit `==`). A validation-level check may be needed to catch it explicitly. | -| Q5 | What must never happen? | Silent acceptance of `~=` as a valid operator after removal. | -| Q6 | What about the ADR? | Add a deprecation note to `ADR_20260426_fuzzy_match_algorithm.md`. Do not supersede with a new ADR. | -| Q7 | What's out of scope? | `docs/index.html` is out of scope (already omits `~=`). No changes to the spec page. | - ---- - -## Scope Confirmation - -| Artifact | Action | -|----------|--------| -| `flowr/domain/condition.py` | Remove `APPROXIMATELY_EQUAL` enum, `"~="` from `_OPERATOR_PREFIXES`, `_compare_numeric` case | -| `tests/unit/condition_test.py` | Remove `~=` parse test (line 64) | -| `tests/features/.../condition_operators_test.py` | Remove/update `~=` feature tests (lines 68-122, including 2 skipped tests) | -| `docs/spec/flow_definition_spec.md` | Remove `~=` from operator table (line 250), examples (lines 85, 91), note (line 256), v1 scope (line 378) | -| `docs/spec/glossary.md` | Remove fuzzy-match term (lines 90-96), remove `~=` from guarded-transition definition (line 102) | -| `docs/spec/system.md` | Remove `~=` references (lines 137, 159, 195) | -| `docs/spec/product_definition.md` | Remove `~=` from expression list (line 18) | -| `docs/adr/ADR_20260426_fuzzy_match_algorithm.md` | Add deprecation note at top | -| `docs/index.html` | **Out of scope** (already omits `~=`) | -| `.flowr/flows/*.yaml` | No changes needed (no flows use `~=`) | - ---- - -## Quality Attributes - -| ID | Attribute | Scenario | Target | Priority | -|----|-----------|----------|--------|----------| -| QA1 | Correctness | When a flow file contains `when: { value: "~=100" }`, the validator rejects it | Clear error message following FlowParseError convention | Must | - ---- - -## Action Items - -- [ ] Write feature file with BDD scenarios covering code removal and doc updates -- [ ] Implement removal via TDD cycle diff --git a/docs/interview-notes/IN_20260507_export-robustness.md b/docs/interview-notes/IN_20260507_export-robustness.md deleted file mode 100644 index be77a75..0000000 --- a/docs/interview-notes/IN_20260507_export-robustness.md +++ /dev/null @@ -1,38 +0,0 @@ -# IN_20260507_export-robustness: Post-PR robustness fixes for export and CLI error handling - -## Pain Points - -1. **Cross-adapter flag confusion** — `flowr export --format mermaid --flat` silently ignores `--flat`. Users may believe the flag had an effect. All adapter flags visible in help regardless of selected format. -2. **Empty directory silent success** — `flowr export --format json /tmp/empty` returns `[]` with exit code 0. No indication that no flows were found. Masks user mistakes (wrong directory). -3. **YAML parse traceback leak** — Malformed YAML crashes the CLI with a full Python traceback across all commands (validate, export, states, check, next, transition). Pre-existing defect predating the export feature. - -## Business Goals - -1. Improve CLI reliability — users should never see raw Python tracebacks -2. Clear feedback — every CLI invocation should produce unambiguous output about what happened -3. Consistent error handling — all commands handle malformed input gracefully - -## Terms to Define - -No new domain terms needed — these are edge-case fixes within existing concepts (Export Adapter, Export Registry, Format Resolution). - -## Quality Attributes - -| ID | Attribute | Scenario | Target | Priority | -|----|-----------|----------|--------|----------| -| QA1 | Usability | When a user passes a flag irrelevant to the selected export format, the CLI warns them | Warning on stderr listing unused flag(s) | Should | -| QA2 | Correctness | When a user exports from an empty directory, the CLI reports failure | Error message on stderr, exit code 1 | Must | -| QA3 | Reliability | When a user passes a malformed YAML file to any CLI command, the CLI produces a user-friendly error | Single-line error on stderr, no traceback, exit code 1 | Must | - -## Scope Confirmation - -- **Cross-adapter flags:** Warn on unused flags (stderr warning listing irrelevant flag names) -- **Empty directory:** Error message + exit code 1 -- **YAML traceback:** Fix across all commands (add `yaml.YAMLError` catch in `main()`) -- **Not in scope:** Changing flag registration, two-pass argparse, new domain types - -## Resolved Decisions - -- Format: warn on unused adapter flags (stakeholder chose over document-and-accept) -- Empty dir: exit code 1 (error, not warning) -- YAML: fix all commands, not just export diff --git a/docs/spec/event_storming.md b/docs/spec/event_storming.md deleted file mode 100644 index cf9e555..0000000 --- a/docs/spec/event_storming.md +++ /dev/null @@ -1,264 +0,0 @@ -# Event Storming: flowr - -Facilitated from interview IN_20260506_export-feature. Surfaces domain events, commands, bounded contexts, and aggregate candidates for the export feature. - ---- - -## Event Map - -Domain events in chronological order. Each event is a fact — something that happened, expressed in past tense. - -### Timeline - -```mermaid -flowchart LR - ExportRequested --> FormatResolved --> AdapterArgumentsParsed - AdapterArgumentsParsed --> InputClassified - InputClassified --> FlowsLoaded - InputClassified --> FlowLoaded - FlowsLoaded --> DirectoryExported - FlowLoaded --> FlowExported -``` - -### Domain Events - -| # | Event | Description | Produced by | -|---|-------|-------------|-------------| -| E1 | **ExportRequested** | User invoked `flowr export --format ` | `RequestExport` command | -| E2 | **FormatResolved** | Format name string mapped to a FlowExporter adapter instance via the EXPORTERS registry | `ResolveFormat` command | -| E3 | **AdapterArgumentsParsed** | Per-adapter CLI flags extracted from the argument namespace into adapter-specific options | `ParseAdapterArguments` command | -| E4 | **InputClassified** | Input path determined to be a single file or a directory of flow definitions | `ClassifyInput` command | -| E5 | **FlowLoaded** | A single YAML file parsed into a Flow domain object | `LoadFlow` command (existing, from `flowr.domain.loader`) | -| E6 | **SubflowsResolved** | Subflow references in a root flow resolved into a list of Flow objects with cross-references expanded | `ResolveSubflows` command (existing, from `flowr.domain.loader`) | -| E7 | **FlowExported** | A single Flow transformed into the target format by the resolved adapter | `ExportFlow` command (adapter method) | -| E8 | **DirectoryExported** | All flows from a directory exported as a collection, optionally with a `defaultFlow` key | `ExportDirectory` command (adapter method) | - -### Commands - -Each command is an intent — imperative verb — that triggers a domain event. Commands may fail (unknown format, missing file, parse error). - -| # | Command | Triggers event | Failure mode | -|---|---------|---------------|--------------| -| C1 | **RequestExport** | ExportRequested | — (entry point) | -| C2 | **ResolveFormat** | FormatResolved | Unknown format name → error | -| C3 | **ParseAdapterArguments** | AdapterArgumentsParsed | Invalid flag values → error | -| C4 | **ClassifyInput** | InputClassified | Path does not exist → error | -| C5 | **LoadFlow** | FlowLoaded | Invalid YAML → `FlowParseError` | -| C6 | **ResolveSubflows** | SubflowsResolved | Missing subflow file → partial (already handled gracefully by existing code) | -| C7 | **ExportFlow** | FlowExported | — (adapter is responsible) | -| C8 | **ExportDirectory** | DirectoryExported | Empty directory → empty collection | - -### Event–Command Pairs - -| Command | → Event | Aggregate | -|---------|---------|-----------| -| `RequestExport(format, path)` | `ExportRequested` | ExportSession | -| `ResolveFormat(format_name)` | `FormatResolved` | ExportRegistry | -| `ParseAdapterArguments(args, exporter)` | `AdapterArgumentsParsed` | ExportSession | -| `ClassifyInput(path)` | `InputClassified` | ExportSession | -| `LoadFlow(path)` | `FlowLoaded` | (existing — Flow aggregate) | -| `ResolveSubflows(root_flow, root_path)` | `SubflowsResolved` | (existing — Flow aggregate) | -| `ExportFlow(exporter, flow, options)` | `FlowExported` | FlowExporter (adapter) | -| `ExportDirectory(exporter, flows, options)` | `DirectoryExported` | FlowExporter (adapter) | - ---- - -## Context Candidates - -Three bounded contexts emerge from the event grouping. Context boundaries are drawn where responsibilities and language diverge. - -### C1: Export Coordination - -**Events:** ExportRequested, FormatResolved, AdapterArgumentsParsed, InputClassified -**Commands:** RequestExport, ResolveFormat, ParseAdapterArguments, ClassifyInput - -Orchestrates the export workflow end-to-end. Owns the CLI `export` subcommand, its argument parser, and the dispatch logic that wires format resolution → input classification → adapter invocation. This context does not understand any output format — it delegates format-specific work to the Format Adaptation context. - -**Language:** format name, input path, export command, adapter options. - -**Owning module:** `flowr.cli` (export subcommand handler in `__main__.py`). - -### C2: Format Adaptation - -**Events:** FlowExported, DirectoryExported -**Commands:** ExportFlow, ExportDirectory - -Transforms loaded Flow domain objects into specific output representations. Each adapter implements the FlowExporter Protocol and owns its serialization logic, CLI argument definitions, and output schema. Adapters are autonomous: the JSON adapter defines `--flat` and `--no-attrs`; the Mermaid adapter defines `--no-conditions`. No adapter knows about other adapters. - -**Language:** nodes, edges, conditions, flat mode, stateDiagram-v2, diagram separator. - -**Owning module:** `flowr.exporters` (new package: `__init__.py`, `json_exporter.py`, `mermaid_exporter.py`). The Protocol lives in `flowr.domain.export.py`. - -### C3: Flow Resolution - -**Events:** FlowLoaded, SubflowsResolved -**Commands:** LoadFlow, ResolveSubflows - -Loads YAML files into Flow domain objects and resolves subflow cross-references. This context already exists in `flowr.domain.loader`. The export feature **consumes** this context but does not own or modify it. The export feature depends on the Flow, State, Transition, and GuardCondition domain types from `flowr.domain.flow_definition`. - -**Language:** flow, state, transition, trigger, guard condition, subflow, exit. - -**Owning module:** `flowr.domain.loader`, `flowr.domain.flow_definition` (existing, unchanged). - -### Context Map - -```mermaid -flowchart TB - EC[Export Coordination
Owns: CLI dispatch, input detect, format lookup] - FA[Format Adaptation
Owns: serialization, per-format CLI, output schema] - FR[Flow Resolution
Owns: YAML → Flow, subflow refs] - EC -- delegates --> FA - EC -- consumes --> FR - FA -- consumes --> FR -``` - -**Relationships:** - -- Export Coordination → Format Adaptation: **delegation** (coordination invokes adapter methods via Protocol) -- Export Coordination → Flow Resolution: **conformist** (consumes Flow/State/Transition types as-is) -- Format Adaptation → Flow Resolution: **conformist** (receives loaded Flow objects, does not load itself) - ---- - -## Aggregate Candidates - -### A1: ExportSession - -**Context:** Export Coordination -**Consistency boundary:** A single `flowr export` invocation. - -Represents one export call from start to finish. Holds the resolved format name, input path (file or directory), loaded flows, and adapter-specific options. Enforces the invariant that a format must be resolved and valid before any export begins. - -**Identity:** The CLI invocation itself (ephemeral — not persisted). - -**State:** -- `format_name: str` — requested format (e.g., `"json"`, `"mermaid"`) -- `input_path: Path` — file or directory -- `is_directory: bool` — classified input type -- `flows: list[Flow]` — loaded domain objects -- `adapter_options: dict[str, Any]` — per-adapter parsed flags - -**Invariants:** -- Format must be resolved (present in EXPORTERS) before export -- Input path must exist on disk -- At least one flow must be loaded for export to proceed - -**Root entity:** The export command handler function (ephemeral session, no persistent identity). - -### A2: ExportRegistry - -**Context:** Export Coordination -**Consistency boundary:** The hardcoded format → adapter mapping. - -A singleton that maps format name strings to FlowExporter instances. Enforces the invariant that only registered formats are accessible. The registry is hardcoded at module load time — no runtime registration. - -**Identity:** The module-level `EXPORTERS` dict (singleton). - -**State:** -- `EXPORTERS: dict[str, FlowExporter]` — format name → adapter instance - -**Invariants:** -- Every value implements the FlowExporter Protocol -- Keys are lowercase format names (e.g., `"json"`, `"mermaid"`) -- Lookup of unknown format raises an error - -**Root entity:** The `EXPORTERS` dict in `flowr/exporters/__init__.py`. - -### A3: FlowExporter (Protocol) - -**Context:** Format Adaptation -**Consistency boundary:** A single adapter's serialization logic. - -Each concrete adapter (JsonExporter, MermaidExporter) is an aggregate root responsible for producing correct output from input Flows. The Protocol defines the contract; each implementation enforces its own invariants (e.g., JSON must produce valid JSON, Mermaid must produce valid stateDiagram-v2). - -**Identity:** The adapter instance (stateless — no mutable identity). - -**Contract methods:** -- `format_name() -> str` — returns the format identifier -- `description() -> str` — human-readable description for help text -- `supports_directory() -> bool` — whether the adapter handles directory export -- `add_arguments(parser)` — registers adapter-specific CLI flags -- `export(flow, options) -> str` — exports a single flow -- `export_directory(flows, options) -> str` — exports a flow collection - -**Concrete implementations:** -- **JsonExporter** — structured nodes/edges with resolved conditions; supports `--flat` (inline subflows) and `--no-attrs` (omit state attrs) -- **MermaidExporter** — stateDiagram-v2 per flow; supports `--no-conditions` (omit transition conditions); delegates to existing `to_mermaid()` in `flowr.domain.mermaid` - ---- - -## Gaps and Follow-ups - -| Gap | Description | Resolution | -|-----|-------------|------------| -| G1 | MermaidExporter wraps existing `to_mermaid()` but `to_mermaid()` does not accept options | MermaidExporter calls `to_mermaid(flow)` and post-processes (strips conditions) if `--no-conditions` is set, or `to_mermaid` gains an options parameter | -| G2 | JSON output schema not yet formally specified | Reference issue #3 proposal; schema validation deferred to architecture phase | -| G3 | Directory export ordering is undefined | Flows loaded from directory glob — sorted alphabetically by filename for deterministic output | -| G4 | `flowr mermaid` removal is a breaking change | Accepted per interview QA4; `flowr export --format mermaid` is the replacement path | -| G5 | No streaming or incremental output for large directories | Out of scope for this feature; all flows loaded into memory before export | - ---- - -## Robustness Events (2026-05-07) - -Addendum from post-mortems PM_20260507_cross-adapter-flags, PM_20260507_empty-directory-silent, and PM_20260507_yaml-traceback-leak. Three edge-case failure events surfaced during production use. No new bounded contexts or aggregates — these extend existing BC1 (Export Coordination) and the CLI entry point. - -### New Domain Events - -| # | Event | Description | Produced by | -|---|-------|-------------|-------------| -| E9 | **UnusedAdapterFlagsWarningIssued** | One or more adapter-specific flags were provided but are irrelevant to the resolved export format; warning emitted on stderr | `ValidateAdapterFlags` command | -| E10 | **EmptyDirectoryRejected** | Directory export target contains no flow definition files; export aborted with error message and exit code 1 | `ClassifyInput` command (extended) | -| E11 | **MalformedYamlRejected** | A YAML file failed to parse due to structural errors; user-friendly error emitted on stderr, no traceback leaked | `LoadFlow` command (extended failure mode) | - -### New Commands - -| # | Command | Triggers event | Failure mode | -|---|---------|---------------|--------------| -| C9 | **ValidateAdapterFlags** | UnusedAdapterFlagsWarningIssued | — (warning only, does not block export) | - -### Extended Commands - -| Command | Change | Rationale | -|---------|--------|-----------| -| C8 **ExportDirectory** | Failure mode updated: "Empty directory → empty collection" becomes "Empty directory → error (exit 1)" | PM_20260507_empty-directory-silent: silent `[]` masked user mistakes | -| C5 **LoadFlow** | Failure mode extended: `yaml.YAMLError` caught at CLI layer in addition to existing `FlowParseError` | PM_20260507_yaml-traceback-leak: raw traceback leaked to end users | - -### Event–Command Pair - -| Command | → Event | Aggregate | -|---------|---------|-----------| -| `ValidateAdapterFlags(adapter_flags, resolved_format)` | `UnusedAdapterFlagsWarningIssued` | ExportSession | - -### Updated Timeline - -```mermaid -flowchart LR - ExportRequested --> FormatResolved --> AdapterArgumentsParsed - AdapterArgumentsParsed --> InputClassified - AdapterArgumentsParsed -.-> UnusedAdapterFlagsWarningIssued - InputClassified --> FlowsLoaded - InputClassified --> FlowLoaded - FlowsLoaded --> DirectoryExported - FlowsLoaded -.-> EmptyDirectoryRejected - FlowLoaded --> FlowExported - FlowLoaded -.-> MalformedYamlRejected -``` - -Dotted lines indicate failure/warning paths (non-happy-path). - -### Placement in Existing Contexts - -| Event | Context | Notes | -|-------|---------|-------| -| UnusedAdapterFlagsWarningIssued | C1: Export Coordination | Fires between AdapterArgumentsParsed and InputClassified | -| EmptyDirectoryRejected | C1: Export Coordination | Replaces the silent-empty behavior of C8 ExportDirectory | -| MalformedYamlRejected | C3: Flow Resolution (caught at CLI) | `yaml.YAMLError` catch lives in `main()` — the CLI boundary — but the event originates from the Flow Resolution context | - -### No New Aggregates - -All three events operate within existing aggregate boundaries: - -- **ExportSession** (A1): gains the `ValidateAdapterFlags` step and the empty-directory guard. -- **ExportRegistry** (A2): unchanged. -- **FlowExporter** (A3): unchanged — adapters are not responsible for input validation. diff --git a/domain_spec.md b/domain_spec.md deleted file mode 100644 index 76ee30a..0000000 --- a/domain_spec.md +++ /dev/null @@ -1,244 +0,0 @@ -# Domain Specification - ---- - -## Context Map - -### Context Relationships - -| Upstream Context | Downstream Context | Relationship Pattern | Translation Notes | -|-----------------|-------------------|---------------------|-------------------| -| Viz-Server | Flowr-Core | CUSTOMER-SUPPLIER | Viz-Server reads/writes flow YAMLs | - -### Context Map Diagram - -```mermaid -graph TB - VizServer[Viz-Server] --> FlowrCore[Flowr-Core] -``` - -### Anti-Corruption Layers - -| ACL | Protects Context | From Context | ADR Reference | -|-----|-----------------|--------------|---------------| -| FlowYamlAdapter | Viz-Server | Flowr-Core | ? | - -## Flowr-Core - -### Context -The Flowr-Core is the engine that manages the execution and definition of software engineering workflows. It handles the loading of flow definitions from YAML, tracks the current state of a session, and manages transitions between states. - -### Entities - -| Name | Type | Purpose | Aggregate Root? | -|------|------|---------|-----------------| -| Flow | Entity | Top-level definition of a workflow, containing states, params, and exits | Yes | -| State | Entity | A node in the workflow with transitions, attributes, and optional subflow links | No | -| Transition | Entity | A mapping from a trigger to a target state, potentially guarded by conditions | No | -| Session | Entity | Tracks the current progress of a user through a flow, including the call stack for subflows | Yes | -| Param | Value Object | A parameter declaration with an optional default value | — | -| GuardCondition | Value Object | A mapping of evidence keys to condition expressions | — | - -### Relationships - -| Subject | Relation | Object | Cardinality | Notes | -|---------|----------|--------|-------------|-------| -| Flow | contains | State | 1:N | | -| State | has | Transition | 1:N | | -| Transition | targets | State | N:1 | | -| Session | tracks | Flow | 1:1 | | -| Session | current | State | 1:1 | | -| Session | has | SessionStackFrame | 1:N | Used for subflow nesting | - -### Aggregate Boundaries - -| Aggregate | Root Entity | Why Grouped | See | -|-----------|-------------|-------------|-----| -| FlowDefinition | Flow | Ensuring consistency of states and transitions within a single flow | ### Invariants | -| SessionState | Session | Atomic updates to current state and stack frames | ### Invariants | - -### Data Shapes - -#### Flow -| Field | Type | Required | Constraints | -|-------|------|----------|-------------| -| flow | string | Yes | | -| version | string | Yes | | -| exits | list[str] | Yes | | -| states | list[State] | Yes | | -| params | list[Param] | No | | - -#### Session -| Field | Type | Required | Constraints | -|-------|------|----------|-------------| -| flow | string | Yes | | -| state | string | Yes | | -| name | string | Yes | | -| stack | list[SessionStackFrame] | Yes | | -| params | dict | Yes | | - -### Integration Points - -#### Technology Requirements -| Context | Requirement | Verification | -|---------|-------------|-------------| -| Flowr-Core | YAML Loading | check flowr.domain.loader | -| Flowr-Core | Atomic Session Storage | check flowr.infrastructure.session_store | - -### External Contracts - -#### CLI: flowr check -- **Actor**: User -- **Trigger**: CLI invocation -- **Input**: {flow: string, state: string} -- **Output**: {attrs: dict, transitions: list} -- **Side Effects**: None (read-only) - -#### CLI: flowr transition -- **Actor**: User -- **Trigger**: CLI invocation -- **Input**: {trigger: string, session: string} -- **Output**: {from: string, to: string} -- **Side Effects**: Updates session state in store. - ---- - -## Viz-Server - - -### Context -The Viz-Server provides a visual interface for inspecting and editing flow definitions. It acts as a bridge between the raw YAML flow files and a web-based visualization tool. - -### Entities - -| Name | Type | Purpose | Aggregate Root? | -|------|------|---------|-----------------| -| VizServerConfig | Value Object | Configuration for the server (host, port, path) | — | -| FlowDefinition | Entity | A representation of a flow state machine read from disk | Yes | - -### Relationships - -| Subject | Relation | Object | Cardinality | Notes | -|---------|----------|--------|-------------|-------| -| VizServerConfig | configures | Viz-Server | 1:1 | | -| Viz-Server | manages | FlowDefinition | 1:N | One server can load multiple flows from a path | - -### Aggregate Boundaries - -| Aggregate | Root Entity | Why Grouped | See | -|-----------|-------------|-------------|-----| -| ServerSettings | VizServerConfig | Grouping server parameters for runtime | ### Invariants | - -### Data Shapes - -#### VizServerConfig -| Field | Type | Required | Constraints | -|-------|------|----------|-------------| -| host | string | Yes | Valid hostname/IP | -| port | integer | Yes | 1-65535 | -| path | string | Yes | Existing directory path | - -#### FlowDefinition -| Field | Type | Required | Constraints | -|-------|------|----------|-------------| -| flow_id | string | Yes | Unique identifier | -| states | list | Yes | List of state definitions | -| transitions | list | Yes | List of transitions | - -### Integration Points - -#### Technology Requirements -| Context | Requirement | Verification | -|---------|-------------|-------------| -| Viz-Server | HTTP Server (e.g. FastAPI/Flask) | check imports | -| Viz-Server | YAML Parser | check imports | - -#### Viz-Server -> Flowr-Core -- Purpose: Load and save flow definitions to disk -- Trigger: User interaction in the UI -- Mechanism: Shared Filesystem (YAML files) -- Pattern: CUSTOMER-SUPPLIER -- Payload: {flow_data: string} -- Response: {status: string} -- Error handling: File not found, YAML syntax error -- Ownership: Flowr-Core (defines the YAML schema) - -### External Contracts - -#### CLI: flowr serve -- **Actor**: User -- **Trigger**: CLI invocation -- **Input**: {host: string, port: integer, path: string} -- **Output**: {server_url: string} on success -- **Errors**: - - Invalid path -> Error: Path does not exist - - Port occupied -> Error: Port already in use -- **Side Effects**: Starts a background process/server using FastAPI and Uvicorn. -- **Preconditions**: `flowr[viz]` dependencies installed. - -#### API: GET /api/flows -- **Actor**: Viz-Frontend -- **Trigger**: HTTP GET request -- **Input**: {refresh: boolean} -- **Output**: list[{name: string, relativePath: string, status: string, error: string}] -- **Errors**: - - Internal Error -> 500 Internal Server Error -- **Side Effects**: Triggers flow discovery if refresh=true. - -#### API: GET /api/flows/{flow_id} -- **Actor**: Viz-Frontend -- **Trigger**: HTTP GET request -- **Input**: {flow_id: string} -- **Output**: {flow_data: object} -- **Errors**: - - Flow Not Found -> 404 Not Found - - Internal Error -> 500 Internal Server Error - -#### API: PUT /api/flows/{flow_id} -- **Actor**: Viz-Frontend -- **Trigger**: HTTP PUT request -- **Input**: {flow_data: object} -- **Output**: {success: boolean, valid: boolean, violations: list} -- **Errors**: - - Editing Disabled -> 405 Method Not Allowed - - Write Rejected -> 422 Unprocessable Entity - - Flow Not Found -> 404 Not Found - - Write Error -> 500 Internal Server Error -- **Side Effects**: Overwrites YAML file on disk. - -#### API: POST /api/flows -- **Actor**: Viz-Frontend -- **Trigger**: HTTP POST request -- **Input**: {filename: string, flow_data: object} -- **Output**: {success: boolean, valid: boolean, violations: list} -- **Errors**: - - Editing Disabled -> 405 Method Not Allowed - - Invalid Input -> 422 Unprocessable Entity (missing filename) - - Path Traversal -> 422 Unprocessable Entity - - Write Rejected -> 422 Unprocessable Entity - - Internal Error -> 500 Internal Server Error -- **Side Effects**: Creates new YAML file on disk. - -#### API: DELETE /api/flows/{flow_id} -- **Actor**: Viz-Frontend -- **Trigger**: HTTP DELETE request -- **Input**: {flow_id: string} -- **Output**: {success: boolean, deleted: string} -- **Errors**: - - Editing Disabled -> 405 Method Not Allowed - - Write Rejected -> 422 Unprocessable Entity - - Flow Not Found -> 404 Not Found - - Write Error -> 500 Internal Server Error -- **Side Effects**: Deletes YAML file from disk. - -### State Machines - -### Error Handling - -#### Concurrency and Conflict Resolution -The Viz-Server uses a "last-write-wins" strategy for flow persistence. There is no distributed locking or optimistic concurrency control (e.g., ETags). If multiple users edit the same flow, the final state is determined by the last PUT/POST request processed by the server. - -### Invariants - - ---- diff --git a/glossary.md b/glossary.md deleted file mode 100644 index c4df4e2..0000000 --- a/glossary.md +++ /dev/null @@ -1,38 +0,0 @@ -# Glossary: flowr (Viz Integration) - -> Living glossary of domain terms used in this project. -> Written and maintained by the Domain Expert during Discovery. -> Append-only: never edit or remove past entries. If a term changes, mark it retired in favor of the new entry and write a new entry. -> Code and tests take precedence over this glossary — if they diverge, refactor the code, not this file. - ---- - -## flowr -**Definition:** A CLI tool that facilitates software engineering flows by implementing state-machine based workflows. -**Aliases:** none -**Example:** "Run `flowr check` to see the current state." -**Source:** 2026-05-19 - -## Flow-Definition -**Definition:** A structured representation of a flow's states and transitions, typically persisted as a YAML file. -**Aliases:** flow-yaml -**Example:** "The Viz-Server loads the Flow-Definition from the .flowr/flows directory." -**Source:** 2026-05-19 - -## Session -**Definition:** An entity that tracks the current progress of a user through a flow, including the call stack for subflows and associated parameters. -**Aliases:** session-state -**Example:** "The session tracks that the user is currently in the `stakeholder-interview` state." -**Source:** 2026-05-19 - -## Viz-Server -**Definition:** A specialized server implementation within flowr that serves the visualization frontend and provides API endpoints for flow manipulation. -**Aliases:** flowr-viz-server -**Example:** "Run `flowr serve` to start the Viz-Server." -**Source:** 2026-05-19 - -## flowr[viz] -**Definition:** An optional installation extra for the flowr package that includes all dependencies required to run the Viz-Server. -**Aliases:** viz-extra -**Example:** "Install the visualization tools using `pip install flowr[viz]`." -**Source:** 2026-05-19 diff --git a/product_definition.md b/product_definition.md deleted file mode 100644 index ce02ba1..0000000 --- a/product_definition.md +++ /dev/null @@ -1,38 +0,0 @@ -# Product Definition: flowr (Viz Integration) - ---- - -## What flowr IS -- A CLI tool that facilitates software engineering flows by implementing state-machine based workflows. -- A system that manages flow definitions (YAML), session state (tracking progress), and provides CLI commands for checking, transitioning, and validating these flows. -- A system that now includes a visual editor (`serve` command) for managing and editing state machine flows via a web interface. - -## What flowr IS NOT -- A full-blown IDE. -- A general-purpose diagramming tool. - -## Why does this exist -The CLI-based flow management can be cumbersome for complex flow definitions. By integrating `flowr-viz`, users can visually map, inspect, and edit their flow state machines, reducing cognitive load and speeding up flow design. - -## Users -- **Software Engineer** — Uses `flowr serve` to visualize the current project's flow and make structural changes to state transitions visually. -- **System Architect** — Uses the viz tool to verify that the flow state machine aligns with the architectural design. - -## Quality Attributes - -| Attribute | Scenario | Target | Priority | -|-----------|----------|--------|----------| -| Consistency | When launching `flowr serve`, the behavior matches `flowr-viz` exactly | 100% feature parity | Must | -| Usability | A user can start the server with `flowr serve --path ` | < 5 seconds to launch | Must | -| Deployability | A user can install the viz components via `pip install flowr[viz]` | Installation succeeds without conflict | Must | - -## Deployment -- **Delivery mechanism**: Python package installable via `pip install flowr[viz]` -- **Architecture**: New `serve` subcommand added to existing argparse CLI, launching a FastAPI + Uvicorn web server as a separate module. No changes to existing domain model or commands. -- **Optional dependency**: `[viz]` extra pulls in FastAPI, Uvicorn, and flowr-viz frontend assets - ---- - -## Out of Scope -- Implementing new visualization features not present in `flowr-viz`. -- Creating a cloud-hosted version of the viz tool. diff --git a/docs/flows/arch-cycle.yaml b/tests/fixtures/arch-cycle.yaml similarity index 100% rename from docs/flows/arch-cycle.yaml rename to tests/fixtures/arch-cycle.yaml diff --git a/docs/flows/feature-flow.yaml b/tests/fixtures/feature-flow.yaml similarity index 100% rename from docs/flows/feature-flow.yaml rename to tests/fixtures/feature-flow.yaml diff --git a/docs/flows/scope-cycle.yaml b/tests/fixtures/scope-cycle.yaml similarity index 100% rename from docs/flows/scope-cycle.yaml rename to tests/fixtures/scope-cycle.yaml diff --git a/docs/flows/tdd-cycle.yaml b/tests/fixtures/tdd-cycle.yaml similarity index 100% rename from docs/flows/tdd-cycle.yaml rename to tests/fixtures/tdd-cycle.yaml