Skip to content
Merged
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
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,4 @@ jobs:
- run: /tmp/samsarix-spirals-smoke/bin/python -m pip install --no-deps dist/*.whl
- run: /tmp/samsarix-spirals-smoke/bin/samsarix-spirals validate examples/hello.json
- run: /tmp/samsarix-spirals-smoke/bin/samsarix-spirals run examples/hello.json --input examples/hello.input.json --compact
- run: /tmp/samsarix-spirals-smoke/bin/samsarix-spirals test examples/release-policy.json examples/release-policy.suite.json --json --compact
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ use semantic versioning while the public API remains pre-1.0.

## [Unreleased]

### Added

- Versioned, bounded workflow regression suites with exact-output and expected-error
contracts through the Python API and `samsarix-spirals test` command.
- A release-policy example that demonstrates a practical CI approval gate.
- Competitive positioning, flagship use cases, and measurable adoption gates.

### Changed

- Renamed the product, distribution, import package, CLI, and public base exception from
Expand Down
39 changes: 30 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# Samsarix Spirals

Samsarix Spirals is a small, deterministic runner for JSON workflows that you can review,
test, and keep beside your code. It is aimed at local validation and data shaping—not
hosted automation, third-party integrations, or durable distributed orchestration.
Samsarix Spirals is a deterministic contract runner for JSON workflows that you can
review, regression-test, and keep beside your code. It is aimed at release gates,
agent-output contracts, configuration checks, and local data shaping—not hosted
automation or durable distributed orchestration.

Version `0.1.0` is a source release candidate. The package is not currently published
on PyPI, so install it from a checkout or a locally built wheel.
Expand All @@ -11,21 +12,23 @@ on PyPI, so install it from a checkout or a locally built wheel.

- Validates a versioned JSON workflow before execution.
- Runs `set` and `assert` steps in a fixed order.
- Runs checked-in suites that prove expected outputs and expected failures.
- Renders values from `input`, `defaults`, and completed `steps`.
- Emits deterministic JSON with no timestamps, random IDs, or hidden state.
- Performs no network requests, subprocess execution, credential storage, or imports
from another Samsarix repository.

Samsarix Spirals is not a Zapier, n8n, Temporal, Prefect, or Dagster replacement. It has no
UI, server, scheduler, retries, connectors, parallelism, or persistence in this release.
Samsarix Spirals is not a Zapier, n8n, Temporal, Prefect, Dagster, Dagger, or CUE
replacement. Its advantage is a deliberately small, hermetic contract surface: no UI,
server, scheduler, connectors, code execution, network access, or persistence.

## Install from a checkout

Python 3.11 or newer is required.

```console
git clone https://github.com/Deathcharge/samsarix-spirals.git
cd helix-spirals
cd samsarix-spirals
python -m venv .venv
.venv\Scripts\python -m pip install -e .
```
Expand All @@ -37,6 +40,7 @@ On macOS or Linux, use `.venv/bin/python` in place of `.venv\Scripts\python`.
```console
.venv\Scripts\samsarix-spirals validate examples/hello.json
.venv\Scripts\samsarix-spirals run examples/hello.json --input examples/hello.input.json
.venv\Scripts\samsarix-spirals test examples/release-policy.json examples/release-policy.suite.json

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Add the Unix form of the new suite command.

The new example uses the Windows-only .venv\Scripts\samsarix-spirals path, although this README also documents macOS and Linux installation. Add the .venv/bin/samsarix-spirals form or show an activated-venv command. Otherwise Unix users cannot run the new release-policy example by copying the documented command.

This follows the platform-specific paths already documented in README.md.

Proposed documentation fix
- .venv\Scripts\samsarix-spirals test examples/release-policy.json examples/release-policy.suite.json
+# Windows
+.venv\Scripts\samsarix-spirals test examples/release-policy.json examples/release-policy.suite.json
+# macOS/Linux
+.venv/bin/samsarix-spirals test examples/release-policy.json examples/release-policy.suite.json
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
.venv\Scripts\samsarix-spirals test examples/release-policy.json examples/release-policy.suite.json
# Windows
.venv\Scripts\samsarix-spirals test examples/release-policy.json examples/release-policy.suite.json
# macOS/Linux
.venv/bin/samsarix-spirals test examples/release-policy.json examples/release-policy.suite.json
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` at line 43, Update the release-policy example command in README.md
to include the Unix virtual-environment executable form
`.venv/bin/samsarix-spirals`, or use an activated-venv invocation, while
preserving the documented Windows command and existing platform-specific
conventions.

```

The output's `output` field is:
Expand All @@ -62,6 +66,21 @@ echo {"name":"Ada"} | .venv\Scripts\samsarix-spirals run examples/hello.json --i

PowerShell users should prefer `'{"name":"Ada"}' | ...` so quoting is preserved.

## Regression suites

A suite stores named inputs beside exact expected outputs or expected execution errors.
The `test` command runs every case, reports all mismatches, and exits `1` if the contract
has changed. Reports describe the mismatch without echoing input or output values, which
reduces accidental disclosure of fixture data in CI logs.
Comment on lines +69 to +74

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Update the failure-status documentation for test.

The test command returns 1 when a suite case does not match its expected output or error, even when workflow execution succeeds. The current sentence says 1 means the contract changed, which is not observable, and the later exit-status list describes 1 only as execution failure. Suite validation errors also return 2, but the list names only workflow structure. Align both sections with the CLI contract.

The test branch in src/samsarix_spirals/cli.py, Lines 97-143, and tests/test_cli.py, Lines 142-160, provide the behavior used here.

Proposed documentation fix
- The `test` command runs every case, reports all mismatches, and exits `1` if the contract
- has changed.
+ The `test` command runs every case, reports all mismatches, and exits `1` if a case does
+ not match its expected output or error.

- CLI exit `0`: validation or execution succeeded.
- CLI exit `1`: a valid workflow failed during execution, such as a false assertion.
- CLI exit `2`: arguments, files, JSON, or workflow structure were invalid.
+ CLI exit `0`: validation or execution succeeded, or all suite cases passed.
+ CLI exit `1`: execution failed, or a suite case did not match.
+ CLI exit `2`: arguments, files, JSON, workflow, or suite structure were invalid.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 69 - 74, Update the README regression-suite
description and exit-status list to match the `test` command contract: status 1
covers mismatched expected outputs or execution errors, including cases where
workflow execution succeeds, while status 2 covers suite validation errors as
well as workflow-structure errors. Replace the non-observable “contract has
changed” wording and ensure both sections consistently describe these statuses.


```console
samsarix-spirals test workflow.json workflow.suite.json
samsarix-spirals test workflow.json workflow.suite.json --json --compact
```

See [`examples/release-policy.suite.json`](examples/release-policy.suite.json) for a
release approval gate with both successful and rejected cases.

## Python API

```python
Expand All @@ -87,21 +106,23 @@ output, and later steps do not run.
## Documentation

- [Workflow format](docs/WORKFLOW_FORMAT.md)
- [Competitive position and use cases](docs/COMPETITIVE_POSITIONING.md)
- [Productization record](docs/PRODUCTIZATION.md)
- [Release process](docs/RELEASING.md)
- [Security policy](SECURITY.md)
- [Contributing](CONTRIBUTING.md)

## Project status and release boundary

The 0.1 core journey—install, validate, run, inspect output—has local automated coverage.
The core journey—install, validate, run, regression-test, inspect output—has local
automated coverage.
Before publishing, a maintainer still needs to observe the GitHub Actions matrix on the
target commit, confirm the distribution name is still available, create the tag, and
publish through an owned package index account. Those external steps are intentionally
not claimed as complete here.

The GitHub repository currently retains its legacy `helix-spirals` slug. The product,
Python distribution, import package, and console command use the Samsarix name.
The repository, product, Python distribution, import package, and console command now use
the Samsarix identity.

## License

Expand Down
96 changes: 68 additions & 28 deletions ROADMAP.md
Original file line number Diff line number Diff line change
@@ -1,43 +1,83 @@
# Samsarix Spirals roadmap

This roadmap separates four gates: merge, release, publication, and flagship adoption. Passing one does not imply the next.
This roadmap separates code completion, release, publication, and real adoption. Passing
one gate does not imply the next.

## Product boundary
## Product position

Portfolio role: **experiment or learning project**. Keep this as an evidence-producing experiment or reference. Promotion to a supported product requires a real consumer and a measured advantage over the simpler alternative.
Planned repository identity: `Deathcharge/samsarix-spirals` (ready-reference).
Samsarix Spirals is a **hermetic JSON workflow contract runner** for developers, platform
teams, and AI-agent builders. It should make small data-shaping and policy flows easier to
review and safer to execute than an ad hoc script, while remaining dramatically smaller
than a general orchestrator.

Current disposition: Merge as a labeled reference or experiment; do not imply production support.
The product earns its place only when all of these remain true:

## Stabilize the productized default
- a workflow and its regression suite fit naturally beside application code;
- identical workflow and input JSON values produce identical results;
- execution needs no daemon, container runtime, credentials, network, subprocess, or
dynamically loaded code;
- failure is bounded, attributable to a step, and useful in CI;
- the workflow is clearer to its owners than the equivalent bespoke script.

- Keep the default branch buildable from a clean checkout and preserve exact-head CI evidence.
- Keep Samsarix LLC branding, package identity, license metadata, and compatibility aliases internally consistent.
- Preserve the pre-productization default under a rollback ref before merging; do not delete legacy history.
- Review priority: Prove one real schema-v1 consumer.
- Review priority: otherwise tag a reviewed reference snapshot and freeze feature investment.
See [the competitive position](docs/COMPETITIVE_POSITIONING.md) for the evidence behind
this boundary.

## Release candidate
## Flagship use cases

- Define a falsifiable evaluation against a simpler baseline.
- Publish fixtures, limits, and reproducible results without overstating conclusions.
- Tag and freeze a useful reference if the experiment does not earn adoption.
1. **Release manifest gates** — validate approval and required metadata, then emit a
normalized manifest for a later publishing job.
2. **AI-output contracts** — turn untrusted structured model output into a bounded,
regression-tested deterministic value before another system consumes it.
3. **Repository policy fixtures** — keep configuration and metadata expectations in
reviewable JSON with positive and negative cases.
4. **Portable data-shaping checks** — produce the same small JSON artifact on a laptop,
pre-commit hook, and CI runner without provider-specific syntax.

Current hardening backlog:
## Milestones

- Only `set` and `assert`; many users can express the same job directly in tests or a short script.
- A new workflow schema creates another compatibility contract in an already crowded orchestration portfolio.
- No consumer, published JSON Schema, external adoption, release, or migration path from the removed prototype.
- The deletion-heavy PR needs careful legal/history review despite the superior direction.
- Repository slug remains Helix-named while distribution/import/CLI use Samsarix.
### 0.2 — Contract suites

## Samsarix adoption
- [x] Versioned suite files with named inputs.
- [x] Exact-output and expected-error assertions.
- [x] Human and machine-readable reports with CI exit behavior.
- [x] A realistic release-policy example.
- [ ] Publish JSON Schemas for workflows and suites.
- [ ] Emit JUnit XML for native CI test reporting.

- Define a public API, event, schema, artifact, or deployment contract before connecting to Samsarix Unified.
- Add a consumer-owned contract fixture covering authentication, privacy, limits, errors, and version compatibility.
- Make one implementation canonical; remove or freeze duplicate behavior only after parity and rollback are proven.
- Record an owner, support level, compatibility window, and measurable adoption signal.
### 0.3 — Useful deterministic shaping

## Completion evidence
- Add a small, orthogonal operation set for object merge, key selection, list mapping,
filtering, and string normalization without arbitrary expressions.
- Add an `explain` command that shows dependencies and referenced input paths without
executing the workflow.
- Define compatibility and deprecation rules for every schema-visible operation.
- Prove agent-output and repository-policy examples with adversarial fixtures.

A milestone is complete only when its exact commit, commands and results, artifact digest, consumer or deployment, and rollback path are recorded in a pull request or release record. README claims must not exceed that evidence.
### 0.4 — Repository adoption

- Ship a pinned GitHub Action and documented pre-commit integration.
- Add stable SARIF or annotation output for step-scoped failures.
- Publish signed distributions and an SBOM through an owned package-index account.
- Measure startup time, maximum-memory behavior, and fixture-suite throughput.

### 1.0 — Supported contract

- Freeze schema version 1 and its compatibility window.
- Publish a support policy and migration fixtures for schema version changes.
- Complete an independent security review of all parsing and amplification limits.
- Provide a rollback-tested release and incident process.

## Adoption gates

Do not describe Samsarix Spirals as production-ready until evidence shows:

- at least three independently owned repositories run it in CI;
- at least one flagship consumer has 30 consecutive days of successful contract checks;
- maintainers record 100 real workflow-suite executions with no nondeterministic result;
- at least one consumer demonstrates that a reviewed workflow is clearer or safer than
its prior script using a written before/after evaluation;
- release artifacts, checksums, exact-head CI, support ownership, and rollback steps are
recorded for the published version.

If those gates are not met, keep the project an honest alpha rather than expanding into
connectors, scheduling, hosted execution, or another general orchestration platform.
58 changes: 58 additions & 0 deletions docs/COMPETITIVE_POSITIONING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Competitive position and use cases

Research reviewed on 2026-08-08 supports a narrow product boundary for Samsarix Spirals.
The project should complement mature orchestrators and configuration languages, not
imitate their broadest capabilities.

## What adjacent products already do well

| Product | Established strength | Why Samsarix should not clone it |
| --- | --- | --- |
| [Temporal](https://docs.temporal.io/) | Durable application execution that resumes after infrastructure failures. | Competing requires a service, persistence model, worker lifecycle, and operational control plane. |
| [Prefect](https://docs.prefect.io/v3/concepts/tasks) | Observable Python tasks with retries, caching, concurrency, timeouts, and state. | Adding these features would erase the hermetic runner's small trust and deployment surface. |
| [Dagster](https://docs.dagster.io/) | Asset-oriented data orchestration with lineage, observability, and testability. | Samsarix has neither an asset catalog nor a data-platform control plane. |
| [Dagger](https://docs.dagger.io/) | Local-first, repeatable CI pipelines using containers, typed SDKs, caching, and traces. | Samsarix should stay useful where Docker and executable pipeline code are unnecessary or undesirable. |
| [CUE](https://cuelang.org/docs/concept/how-cue-enables-configuration/) | Expressive configuration constraints, validation, unification, and generation. | Recreating a constraint language would introduce far more semantic complexity than a reviewable step model needs. |
| [GitHub Actions](https://docs.github.com/en/actions/concepts/workflows-and-actions/workflows) | Event-triggered jobs and reusable actions on managed or self-hosted runners. | Samsarix can be one portable contract-checking step inside CI rather than another CI service. |

## Differentiated promise

Samsarix should optimize for a sentence a reviewer can verify:

> This checked-in JSON turns these bounded inputs into this exact output—or this expected
> step failure—without executing code or contacting another system.

That promise makes the product useful in security-sensitive and agentic development
loops where an orchestration platform is excessive but a shell or Python script creates
an unnecessarily broad execution surface.

## Initial user journeys

### Release-policy owner

The owner checks in a workflow and positive/negative cases. Developers run the suite
locally; CI runs the same command before a separate, credentialed publish job. Samsarix
never receives publishing credentials and emits only normalized JSON.

### AI application developer

The developer treats structured model output as untrusted input. A workflow asserts
required policy decisions and shapes the accepted fields. Regression cases lock in known
good and known bad responses before the output reaches a side-effecting tool.

### Platform repository maintainer

The maintainer defines small configuration or metadata policies once, stores adversarial
fixtures beside them, and receives deterministic step-scoped failures across laptops and
CI providers.

## Product guardrails

- Do not add arbitrary Python, shell, JavaScript, dynamic imports, or expression `eval`.
- Keep network, filesystem writes, environment access, time, randomness, and credentials
outside the workflow runtime.
- Add new operations only when they are deterministic, bounded, composable, and supported
by a flagship fixture suite.
- Prefer machine-readable artifacts and CI integration over a hosted dashboard until
adoption proves that a control plane is necessary.
- Compare every new feature with a short script and remove it when the script is clearer.
41 changes: 41 additions & 0 deletions docs/WORKFLOW_FORMAT.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,3 +122,44 @@ environment variables, and does not add time, randomness, or identifiers to resu
Given the same workflow, input, and run limit, its JSON value result is the same.

Object key order is not semantic. The CLI sorts keys when serializing its result.

## Regression suite format

The `test` command accepts a workflow and a separate suite document. Suite version `1`
has this shape:

```json
{
"suite_version": 1,
"name": "release contract",
"cases": [
{
"name": "approved release",
"input": {"approved": true},
"expect": {"output": {"publish": true}}
},
{
"name": "unapproved release",
"input": {"approved": false},
"expect": {
"error": {
"step_id": "require_approval",
"message_contains": "approval is required"
}
}
}
]
}
```

A suite contains between 1 and 1,000 uniquely named cases. Each case has an optional
`input` object and exactly one expectation:

- `output` compares the workflow's final JSON value using exact JSON equality;
- `error` expects execution to fail and can constrain `step_id`, `message_contains`,
both, or neither.

Unknown fields are rejected. Suite files use the same 1 MiB, UTF-8, unique-key,
finite-number, nesting, string, collection, and total-value limits as workflow and input
documents. A suite runs all cases even after a mismatch. Human and JSON reports avoid
echoing fixture values.
49 changes: 49 additions & 0 deletions examples/release-policy.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
"schema_version": 1,
"name": "release-policy",
"description": "Gate and normalize release metadata before a CI publish job.",
"defaults": {
"channel": "stable"
},
"steps": [
{
"id": "require_version",
"uses": "assert",
"with": {
"value": "{{ input.version }}",
"operator": "not_empty",
"message": "version is required"
}
},
{
"id": "require_commit",
"uses": "assert",
"with": {
"value": "{{ input.commit }}",
"operator": "not_empty",
"message": "commit is required"
}
},
{
"id": "require_approval",
"uses": "assert",
"with": {
"value": "{{ input.approved }}",
"operator": "equals",
"expected": true,
"message": "release approval is required"
}
},
{
"id": "manifest",
"uses": "set",
"with": {
"version": "{{ input.version }}",
"commit": "{{ input.commit }}",
"channel": "{{ defaults.channel }}",
"publish": true
}
}
],
"output": "{{ steps.manifest }}"
}
Loading
Loading