Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 0 additions & 14 deletions .flake8

This file was deleted.

27 changes: 27 additions & 0 deletions .github/workflows/pre-commit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: pre-commit (Ruff)

on:
push:
branches:
- "master"
- "main"
pull_request:
branches:
- "master"
- "main"
workflow_dispatch:

jobs:
ruff:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- uses: pre-commit/[email protected]
with:
extra_args: --all-files ruff
- uses: pre-commit/[email protected]
with:
extra_args: --all-files ruff-format
26 changes: 15 additions & 11 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
repos:
- repo: https://github.com/ambv/black
rev: 23.11.0
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.7.0
hooks:
- id: black
- repo: https://github.com/pycqa/isort
rev: 5.12.0
hooks:
- id: isort
- repo: https://github.com/python-poetry/poetry
rev: 1.7.0
- id: ruff
args: ["--fix", "--exit-non-zero-on-fix"]
- id: ruff-format
- repo: local
hooks:
- id: poetry-check
name: poetry-check
entry: poetry check
language: system
pass_filenames: false
- id: poetry-lock
- repo: local
hooks:
name: poetry-lock
entry: poetry lock
language: system
pass_filenames: false
- id: unittests
name: unittests
language: system
entry: poetry run pytest ./tests
files: ^(flowpipe/|tests/|examples/)
pass_filenames: false
- id: pylint
name: pylint
Expand Down
104 changes: 104 additions & 0 deletions .specify/memory/constitution.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<!--
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need those .specify files for ruff formatting?

Sync Impact Report
Version change: 0.0.0 → 1.0.0
Modified principles:
- [PRINCIPLE_1_NAME] → Framework-Only Scope
- [PRINCIPLE_2_NAME] → Plain Python Simplicity
- [PRINCIPLE_3_NAME] → Portable Graph Serialization
- [PRINCIPLE_4_NAME] → Test-Driven Total Coverage
- [PRINCIPLE_5_NAME] → Stable APIs & Dual-Python Support
Added sections:
- Engineering Constraints
- Development Workflow & Quality Gates
Removed sections:
- None
Templates requiring updates:
- ✅ .specify/templates/plan-template.md
- ✅ .specify/templates/spec-template.md
- ✅ .specify/templates/tasks-template.md
Follow-up TODOs:
- None
-->
# Flowpipe Constitution

## Core Principles

### I. Framework-Only Scope
Flowpipe ships only the graph, node, plug, and evaluation framework. Core code MUST remain
domain-agnostic: contributions MAY NOT add business-specific node implementations, external
service wrappers, or bundled workflows. Examples and docs can demonstrate user-defined
nodes, but the runtime stays a thin framework so teams own their node libraries. Rationale:
the project’s value is the reusable framework, not pre-baked logic, which keeps Flowpipe
lightweight.

### II. Plain Python Simplicity
Flowpipe MUST run with normal Python tooling and never require bespoke environments,
background services, or infrastructure. New dependencies MUST be justified, pure-Python
when possible, and optionalized if they raise the project’s footprint. APIs MUST embrace
idiomatic Python constructs (classes, decorators, dataclasses where compatible) so users can
work inside familiar workflows. Rationale: simplicity keeps adoption friction low and honors
Flowpipe’s lightweight promise.

### III. Portable Graph Serialization
Graphs and nodes MUST stay serializable so they can execute remotely (render farms, job
queues, services). State belongs in plugs and metadata; hidden runtime state is forbidden.
Node metadata MUST capture everything remote evaluators need, and serialization formats
must stay stable so external converters—documented but not maintained here—can rebuild
graphs. Rationale: serialization is the bridge that lets Flowpipe stay framework-only yet run
anywhere.

### IV. Test-Driven Total Coverage
Every change follows red-green-refactor: author tests that fail, implement code, refactor with
green tests. Coverage MUST remain at 100% with pytest across supported Python versions.
New features require targeted unit tests plus higher-level coverage (integration/functional)
when behavior spans nodes/graphs. Skipping tests or marking `# pragma: no cover` demands
documented justification. Rationale: Flowpipe is engineered test-first, and exhaustive tests
ensure safe serialization and remote execution.

