Files
ThothII/harness/docs/workflow-editing.md
T
marcopan fc5fbe6b65 refactor(harness): renaming prodotto tht (Onda -1)
Thoth (tht) è il prodotto, PSD è il cliente. Nessun riferimento al contesto
clinico nel codice.

Rinomine:
- comando+package nsp→tht (dir nsp/→tht/, 46 import, pyproject entry point)
- gate nsp-gate.js→tht-gate.js (+ rewrite token, relayIfNspFails→relayIfThtFails)
- workspace chirone.{example,test}.yaml→tht.{example,test}.yaml (generici)
- env THOTH_→THT_ (19 var) + NSP_ stragglers (NSP_HARNESS_ROOT, NSP_SESSION)
- commenti/docstring chirone/psdwp3/policlinico neutralizzati ('the reference
  implementation', 'the DWH')

Aggiunto [tool.setuptools.packages.find] include=['tht*'] (necessario: l'auto-
discovery rompeva con tht/ + workspaces/ come top-level multipli).

.env operatore aggiornato in-place (prefissi THT_, valori preservati, gitignored).

Verifica: pytest 109 passed, npm test 14 pass, tht phase meta --json OK, zero
residui nsp/THOTH_/NSP_/chirone nel package.
2026-06-27 10:33:16 +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 (tht-gate.js), and the skill all read from it. There are no mirrored constants in JS or Python — that was the the reference implementation 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 (tht 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

tht 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.