Files
ThothII/harness/docs/workflow-editing.md
T
marcopan 50d5f9c9cf docs(harness): README + workflow editing + testing guide (D6)
README: install, configure (.env + workspaces/), the workflow, run inside Pi, the
three-level test commands, layout, references.

docs/workflow-editing.md: how to edit workflow.yaml (add/reorder/merge/skip phases,
advance kinds, prerequisite predicates, decision_min_phase derivation, artifacts_out
+ teardown) -- referencing spec §5.3. Emphasizes no mirrored constants (the F2 point).

docs/testing.md: the honest L0/L1/L2 split in plain language -- what each covers and
does NOT. States the headline plainly: the skill->LLM->gate loop has NO automated
regression coverage (L2 only, pre-release). Documents the fake-Pi follow-up as the
gap-closer. Security note on keys (.env gitignored, never logged, rotate leaked keys).
2026-06-26 23:20:06 +02:00

3.3 KiB

Editing the workflow

harness/workflow.yaml is the single source of workflow truth (spec F2, §5.3). phase.py, the gate (nsp-gate.js), and the skill all read from it. There are no mirrored constants in JS or Python — that was the ChironeWp3 drift bug (PHASE_NAMES truncated to 7 entries in JS, F8/datamart silently dropped). Editing this one file is the only place the workflow changes.

Structure

schema_version: 1
phases:
  - id: F3                      # stable id (referenced by the gate)
    name: riscrittura           # human label (nsp phase show / gate UI)
    advance: kind:phase         # how the phase advances (see below)
    prerequisites:              # what must hold before advancing (gate checks these)
      - decision_exists: question_rewritten
    artifacts_out: [question.md]  # files produced; used by teardown on rollback (D15)

decision_min_phase: auto and max_phase: auto mean these are derived from the phase list (don't hard-code them).

advance kinds

kind meaning
kind:phase advances on any phase-approved decision for this phase
auto_if_empty auto-advances if no decisions were made (F2 memoria)
auto_if_empty_or_skipped auto-advances if empty OR a phase_skipped decision exists
reviewer_decide requires an explicit reviewer decision (F4, F8)

prerequisites predicates

A phase is "ready to advance" when ALL its prerequisites hold. Predicates:

  • decision_exists: <type> — a decision of that type exists (effective view).
  • decision_subject_exists: [<type>, <subject>] — e.g. a phase_skipped for phase:6.
  • file_validates: [<artifact>, <model>] — e.g. schema_linking.json parses as a SchemaLinking.
  • all_ctes_approved: true — all CTE blocks approved (F6).
  • any: [...] / all: [...] — combine predicates.

A decision type's min phase is derived: the earliest phase whose prerequisites reference it. So adding a prerequisite like decision_exists: my_new_decision to F5 automatically makes my_new_decision valid from phase 5.

Common edits

Add a phase

Append a phase to phases:. max_phase becomes the new count automatically. Give it an id, name, advance, and (optionally) prerequisites / artifacts_out.

Reorder / merge / skip phases

Reorder the list; max_phase and decision_min_phase recompute. To make a phase skippable, set advance: auto_if_empty_or_skipped and let the gate emit a phase_skipped decision (predicate decision_subject_exists: [phase_skipped, "phase:N"]).

Add an artifact

Add it to a phase's artifacts_out. On rollback (teardown_to_phase), artifacts produced by phases after the target are deleted; the target phase's artifacts are preserved. This is the D15 fix for the orphaned-CTE-blocks-finalize bug.

After editing

nsp phase meta --json     # confirm the new shape (max_phase, phases, artifacts_out)
pytest                    # L1 coherence smoke re-derives from the new workflow.yaml

No JS or Python constants to update — that's the point.