### V. Stable APIs & Dual-Python Support
The public API MUST remain backward compatible for Python 3.7+ consumers until
governance explicitly retires that guarantee. Deprecations require a migration path and
semantic versioning (MAJOR for breaking changes, MINOR for backward-compatible features,
PATCH for fixes). Metadata in `pyproject.toml`, docs, and release notes MUST stay in sync so
downstream automation remains trustable. Rationale: pipelines depend on Flowpipe stability.

## Engineering Constraints

- Repository content MUST stay focused on framework modules (`flowpipe/*`), documentation,
and examples. Example nodes remain under `examples/` and never bleed into installable
packages.
- Serialization requirements MUST be met by keeping plug payloads JSON/pickle friendly, and
by guarding against implicit references (open file handles, live connections, global singletons).
- Tooling MUST use Black formatting and Google-style docstrings; lint/test hooks in
`.pre-commit-config.yaml` MUST remain green before merge.
- Documentation MUST accompany new behaviors, covering how to keep nodes simple,
serialize metadata, and run graphs locally versus remotely. Conversion guides live in docs,
not in runtime code.
- Releases follow the documented recipe (update `pyproject.toml` + `docs/conf.py`, tag, publish)
so PyPI consumers get reproducible artifacts with matching metadata.

## Development Workflow & Quality Gates

1. **Specification First**: Each feature starts with `specs/[feature]/spec.md`, capturing independent
user stories, serialization considerations, and backward-compatibility notes.
2. **Implementation Plan**: Plans must document how the work obeys every core principle,
especially framework scope, serialization, and TDD coverage expectations.
3. **Task Breakdown**: Tasks are grouped per user story so increments stay independently
deliverable and testable. Each task references precise paths and required tests.
4. **Testing Discipline**: Contributors run pre-commit hooks plus pytest across supported Python
versions. Pull requests link coverage diffs proving 100% coverage is intact.
5. **Serialization Proof**: Features that touch graph/node data include reproduction steps (docs
or tests) showing the new metadata serializes/deserializes cleanly without custom runtimes.

## Governance

- This constitution governs every Flowpipe contribution. Conflicting practices defer to this file.
- Amendments require: (a) an issue outlining the change and rationale, (b) agreement from at
least two maintainers, (c) synchronized updates to dependent templates/docs, and (d) a
recorded version bump with dates.
- Version bumps follow semantic rules described in Principle V. Ratification date records when
v1.0.0 was adopted; Last Amended reflects the latest accepted change.
- Compliance Review: Every PR must cite how it satisfies each principle (link to plan/spec
sections). Reviews block until gaps are resolved or explicitly deferred with TODOs noted here.

**Version**: 1.0.0 | **Ratified**: 2025-11-14 | **Last Amended**: 2025-11-14
148 changes: 148 additions & 0 deletions .specify/scripts/powershell/check-prerequisites.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
#!/usr/bin/env pwsh

# Consolidated prerequisite checking script (PowerShell)
#
# This script provides unified prerequisite checking for Spec-Driven Development workflow.
# It replaces the functionality previously spread across multiple scripts.
#
# Usage: ./check-prerequisites.ps1 [OPTIONS]
#
# OPTIONS:
# -Json Output in JSON format
# -RequireTasks Require tasks.md to exist (for implementation phase)
# -IncludeTasks Include tasks.md in AVAILABLE_DOCS list
# -PathsOnly Only output path variables (no validation)
# -Help, -h Show help message

[CmdletBinding()]
param(
[switch]$Json,
[switch]$RequireTasks,
[switch]$IncludeTasks,
[switch]$PathsOnly,
[switch]$Help
)

$ErrorActionPreference = 'Stop'

# Show help if requested
if ($Help) {
Write-Output @"
Usage: check-prerequisites.ps1 [OPTIONS]
Consolidated prerequisite checking for Spec-Driven Development workflow.
OPTIONS:
-Json Output in JSON format
-RequireTasks Require tasks.md to exist (for implementation phase)
-IncludeTasks Include tasks.md in AVAILABLE_DOCS list
-PathsOnly Only output path variables (no prerequisite validation)
-Help, -h Show this help message
EXAMPLES:
# Check task prerequisites (plan.md required)
.\check-prerequisites.ps1 -Json
# Check implementation prerequisites (plan.md + tasks.md required)
.\check-prerequisites.ps1 -Json -RequireTasks -IncludeTasks
# Get feature paths only (no validation)
.\check-prerequisites.ps1 -PathsOnly
"@
exit 0
}

