Skip to contents

Used by ai_propose_clustering() during the multi-pass theme- clustering algorithm in generate_themes_multipass(). Replaces (for the v2 algorithm) the single-call .theme_decision_schema() which fused structural and labeling decisions in one shot.

Usage

.clustering_schema()

Details

Design contract honored by this schema (binding under C-tenets 3 and 5):

(a) NO name / description fields. Labeling happens in a dedicated post-convergence pass (.theme_labeling_schema()). The AI cannot leak name pressure into the structural decision.

(b) Per-cluster rationale field. The AI must justify EACH proposed grouping in its own words, naming the codes it's grouping and why. This is the "look at each code carefully" property without falling into the earlier sequential-pairwise cascade. The AI still sees ALL leaves at once – the "full picture" – but is forced to write a justification per cluster.

(c) Closed two-valued verdict enum (continue or converged). The AI either proposes a new partition that groups the current leaves OR declares convergence. No hedging.

(d) cluster_assignments is nullable. When verdict is converged the field is null. OpenAI strict mode forbids conditional schemas (no oneOf), so the validation contract is post-call: orchestrator checks that continue + null or converged + non-null are rejected and re-prompts.


  {
    "verdict": "continue" | "converged",
    "cluster_assignments": [
      { "leaf_indices": [int, ...], "cluster_rationale": str }, ...
    ] | null,
    "overall_rationale": str
  }