# Source common functions
. "$PSScriptRoot/common.ps1"

# Get feature paths and validate branch
$paths = Get-FeaturePathsEnv

if (-not (Test-FeatureBranch -Branch $paths.CURRENT_BRANCH -HasGit:$paths.HAS_GIT)) {
exit 1
}

# If paths-only mode, output paths and exit (support combined -Json -PathsOnly)
if ($PathsOnly) {
if ($Json) {
[PSCustomObject]@{
REPO_ROOT = $paths.REPO_ROOT
BRANCH = $paths.CURRENT_BRANCH
FEATURE_DIR = $paths.FEATURE_DIR
FEATURE_SPEC = $paths.FEATURE_SPEC
IMPL_PLAN = $paths.IMPL_PLAN
TASKS = $paths.TASKS
} | ConvertTo-Json -Compress
} else {
Write-Output "REPO_ROOT: $($paths.REPO_ROOT)"
Write-Output "BRANCH: $($paths.CURRENT_BRANCH)"
Write-Output "FEATURE_DIR: $($paths.FEATURE_DIR)"
Write-Output "FEATURE_SPEC: $($paths.FEATURE_SPEC)"
Write-Output "IMPL_PLAN: $($paths.IMPL_PLAN)"
Write-Output "TASKS: $($paths.TASKS)"
}
exit 0
}

# Validate required directories and files
if (-not (Test-Path $paths.FEATURE_DIR -PathType Container)) {
Write-Output "ERROR: Feature directory not found: $($paths.FEATURE_DIR)"
Write-Output "Run /speckit.specify first to create the feature structure."
exit 1
}

if (-not (Test-Path $paths.IMPL_PLAN -PathType Leaf)) {
Write-Output "ERROR: plan.md not found in $($paths.FEATURE_DIR)"
Write-Output "Run /speckit.plan first to create the implementation plan."
exit 1
}

# Check for tasks.md if required
if ($RequireTasks -and -not (Test-Path $paths.TASKS -PathType Leaf)) {
Write-Output "ERROR: tasks.md not found in $($paths.FEATURE_DIR)"
Write-Output "Run /speckit.tasks first to create the task list."
exit 1
}

# Build list of available documents
$docs = @()

# Always check these optional docs
if (Test-Path $paths.RESEARCH) { $docs += 'research.md' }
if (Test-Path $paths.DATA_MODEL) { $docs += 'data-model.md' }

# Check contracts directory (only if it exists and has files)
if ((Test-Path $paths.CONTRACTS_DIR) -and (Get-ChildItem -Path $paths.CONTRACTS_DIR -ErrorAction SilentlyContinue | Select-Object -First 1)) {
$docs += 'contracts/'
}

if (Test-Path $paths.QUICKSTART) { $docs += 'quickstart.md' }

# Include tasks.md if requested and it exists
if ($IncludeTasks -and (Test-Path $paths.TASKS)) {
$docs += 'tasks.md'
}

# Output results
if ($Json) {
# JSON output
[PSCustomObject]@{
FEATURE_DIR = $paths.FEATURE_DIR
AVAILABLE_DOCS = $docs
} | ConvertTo-Json -Compress
} else {
# Text output
Write-Output "FEATURE_DIR:$($paths.FEATURE_DIR)"
Write-Output "AVAILABLE_DOCS:"

# Show status of each potential document
Test-FileExists -Path $paths.RESEARCH -Description 'research.md' | Out-Null
Test-FileExists -Path $paths.DATA_MODEL -Description 'data-model.md' | Out-Null
Test-DirHasFiles -Path $paths.CONTRACTS_DIR -Description 'contracts/' | Out-Null
Test-FileExists -Path $paths.QUICKSTART -Description 'quickstart.md' | Out-Null

if ($IncludeTasks) {
Test-FileExists -Path $paths.TASKS -Description 'tasks.md' | Out-Null
}
}
Loading