schema

package module
v0.1.0-rc8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 27, 2026 License: Apache-2.0 Imports: 22 Imported by: 0

README

peasant-labs/schema

The canonical data / wire contract for peasant and the village transcript commons: one contract-only Go leaf module that every backend produces and every client consumes.

Use this module whenever code produces, validates, or consumes a peasant-labs wire payload. Go services import the canonical structs and validators directly; TypeScript applications import the matching generated types and Zod schemas. API-aware TypeScript tooling can additionally import type-only paths and operations contracts from @peasant-labs/schema/local-api or @peasant-labs/schema/village-api. Those subpaths describe request and response shapes; they do not perform network requests.

module github.com/peasant-labs/schema

It holds the domain + wire types, the closed-set enums, the publish/pull/push envelopes, the versioned OpenAPI specs, the publish-request validator, the typed fixtures, the generated TypeScript bindings, and the codegen + release-guard tooling. It has no service runtime: no HTTP server, WebSocket hub, transport client, or CLI product. Everything here is contract data, validators, generated specs, fixtures, and the gates that keep them honest.


Why this module exists

The peasant backend, the village backend, and their frontends all speak the same session_detail / publish / pull wire. If each side kept its own copy of those types, the copies would drift, and a silent wire mismatch between a producer and a consumer is exactly the class of bug that is expensive to find.

This module is the single source of truth for that wire. It was extracted from peasant's old nested pkg/schema into a standalone, public, versioned Go module so that:

  • One definition, many consumers. The Go types here ARE the contract. peasant emits SessionDetailPayload / PublishRequest; the village validates and stores the same shapes; the frontends render them. Nobody redefines the wire.
  • Served ≡ enforced. The village serves its OpenAPI doc from VillageAPISpecJSON() and validates inbound publishes against PublishRequestSchemaJSON(): the same embedded bytes. The documented spec and the enforced schema are one artifact, so they can never diverge.
  • It stays a leaf. The module depends on nothing first-party except bestiary (a sibling), imports no runtime machinery, and a leaf-audit gate keeps its dependency set pinned. That is what lets consumers pin it cheaply (see Pinning).

The data path end-to-end: the contract defines the wire, the peasant and village backends produce it, and transcript-browser (embedded by the two frontends) renders it.

flowchart LR
    schema["schema module<br/>the wire contract"]
    peasant["peasant backend"]
    village["village backend"]
    tb["transcript-browser"]
    pweb["peasant web"]
    vfe["village frontend"]

    schema -->|defines the wire| peasant
    schema -->|defines the wire| village
    peasant -->|SessionDetailPayload| tb
    village -->|SessionDetailPayload| tb
    pweb -->|embeds| tb
    vfe -->|embeds| tb

Coordinates & status

Module path github.com/peasant-labs/schema
Default branch develop (releases are cut from it; main/tags carry the releases)
Latest tag v0.1.0-rc6 (GitHub prerelease) - prior release candidates remain published
License Apache-2.0
Spec versions village API 0.7.0 · PublishRequest 0.7.0 · peasant local API 0.5.0 · types 0.4.0 (see versions.go)
Consumers
Consumer Language How it pins / uses the contract
peasant (Go backend + web) Go go.mod requires github.com/peasant-labs/schema@v0.1.0-rc5; produces SessionDetailPayload, imports the enums, mirrors AllLicenses in its SQLite CHECKs.
village (Go backend) Go backend/go.mod requires @v0.1.0-rc5; serves GET /openapi.json from VillageAPISpecJSON() and enforces inbound publishes via ValidatePublishRequest (both read the embedded spec, so served ≡ enforced).
TypeScript consumers (@peasant-labs/schema) TypeScript npm install @peasant-labs/schema (published to npm from typescript/, version tracking the module release tag) for generated named types, Zod schemas, schema-owned fixtures, and type-only Local/Village paths and operations contracts. It provides no transport client. @peasant-labs/types is deprecated and must not receive new contract definitions.

Both consumers currently pin rc5. Because the module is normal go get-pinned, each consumer moves independently, so they can briefly sit on different tags between re-pins; a re-pin is a one-line go.mod change plus go mod tidy.


What's in the contract

The Go source (all package schema in the repo root) is grouped by surface. Every identifier and enum below is a wire type: a JSON-tagged struct or a closed-set string newtype with IsValid() / String() / a JSONSchema() exposer and an All... canonical list.

Surface File(s) Representative types
Local dashboard / session-detail wire local_api.go SessionDetailPayload, TurnDetail, ToolCallDetail, SessionSummary, SessionScorecard, ChildSessionRef, DashboardPayload, TrendsPayload, QualityPayload, project-familiarity payloads, the WebSocket envelope (ClientMessage / ServerMessage, MessageType, ChannelTopic, ChannelSubscription), CreateAnnotationRequest/Response
Session metadata & git metadata.go UnifiedMetadata, RedactionInfo, TimestampInfo, SourceInfo, CommitInfo, GitContext, ProjectContext, SessionStats, SubagentRef, DiagnosticsInfo; the MetadataSchemaVersion constant
Content layer content.go, identity.go SessionEntry (1:1 with an indexed transcript entry), SessionIdentity
Publish envelope publish.go, publish_validate.go PublishRequest, PublishResponse, ModelInfo; the annotation push wire (AnnotationPushItem / Request / Response), SchemaVersionResponse; ValidatePublishRequest
Pull envelope pull.go TranscriptID, PullTranscriptInfo, PullListResponse, PullAnnotation
Push content envelope push_content.go TranscriptContent (self-describing, versioned blob body), ContractVersion / PushContractVersion, ContentKind
Map / Review REST map_api.go MapGraphPayload, MapNode, MapEdge, ActivityEdge, EdgeViolation, MapNodeDetailPayload, TaskSummary, CommitRef, SessionAssociation, RewrittenCommit, TimelineSessionRef, ProjectResolutionPayload, ProjectTasksPayload, ProjectSummary, ReviewListPayload, ChangeSummary, ChangeDetailPayload, ChangeDiffPayload, FrictionCluster, FileChange, DiffHunk
Search REST search_api.go SearchPayload, SearchResult
Quality metrics quality.go QualityMetrics, QualitySession (session stats + derived quality/cost signals)
Annotations annotation.go, annotation_enums.go, annotation_manifest.go, annotation_registry.go, annotation_validate.go AnnotationSummary, AnnotationTypeSummary, AnnotatorSummary, ValueDomain, Provenance, TaxonomyNode, batch request/response types; the enums AnnotatorKind, AnnotationStatus, TargetKind, ScaleKind, ValueDomainKind, AnnotationDatatype, TypeOrigin
Identifiers & enums types.go Validated newtypes SessionID, ModelID, ProjectHash, HostSlug (+ TranscriptID in pull.go); closed enums Role, EntryType, ToolCallKind, StopReason, SessionOutcome, SourceFormat, Visibility, License, and Harness (re-exported from bestiary)
Auth & commands auth.go, command.go ExchangeCodeRequest/Response, CLILoginQuery; BuiltinCommand + IsClaudeBuiltinCommand
Redaction fixtures redactions.go RedactionInfo staleness helpers, RedactionFixtureLevel, the RedactionExamples corpus, LoadRedactionExamples (the redaction engine stays in peasant; this module carries only the metadata type and the fixture corpus)
Embedded specs & fixtures specs.go, contract_embeds.go, fixtures.go VillageAPISpecJSON(), PublishRequestSchemaJSON(), EvalSchemaJSON, ContractCorpusFS, and the embedded YAML/JSON fixture corpora
The session-detail payload (the central object)

SessionDetailPayload is the object every producer builds and every renderer consumes. It travels two ways:

  • On peasant's local session_detail WebSocket channel, and
  • Wrapped in a TranscriptContent envelope as the versioned peasant push wire body (replacing raw provider JSONL with a normalized, self-describing blob).

It carries the session header (Harness, timing, token totals), the ordered []TurnDetail (each with its []ToolCallDetail, ACP-aligned enrichment, and optional thinking / stop-reason / token fields), an optional SessionScorecard, and the resolved SessionOutcome.

Its composition ([] = has-many; a * pointer = optional):

classDiagram
    class SessionDetailPayload {
        Harness harness
        int totalTokens
        int turnCount
        int toolCallCount
        SessionOutcome outcome
    }
    class TurnDetail {
        int index
        Role role
        string content
        EntryType entryType
        StopReason stopReason
    }
    class ToolCallDetail {
        string name
        string arguments
        string result
        ToolCallKind toolKind
    }
    class ChildSessionRef {
        string id
        string project
    }
    class SessionScorecard {
        float specQualityScore
        float m2TokenOutcomeRatio
        int m4ConsecutiveErrorMax
    }
    SessionDetailPayload "1" *-- "many" TurnDetail : turns
    SessionDetailPayload "1" *-- "many" ChildSessionRef : childSessions
    SessionDetailPayload "1" o-- "0..1" SessionScorecard : scorecard
    TurnDetail "1" *-- "many" ToolCallDetail : toolCalls

The enum field types (Role, EntryType, StopReason, ToolCallKind, SessionOutcome, FileChangeStatus, and DiffLineKind) are schema newtypes; Harness is re-exported from bestiary. File-change statuses retain the Git wire tokens M, A, D, and R; diff-line kinds retain context, add, and del.

A trimmed excerpt of the top-level shape (local_api.go):

type SessionDetailPayload struct {
    Harness       Harness           `json:"harness"`
    Turns         []TurnDetail      `json:"turns"`
    ChildSessions []ChildSessionRef `json:"childSessions,omitempty"`
    Outcome       SessionOutcome    `json:"outcome,omitempty"`
    Scorecard     *SessionScorecard `json:"scorecard,omitempty"`
    // + session header: timing, token totals, turn/tool-call counts
}
The License surface

The content-license menu is owned by this contract (types.go), so producers, enforcers, and UIs all read one closed set:

Symbol Value / behaviour
License Closed string newtype
LicenseCC0 / LicenseCCBY / LicenseCCBYSA CC0-1.0 · CC-BY-4.0 · CC-BY-SA-4.0
AllLicenses The canonical ordered menu
License.IsValid() Reports membership in the menu
LicenseMenu() The menu as a comma-separated string for help text / errors (derived from AllLicenses, never a literal)

The publish/pull wire carries it as an optional license field (PublishRequest, PullTranscriptInfo); the generated JSON-Schema's license enum is derived from AllLicenses, so widening the menu flows through the schema automatically. village enforces it; peasant mirrors it in two SQLite CHECK constraints.

Generated OpenAPI specs (generated/)

go run ./cmd/schema-gen renders the Go source into OpenAPI 3.1 specs, committed as byte-frozen goldens (JSON + YAML) plus the standalone PublishRequest JSON-Schema (draft 2020-12). Three OpenAPI spec families and one standalone JSON Schema are emitted from the builders in openapi/:

Spec family Builder Covers Current version
village API BuildVillageAPISpec publish / pull / annotations / auth / schema-version 0.7.0
PublishRequest JSON Schema BuildPublishRequestSchema the standalone publish request validator schema 0.7.0
peasant local API BuildPeasantLocalAPISpec the local dashboard REST + Map / Review / Search surface 0.5.0
types BuildTypesSpec the foundational shared domain-type catalog 0.4.0

The current specs are read back into the binary via //go:embed generated. Two version-aware accessors expose the bytes so consumers follow the go.mod pin without vendoring their own copy:

  • VillageAPISpecJSON(): the current village API spec (village serves it as GET /openapi.json).
  • PublishRequestSchemaJSON(): the current PublishRequest JSON-Schema (the single byte-source ValidatePublishRequest compiles and the village enforces through).

Both derive their filename from the version constant in versions.go, so a version bump re-points them in lockstep: consumers need no change.


Versioned specs & frozen goldens

Released spec versions are immutable. The rule is bump, don't mutate: you never add or change surface on an already-shipped spec in place. You bump the relevant version constant in versions.go (minor for additive surface, major for a breaking change), regenerate, and commit: the new version is emitted while every prior version stays byte-frozen exactly as shipped.

flowchart TD
    change["a surface change<br/>(additive or breaking)"]
    bump["bump the version constant<br/>versions.go (minor / major)"]
    regen["go run ./cmd/schema-gen"]
    current["new current spec in generated/<br/>codegen-freshness gate"]
    frozen["every prior version byte-frozen<br/>retired-versions immutability guard<br/>(retired_specs_test.go)"]
    change --> bump --> regen
    regen --> current
    regen --> frozen

Two gates enforce this (both run in make check via cmd/schema-gen):

  • Codegen-freshness gate: the committed artifacts under generated/ (and the generated redaction fixture) must be byte-identical to what the generator emits from the Go source. A stale or hand-edited current spec fails the build; the fix is go run ./cmd/schema-gen + commit. (make freshness is the git-diff backstop for the same invariant.)
  • Retired-versions immutability guard (cmd/schema-gen/retired_specs_test.go): every retired version is content-hash-pinned (sha256 of its committed bytes) in a registry and asserted present-and-frozen. It fails loudly on both an in-place edit (hash mismatch) and a deletion (missing file): the exact gap the freshness gate can't see, because freshness only diffs versions the generator still emits. A version is moved into the registry at the moment it is frozen (the same change that bumps the live constant past it), so there is never a window where a retired spec is mutable-and-unguarded. A permanent negative-control self-test proves the guard actually fires.

Currently frozen (retired) goldens: village API 0.1.0 / 0.2.0 / 0.3.0 / 0.4.0 / 0.5.0 / 0.6.0, PublishRequest schema 0.2.0 / 0.3.0 / 0.4.0 / 0.5.0 / 0.6.0, peasant local API 0.1.0 / 0.2.0 / 0.3.0 / 0.4.0, and types 0.1.0 / 0.2.0 / 0.3.0. The still-generated current versions (village API 0.7.0, PublishRequest 0.7.0, peasant local API 0.5.0, types 0.4.0) live under the freshness gate instead.

The versioning procedure itself is codified in the versions.go doc comments, the "Regeneration & gates" section of CONTRIBUTING.md, and the release ceremony in docs/release-runbook.md; there is no separate versioning document.


How pinning works

Because the contract is a normal published, tagged Go module, a consumer pins one version:

go get github.com/peasant-labs/schema@v0.1.0-rc6

That single pin replaces the old model of vendoring an in-tree copy of the types. It also structurally retires the cross-repo cost that model carried: there is no vendorHash / private-module-auth tax to fold first-party schema source into a consumer's build. The Nix buildGoModule vendorHash covers only the third-party module graph, and a no-local-replace rule (proven by TestVendorHashStableOnFirstPartyEdit) forbids the local-path replace directive that would fold first-party source into the vendor graph, so a schema edit can never drift a consumer's hash.

The ceremony (in effect): a contract change lands as its own schema-repo PR + tag first, and only then do the consumer PRs that re-pin to the new tag land. The wire is defined once, published once, and adopted deliberately. Never edited in two repos at once. Because the village both serves and enforces from the same pinned module bytes, its served spec and its enforcement can't drift from each other or from the tag.


Contract gates

Gate Tool Consequence
OpenAPI breaking diff oasdiff breaking --fail-on ERR Hard - fails on an ERR-level breaking change vs the prior golden.
OpenAPI lint vacuum lint -r .vacuum.yaml Hard - fails on error-severity findings in the generated specs.
Exported-Go-API diff go-apidiff Advisory while pre-1.0 - an incompatible exported-Go-API change surfaces a workflow warning + a single sticky PR comment listing the changed/removed symbols (and any additive changes), then exits success. Detection is unchanged; only the consequence is. An unrecognizable diff-tool output still fails closed.

The advisory posting runs in a write-scoped companion workflow (go-apidiff-comment.yml) so the read-only Tests workflow can be reused as a gate. Alongside these, make check runs the codegen-freshness gate, the retired-versions immutability guard, the leaf-audit, the vendorHash-stability proof, and the synthetic-break tests that prove the oasdiff / go-apidiff gates actually fire.

TypeScript bindings

The typescript/ directory is the source of the @peasant-labs/schema package, first shipped with the module's v0.1.0-rc6 tag. It mirrors the Go contract architecture:

  • the package root is the canonical Types 0.4 projection of the complete public Go wire/domain catalog, including Zod runtime schemas and Go-shaped closed sets and guards;
  • /local-api and /village-api retain type-only OpenAPI paths and operations namespaces for consumers that need endpoint request/response contracts; shared payloads resolve to the canonical root identities;
  • /types remains a deprecated compatibility re-export of the canonical root;
  • no HTTP or WebSocket transport client SDK is generated;
  • /testcase owns generic validation behavior and a strict YAML decoder;
  • /fixtures/quality and /fixtures/timeline provide typed access to generated data from the same canonical YAML corpora consumed by Go.

The Go source and generated OpenAPI catalogs remain authoritative. Hey API's Zod plugin derives root TypeScript definitions and runtime schemas without enabling its SDK/client plugins. openapi-typescript derives the type-only Local/Village operation contracts. Canonical shared payload names preserve their root identity.

The package is published to npm as @peasant-labs/schema. The committed typescript/package.json stays 0.0.0-development + private: true as the local safety; the release pipeline (release.yml's npm-publish job, behind the same guard → nix-vendor-hash → contract-gates gates as the GitHub Release, and authenticated via npm Trusted Publishing / OIDC rather than a stored token) stamps the real version from the tag and publishes at release time. The published version follows the schema module release tag, not the individual Village, local, or types document versions: an -rcN tag publishes under the npm dist-tag next, a final vX.Y.Z under latest. See docs/release-runbook.md for the npm publication ceremony (the one-time GitHub environment + npm Trusted Publisher setup) and troubleshooting. The old @peasant-labs/types package is deprecated rather than migrated: do not add new handwritten wire interfaces there.


Develop, build, regenerate

Everything is provisioned through Nix: the flake devShell is the dev-dependency manifest (Go has no dev/prod dependency split). You do not install Go or any tool globally.

Prerequisites: Nix with flakes enabled, and (recommended) direnv with nix-direnv.

# Option A: direnv (recommended)
cd <this-worktree>
direnv allow          # loads the flake devShell on cd; the committed .envrc is `use flake .`

# Option B: nix develop
nix develop           # drops you into the Go 1.26 dev shell

Inside the shell (go, gopls, golangci-lint, oasdiff, go-apidiff, vacuum, actionlint, Node, pnpm, ... on PATH):

pnpm --dir typescript install --frozen-lockfile --ignore-scripts # install the exact locked generator/toolchain
make check                            # Go + TypeScript generation, tests, and package gates
                                      #   (incl. leaf-audit, freshness, immutability, and the synthetic-break tests)
make gates BASE_REF=origin/develop    # breaking-change gates vs a base ref (oasdiff + go-apidiff + vacuum)
make schema                           # regenerate OpenAPI/Redoc and TypeScript contract outputs
nix build                             # hermetic buildGoModule (cmd/schema-gen + cmd/release-guard)

The Go test packages remain runnable with a bare Go toolchain. Full make check also needs the locked Node dependencies because freshness regenerates the TypeScript package. If they are absent, the gate names the exact pnpm install command. After any change to the Go schema source, regenerate and commit both generated/ and the generated TypeScript sources; freshness enforces byte-identity.

The leaf rule

The module's go.mod direct require set must stay a subset of the allowed contract dependencies, enforced by TestLeafAudit_GoModRequiresAreAllowed:

github.com/dayvidpham/bestiary
github.com/google/go-github/v88          # runtime seam for cmd/release-guard's GitHub API, not a dev tool
github.com/santhosh-tekuri/jsonschema/v5
github.com/swaggest/jsonschema-go
github.com/swaggest/openapi-go
golang.org/x/crypto
gopkg.in/yaml.v3

Dev/CI tools (oasdiff, go-apidiff, vacuum, linters) live in the flake devTools, never in go.mod. See CONTRIBUTING.md for the leaf-audit and no-local-replace (vendorHash-stability) rules and the go.work workflow for co-developing consumers against a local worktree before a version is cut.


Testing

The suite keeps the contract honest rather than exercising a runtime: the committed specs stay byte-identical to the Go source, released spec versions stay frozen, a breaking wire change is caught before it ships, and the module stays a dependency leaf. Three layers do this: the contract gates (codegen freshness, retired-version immutability, the oasdiff / vacuum / go-apidiff gates, the leaf-purity audit, and the vendor-hash guard, each with a real test plus a synthetic-break meta-gate that proves it fires); unit tests alongside every source (closed enums, JSON shapes, validator behaviour); and typed fixture families under testdata/. The whole suite runs with a bare go toolchain, the tool-gated tests skipping when oasdiff / go-apidiff / vacuum are absent.

Case corpora live in fixtures, not inline. When a test drives a set of cases, the cases live in a testdata/*.yaml corpus loaded through one idiom: a typed struct with yaml: tags, a //go:embed of the file, a yaml.Unmarshal, a small Load...Fixtures loader, and a row-count guard that fails loudly on an empty or mis-keyed corpus (so an iterating test can never pass on no cases). New corpora adopt the canonical testcase standard (a generic Case[I, E] / Corpus[I, E] with closed-set classification and provenance + mutation metadata, a pure loader, and its *testing.T seams split into testcase/assert), so each case also records why it exists and the single change it embodies. Fixtures that split into heterogeneous behavioral arms use the segmented form: a typed struct of named per-arm Corpus fields, each guarded by RequireMin + RequireValid. A contract change then updates one corpus instead of N inline tables, and a new test follows this by default. The corpora sit under testdata/ (annotations, contract, publish, pull, quality, session-detail, sync), internal/release/testdata/ (grammar, workflow), and cmd/release-guard/testdata/github.

See TESTING.md for the full strategy and the test behind each gate.


Releasing

Releases are cut by merging a PR titled release(vX.Y.Z[-rcN]): <summary> into develop. Never by hand-tagging. The title/tag grammar and final-release guard live once in internal/release, exposed through cmd/release-guard, the single canonical release-gating tool (built on go-github; it also serves peasant via a per-repo .github/release-guard.policy.yml). On merge, the release workflow mints the annotated tag and publishes a GitHub Release (prerelease for -rcN) with the generated/ OpenAPI specs attached as assets.

The maintainer-approval assertion in the release PR is deferred to the public flip (a single active maintainer plus GitHub's no-self-approval rule make it unsatisfiable today); the release-guard check-approval guard code stays live and tested, re-enabled alongside branch protection at the flip. The full operator guide (secrets, the GitHub App, the ceremony, and the public-flip checklist) is in docs/release-runbook.md.


Repository layout

Path What
*.go (root, package schema) The contract: domain + wire types, enums, content-hashing, metadata, publish/pull/push envelopes, annotations, the embedded-spec accessors
versions.go Single source of truth for the versioned-spec semvers
openapi/ OpenAPI 3.1 spec builders (BuildVillageAPISpec, BuildPeasantLocalAPISpec, BuildTypesSpec)
generated/ Committed OpenAPI spec goldens (JSON + YAML) + the PublishRequest JSON-Schema - gate-checked; regenerate with go run ./cmd/schema-gen
typescript/ Unpublished @peasant-labs/schema package: generated named wire types, testcase helpers, typed fixtures, and package gates
external/, testdata/, fixtures.go Vendored external schemas + typed test fixtures
cmd/schema-gen/ Regenerates generated/; hosts the freshness / immutability / surface gate tests
cmd/release-guard/ + internal/release/ The PR-title/tag grammar + release-gating CLI
docs/release-runbook.md · CONTRIBUTING.md · CHANGELOG.md Operator + contributor references

License

Apache-2.0, see LICENSE.

Documentation

Index

Constants

View Source
const (
	HarnessClaudeCode  = bestiary.HarnessClaudeCode
	HarnessGeminiCLI   = bestiary.HarnessGeminiCLI
	HarnessCodex       = bestiary.HarnessCodex
	HarnessOpenCode    = bestiary.HarnessOpenCode
	HarnessCursor      = bestiary.HarnessCursor
	HarnessAntigravity = bestiary.HarnessAntigravity
)
View Source
const (
	// VillageAPIVersion is the info.version of the Village API spec. Bumped to
	// 0.2.0 when the /api/v1/pull surface was added (additive = minor bump).
	// Bumped to 0.3.0 (rc2 #118) when model + model.harness/model.model became
	// required — a tightening of the publish contract (selective required arrays on
	// operation-specific publish request + SchemaModelInfo). Bumped to 0.4.0 when
	// PublishRequest.License + PullTranscriptInfo.License were added (additive
	// optional field = minor bump). Bumped to 0.5.0 when the pull skip-gate surface
	// (POST /api/v1/pull/transcripts/skip-gate) was added (additive = minor bump).
	// Bumped to 0.6.0 when shared operation components adopted exact canonical
	// Types schemas and the stricter publish HTTP body gained a distinct component
	// identity instead of shadowing the canonical PublishRequest.
	// Bumped to 0.7.0 when TargetKind gained the file_version and association
	// members and AnnotationSummary gained TargetFilePath/TargetContentHash and
	// TargetAssociationID;
	// harmonizeSharedTypeComponents propagates both into this spec's embedded
	// annotation components (additive = minor bump).
	// Each prior version's generated goldens are retained byte-frozen under the
	// retired-spec immutability guard.
	VillageAPIVersion = "0.7.0"
	// PeasantLocalAPIVersion is the info.version of the local dashboard API spec.
	// Bumped to 0.2.0 when the Map/Review/Search surface was added (8 additive ops
	// + FrictionCluster = minor bump). Bumped to 0.3.0 when the project Git
	// timeline gained normalized session identities and authoritative many-to-many
	// commit bindings. Bumped to 0.4.0 when file-change statuses and diff-line
	// kinds became named closed sets while retaining their existing JSON tokens.
	// Bumped to 0.5.0 when the git+session timeline and insight-first code map
	// surface landed: durable atomic session-to-commit associations, ghost/rewrite
	// mapping, the mechanical insight envelope, node-grain
	// read-state/comprehension signals, and TaskSummary.ReadFiles (all
	// additive).
	// Prior versions stay byte-frozen.
	PeasantLocalAPIVersion = "0.5.0"
	// TypesVersion is the info.version of the types spec (the foundational shared
	// domain types catalog; formerly "shared-types").
	// Bumped to 0.2.0 when the catalog became the comprehensive canonical
	// cross-language contract surface instead of a small set of seed types.
	// Bumped to 0.3.0 when the map/review diff string fields became named closed
	// sets with generated runtime inventories and predicates.
	// Bumped to 0.4.0 when the Local API 0.5.0 surface's new catalog types
	// (SessionAssociation, RewrittenCommit, SessionInsight and their closed
	// sets) and the widened TargetKind landed (additive = minor bump).
	TypesVersion = "0.4.0"
)

Versioned-spec info.version values. These are the SINGLE SOURCE OF TRUTH for each versioned OpenAPI spec's semantic version: they feed WithVersion(...) in the openapi.Build*Spec functions (re-exported there as openapi.VillageAPIVersion etc.), the generated artifact filenames, AND the version-aware accessors in this package (e.g. VillageAPISpecJSON). A version bump is a one-line edit here.

They live in the contract root (not the openapi sub-package) so the embedded-spec accessors below can key off them without an import cycle (openapi imports this package, so this package cannot import openapi).

Bump the relevant one when its API surface changes (minor for additive surface, major for breaking changes). Retired versions stay byte-frozen under the retired-spec immutability guard; new surface goes on a new version.

View Source
const MetadataSchemaVersion = 9

MetadataSchemaVersion is the schema version written by this build of the ingest tool. v1: initial schema v2: SQLite persistence layer, store integration v3: transcript filename {sessionId}--transcript.{ext} (was {unixMillis}--),

timestamp extraction scans all lines (was first/last line only)

v4: GitContext.Commits field added (session-to-commit linking) v5: Claude indexer fixes — system content extraction, tool_result tool_use_id linking v6: ContentHash, MetadataHash, RedactionInfo — deferred redaction model v7: CWD field — real working directory for context-aware slug redaction v8: DerivedAt field — Unix ms when metadata.json was derived from DB (DB as SOT) v9: harness key unification — UnifiedMetadata.ModelHarness re-keyed json:"modelHarness"

-> json:"harness" (emit-side flip). The bump forces the DIFF stage to
re-classify existing on-disk sessions as Updated so the stale "modelHarness" key
self-heals (re-extract + rewrite) on next ingest; UnmarshalJSON still accepts the
legacy key on pre-v9 files in the meantime.

Variables

View Source
var AllAnnotationAxes = []AnnotationAxis{
	AxisType,
	AxisSession,
	AxisProject,
}

AllAnnotationAxes is the canonical list of annotation subscription axes.

AllAnnotationDatatypes is the canonical list of all known annotation datatypes.

AllAnnotationPushStatuses is the canonical list of annotation push outcomes.

AllAnnotationStatuses is the canonical list of all known annotation statuses.

AllAnnotatorKinds is the canonical list of all known annotator kinds.

AllAssociationConclusions is the canonical list of association conclusions.

AllAssociationEvidenceKinds is the canonical list and order of atomic association evidence observations.

AllChangeBindings is the canonical list of session-to-change bindings.

AllChannelTopics is the canonical list of subscribable WebSocket topics.

AllClaudeBuiltinCmds is the canonical list of all known Claude Code built-in commands.

AllConfidences is the canonical list of confidence levels.

AllContentKinds is the canonical list of transcript content envelope kinds.

AllDecayLevels is the canonical list of project familiarity decay levels.

AllDiffLineKinds is the canonical inventory of unified-diff line kinds.

AllEdgeViolationKinds is the canonical list of map structure violations.

AllEntryTypes is the canonical list of all known entry types.

AllFileChangeStatuses is the canonical inventory of file change statuses.

AllHarnesses is the canonical list of harnesses that peasant supports for ingestion.

AllInsightKinds is the canonical list of insight kinds.

AllInsightProvenances is the canonical list of insight provenances.

AllInteractionTypes is the canonical list of project familiarity interactions.

AllLicenses is the canonical menu of known licenses.

AllMapNodeKinds is the canonical list of map node classifications.

AllMessageTypes is the canonical list of WebSocket message discriminators.

AllOutcomes is the canonical list of all known session outcomes.

AllReadAttributionStates is the canonical list of read attribution states.

AllReadStateGrades is the canonical ordered list of read-state grades, ascending: none < viewed < reviewed < reviewed_in_detail.

AllRewriteMethods is the canonical list of rewrite resolution methods.

AllRewriteResolutions is the canonical list of rewrite resolutions.

AllRoles is the canonical list of all known roles.

AllScaleKinds is the canonical list of all known scale kinds.

AllSourceFormats is the canonical list of transcript source formats.

AllStopReasons is the canonical list of all known stop reasons.

AllTargetKinds is the canonical list of all known target kinds.

AllToolCallKinds is the canonical list of all known tool call kinds.

AllTypeOrigins is the canonical list of all known type origins.

View Source
var AllValueDomainKinds = []ValueDomainKind{
	DomainEnumerated, DomainDescribed,
}

AllValueDomainKinds is the canonical list of all known value domain kinds.

AllVisibilities is the canonical list of all known visibility levels.

View Source
var AnnotationsYAML []byte

AnnotationsYAML contains the raw YAML content for annotation test fixtures.

View Source
var ContractCorpusFS embed.FS

ContractCorpusFS is the push/pull back-compat golden corpus tree (testdata/contract/**): the current contract shape plus the retained legacy shapes (legacy-metadata-field / legacy-provider-keyed / legacy-raw-jsonl). Exported as an embed.FS so consumers (peasant internal/push back-compat round-trip tests) enumerate and read the corpus through the contract leaf rather than a cross-module filesystem path. Walk it from the "testdata/contract" root (e.g. fs.ReadDir(schema.ContractCorpusFS, "testdata/contract")).

View Source
var ErrCycleDetected = errors.New("annotation type dependency cycle detected")

ErrCycleDetected is returned when adding a dependency would create a cycle in the annotation_type_deps graph (V14: depth limit 20).

View Source
var ErrInvalidValue = errors.New("invalid annotation value")

ErrInvalidValue is returned when a value is not permissible for an annotation domain. Callers should wrap this error with fmt.Errorf("%w: ...", ErrInvalidValue) for context.

View Source
var ErrTypeNotFound = errors.New("annotation type not found")

ErrTypeNotFound is returned when a requested annotation type does not exist in the registry.

View Source
var EvalSchemaJSON []byte

EvalSchemaJSON is the vendored EEE (eval) JSON Schema (external/eee/eval.schema.json) — the contract that peasant's `export` surface validates its evaluation payloads against. Exported so consumers (peasant internal/export conformance + drift tests) read the schema through the contract leaf instead of a cross-module filesystem path. Provenance and re-vendoring policy: external/eee/PROVENANCE.md.

View Source
var PublishVerdictsYAML []byte

PublishVerdictsYAML contains the shared publish schema verdict corpus.

View Source
var PullManifestExampleJSON []byte

PullManifestExampleJSON is the golden one-complete-PullManifest example (round-trip shape-pin source).

View Source
var PullRefsYAML []byte

PullRefsYAML contains the raw YAML content for transcript-reference parse fixtures (internal/pull.ParseTranscriptRef).

View Source
var PullStatusesYAML []byte

PullStatusesYAML contains the raw YAML content for PullStatus<->wire mappings.

View Source
var QualitySessionsYAML []byte

QualitySessionsYAML contains the raw YAML content for mock quality sessions.

ReadStateGradeRegistrySeedPermissibleValues is AllReadStateGrades with the unstated zero grade "none" removed, in the same ascending order: the registered set the peasant-side read-state registry seed's PermissibleValues must byte-equal. TestReadStateGradeRegistrySeedCrossCheck pins this module's half of the cross-check; the peasant-side registry seed test pins the other half against this exported value.

View Source
var RedactionExamples = []RedactionExample{
	{
		Name:                "aws_access_key",
		RuleID:              "aws_access_key",
		Category:            "secrets",
		Level:               RedactionLevelMinimal,
		OriginalText:        "AKIAIOSFODNN7EXAMPLE",
		RedactedReplacement: "<AWS_ACCESS_KEY>",
		Confidence:          98,
		LineNumber:          142,
		Description:         "AWS access key ID (pkg/redact rule: aws_access_key)",
	},
	{
		Name:                "email_address",
		RuleID:              "email",
		Category:            "pii",
		Level:               RedactionLevelStandard,
		OriginalText:        "vitor.eduardo@company.com",
		RedactedReplacement: "<EMAIL>",
		Confidence:          94,
		LineNumber:          587,
		Description:         "Email address (pkg/redact rule: email)",
	},
	{
		Name:                "home_directory",
		RuleID:              "unix_home_path",
		Category:            "paths",
		Level:               RedactionLevelMinimal,
		OriginalText:        "/Users/acme-dev/Projects/internal-api",
		RedactedReplacement: "/Users/<USER>/Projects/internal-api",
		Confidence:          72,
		LineNumber:          23,
		Description:         "Unix home directory path with username (pkg/redact rule: unix_home_path)",
	},
	{
		Name:                "github_token",
		RuleID:              "github_pat",
		Category:            "secrets",
		Level:               RedactionLevelMinimal,
		OriginalText:        "ghp_xK9mN2pL4qR7sT8vW1yZ3aB5cD6eF0gH12ab",
		RedactedReplacement: "<GITHUB_PAT>",
		Confidence:          96,
		LineNumber:          310,
		Description:         "GitHub personal access token (pkg/redact rule: github_pat)",
	},
	{
		Name:                "git_remote_url",
		RuleID:              "git_remote_https",
		Category:            "project",
		Level:               RedactionLevelMaximum,
		OriginalText:        "https://github.com/acme-corp/internal-api",
		RedactedReplacement: "<PROJECT_URL>",
		Confidence:          61,
		LineNumber:          445,
		Description:         "Git remote URL exposing project identity (pkg/redact rule: git_remote_https)",
	},
	{
		Name:                "phone_number",
		RuleID:              "phone_us",
		Category:            "pii",
		Level:               RedactionLevelStandard,
		OriginalText:        "+1-555-867-5309",
		RedactedReplacement: "<PHONE>",
		Confidence:          89,
		LineNumber:          712,
		Description:         "US phone number (pkg/redact rule: phone_us)",
	},
	{
		Name:                "database_connection",
		RuleID:              "basic_auth_uri",
		Category:            "secrets",
		Level:               RedactionLevelMinimal,
		OriginalText:        "postgresql://admin:s3cretPass99@db.prod.internal:5432/maindb",
		RedactedReplacement: "postgresql://<BASIC_AUTH_URI>@db.prod.internal:5432/maindb",
		Confidence:          99,
		LineNumber:          18,
		Description:         "URL with embedded basic-auth credentials (pkg/redact rule: basic_auth_uri)",
	},
	{
		Name:                "workspace_path",
		RuleID:              "unix_home_path",
		Category:            "paths",
		Level:               RedactionLevelMinimal,
		OriginalText:        "/home/deploy/apps/acme-billing-service",
		RedactedReplacement: "/home/<USER>/apps/acme-billing-service",
		Confidence:          65,
		LineNumber:          891,
		Description:         "Unix home directory path with username (pkg/redact rule: unix_home_path)",
	},
	{
		Name:                "ip_address",
		RuleID:              "ip_address",
		Category:            "pii",
		Level:               RedactionLevelStandard,
		OriginalText:        "192.168.1.42",
		RedactedReplacement: "<IP_ADDRESS>",
		Confidence:          85,
		LineNumber:          156,
		Description:         "IPv4 address (pkg/redact rule: ip_address)",
	},
	{
		Name:                "slack_webhook",
		RuleID:              "slack_webhook_url",
		Category:            "secrets",
		Level:               RedactionLevelMinimal,
		OriginalText:        "https://hooks.slack.com/services/T024BE7LD/B0DAF2RC3/bJTqg8NS27FYm2pQL0jAiE",
		RedactedReplacement: "<SLACK_WEBHOOK_URL>",
		Confidence:          58,
		LineNumber:          234,
		Description:         "Slack incoming webhook URL (pkg/redact rule: slack_webhook_url)",
	},
	{
		Name:                "stripe_secret",
		RuleID:              "stripe_key",
		Category:            "secrets",
		Level:               RedactionLevelMinimal,
		OriginalText:        "sk_live_4eC39HqLyjWDarjtT1zdp7dc",
		RedactedReplacement: "<STRIPE_KEY>",
		Confidence:          92,
		LineNumber:          67,
		Description:         "Stripe API secret key (pkg/redact rule: stripe_key)",
	},
}

RedactionExamples is the canonical redaction example corpus — the CURRENT session-detail mock cases only (NOT the full pkg/redact corpus). Every RedactedReplacement here is the verbatim output of the real pkg/redact engine run on OriginalText at Level; the peasant conformance test (pkg/redact/redactconform_test.go) enforces that and fails on any drift.

View Source
var RedactionsYAML []byte

RedactionsYAML contains the GENERATED redaction example corpus (testdata/session-detail/redactions.yaml). It is produced by `go run ./cmd/schema-gen` from RedactionExamples (see redactions.go) and is the single source of truth consumed by peasant's behavioural conformance test (pkg/redact) and the web mock codegen. Regenerate + commit on any change to RedactionExamples; the leaf freshness gate enforces byte-identity.

View Source
var SessionsYAML []byte

SessionsYAML contains the raw YAML content for mock sessions.

View Source
var TimelineYAML []byte

TimelineYAML contains project timeline validation cases.

Functions

func ComputeAnnotationHash

func ComputeAnnotationHash(
	annotationTypeID string,
	annotatorID string,
	value string,
	sessionID *string,
	entryIndex *int,
	endIndex *int,
	confidence *float64,
	reason *string,
	provenance *Provenance,
) string

ComputeAnnotationHash computes a SHA3-256 content hash over the core fields of an annotation for deduplication purposes. The hash is deterministic: the same annotation content always produces the same hex string.

Parameters mirror the annotation's content-bearing fields. Target-specific fields (sessionID, entryIndex, endIndex) are optional and contribute to the hash only when set (ensuring session-level and entry-level annotations of the same type/value/annotator produce different hashes).

func ComputeManifestDigest

func ComputeManifestDigest(hashes []string) string

ComputeManifestDigest computes a deterministic SHA3-256 digest over a SET of content-hashes. The result depends only on the underlying set, not on input order or duplicate multiplicity: the hashes are sorted and de-duplicated before hashing. Two callers observing the same logical set always produce the same digest, which is what makes the no-op short-circuit correct across machines.

The empty set hashes to a fixed, well-defined value (the digest of no input), so two empty manifests compare equal.

func ComputeMetadataHash

func ComputeMetadataHash(meta *UnifiedMetadata) string

ComputeMetadataHash computes the SHA3-256 hash of metadata fields, excluding ContentHash, MetadataHash, and Redaction to avoid circular dependency. Changing any content-bearing metadata field produces a different hash.

func ComputeTranscriptHash

func ComputeTranscriptHash(transcriptBytes []byte) string

ComputeTranscriptHash computes the SHA3-256 hash of raw transcript bytes. Used to detect content changes for incremental re-processing and stale redaction detection.

func HarnessDisplayName

func HarnessDisplayName(h Harness) string

HarnessDisplayName returns the human-readable name for a harness.

func HarnessJSONSchema

func HarnessJSONSchema() jsonschema.Schema

HarnessJSONSchema returns the JSON Schema for the Harness type. This is a standalone function because Harness is a type alias for bestiary.Harness, and Go does not allow methods on imported types.

func IsClaudeBuiltinCommand

func IsClaudeBuiltinCommand(name string) bool

IsClaudeBuiltinCommand reports whether name (with any leading slash stripped) matches a known Claude Code built-in command. Skill names like "aura:epoch" or "user-defined-command" will return false.

Examples:

IsClaudeBuiltinCommand("exit")   → true
IsClaudeBuiltinCommand("/exit")  → true
IsClaudeBuiltinCommand("aura:epoch") → false

func LicenseMenu

func LicenseMenu() string

LicenseMenu returns the known license IDs as a comma-separated string, derived from AllLicenses so help text and error messages can't drift from the canonical menu when a license is added.

func PublishRequestSchemaJSON

func PublishRequestSchemaJSON() []byte

PublishRequestSchemaJSON returns the standalone JSON-Schema (draft 2020-12) bytes for the PublishRequest wire format at the CURRENT VillageAPIVersion — the schema extracted from the Village API spec by openapi.BuildPublishRequestSchema and committed under generated/publish-request-<VillageAPIVersion>.schema.json.

This is the SINGLE BYTE-SOURCE the publish-enforce path validates against: schema.ValidatePublishRequest (root publish_validate.go) compiles exactly these bytes, and village's publish handler enforces through it rather than vendoring its own schema copy. Routing both the documented spec and the enforced schema through this one accessor means they can never drift (it retired the hand-maintained validate/schema.json, which had diverged from the generated artifact, and — rc2 #118 — folded the standalone `validate` subpackage into the root schema package).

It is version-aware: the filename is derived from VillageAPIVersion, never a literal, so a version bump in versions.go re-points it in lockstep. The bytes are embedded at compile time, so a miss here is a build/generation bug, not a runtime condition — it panics with an actionable message. The codegen-freshness gate and TestPublishRequestSchemaJSON_MatchesGenerated keep this unreachable in a healthy tree.

func RunPublishVerdicts

func RunPublishVerdicts(t *testing.T, validate func([]byte) error)

RunPublishVerdicts drives a publish-body validator over the ENTIRE shared publish-verdict corpus (testdata/publish/verdicts.yaml), in two passes — first the Acceptances() (schema_accepts:true), then the Rejections() (schema_accepts:false) — asserting each row's expectation with ASSERT-WHERE-PRESENT semantics (FINDING-2a):

  • an accepted row MUST validate with no error;
  • a rejected row MUST error;
  • WHERE a rejected row pins error_contains, the validator message MUST contain that exact (minimal/stable) substring — but rows WITHOUT error_contains are NOT required to carry one (no false-fail on the ~half the corpus that pins only error_category); and
  • EVERY rejected row MUST carry a non-empty error_category (no vacuous reject).

It is the one-call, reusable form of the accept/reject loop every corpus consumer would otherwise open-code, so the corpus stays the SINGLE source of publish-validation cases. Pass the validator under test — e.g. schema.RunPublishVerdicts(t, schema.ValidatePublishRequest) for the root client validator, or a compiled-schema closure for the extracted-schema side.

ERROR-STRING BREADCRUMB (FINDING-2b): the pinned error_contains substrings are coupled to the message text of github.com/santhosh-tekuri/jsonschema/v5, pinned at v5.3.1 (see go.mod). They are kept MINIMAL/stable on purpose — e.g. "value must be one of", "missing properties: 'model'"/'harness'", "does not match pattern". If a future jsonschema/v5 bump changes the wording, the error_contains assertions here (and TestPublishVerdicts_ErrorContainsPinnedStrings) fail loudly so the drift is diagnosable at the dep, not silently tolerated.

NOTE on placement: this helper takes *testing.T, so it necessarily imports "testing". It is isolated in this dedicated file (not the production-logic files) and is consumed only by _test packages (publish_validate_test, openapi); production code never calls it.

func ValidateAnnotationValue

func ValidateAnnotationValue(domain ValueDomain, value string) error

ValidateAnnotationValue checks that value is permissible for the given ValueDomain.

Rules:

  • value must not be empty (regardless of domain kind).
  • For enumerated domains: value must be in PermissibleValues.
  • For described domains: delegates to ValidateDescribedValue (datatype coercion + JSON schema).

Returns nil if valid. Returns an error wrapping ErrInvalidValue otherwise.

func ValidateDescribedValue

func ValidateDescribedValue(domain ValueDomain, value string) error

ValidateDescribedValue validates that value is permissible for the given described ValueDomain. It performs two checks in order:

  1. Datatype coercion: the string value must parse as the declared Datatype before schema validation. This catches "3.7" for an integer field before jsonschema sees it.

  2. JSON-schema validation: the ConstraintSpec is compiled (with caching) and the coerced Go value is validated against it.

Returns nil if valid, or an error wrapping ErrInvalidValue when rejected. Returns a non-ErrInvalidValue error when the ConstraintSpec is malformed JSON.

Callers:

  • ValidateAnnotationValue (delegated for described domains)

Where: annotation_validate.go ValidateDescribedValue.

func ValidatePublishRequest

func ValidatePublishRequest(data []byte) error

ValidatePublishRequest validates a publish-request JSON body against the generated PublishRequest JSON-Schema (the bytes PublishRequestSchemaJSON() returns for the current VillageAPIVersion). A non-nil error means the body is invalid — a type/enum/pattern violation, the rc2 (#118) required model object or its harness/model fields missing (e.g. "missing properties: 'model'"/'harness'), or not valid JSON — and the caller must reject it (the village maps this to HTTP 422). It returns nil for a conforming body, or the compile error if the embedded schema fails to compile on first use.

func ValidateScaleDomainCombo

func ValidateScaleDomainCombo(scale ScaleKind, domain ValueDomainKind) error

ValidateScaleDomainCombo returns an error when the (scale, domain) combination is structurally incoherent:

  • described + ordinal: rejected because ordinal requires explicit ordering via permissible values (enumerated), not a range constraint.
  • enumerated + continuous: rejected because continuous ranges must be described with a JSON-schema constraint, not a finite list of permissible values.

func VillageAPISpecJSON

func VillageAPISpecJSON() []byte

VillageAPISpecJSON returns the JSON bytes of the CURRENT Village API OpenAPI spec — the version named by VillageAPIVersion. It is version-aware: the filename is derived from the single-source VillageAPIVersion constant, never a literal, so a version bump in versions.go re-points this accessor in lockstep and consumers (e.g. village's GET /openapi.json) need no change.

The bytes are embedded at compile time, so a failure here means the committed generated/ artifact for VillageAPIVersion is missing — a build/generation bug, not a runtime condition. It panics with an actionable message in that case; the codegen-freshness gate and TestVillageAPISpecJSON_MatchesCurrentVersion make this unreachable in a healthy tree.

Types

type ActivityEdge

type ActivityEdge struct {
	From      string `json:"from"`
	To        string `json:"to"`
	TaskCount int    `json:"taskCount"` // distinct tasks that edited both
}

ActivityEdge is a co-edit observation: two nodes repeatedly edited by the same tasks.

type AnnotationAxis

type AnnotationAxis string

AnnotationAxis is the subscription dimension for annotation channels.

const (
	AxisType    AnnotationAxis = "type"
	AxisSession AnnotationAxis = "session"
	AxisProject AnnotationAxis = "project"
)

func (AnnotationAxis) IsValid

func (a AnnotationAxis) IsValid() bool

IsValid reports whether a is a defined annotation subscription axis.

func (AnnotationAxis) JSONSchema

func (AnnotationAxis) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (AnnotationAxis) String

func (a AnnotationAxis) String() string

String returns the wire representation of the annotation axis.

type AnnotationDatatype

type AnnotationDatatype string

AnnotationDatatype is the storage type for annotation values.

const (
	DatatypeText    AnnotationDatatype = "text"
	DatatypeInteger AnnotationDatatype = "integer"
	DatatypeReal    AnnotationDatatype = "real"
	DatatypeBoolean AnnotationDatatype = "boolean"
)

func (AnnotationDatatype) IsValid

func (d AnnotationDatatype) IsValid() bool

IsValid returns true if the annotation datatype is one of the known variants.

func (AnnotationDatatype) JSONSchema

func (AnnotationDatatype) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (AnnotationDatatype) String

func (d AnnotationDatatype) String() string

type AnnotationEntryTarget

type AnnotationEntryTarget struct {
	SessionID  string `json:"sessionId"`
	EntryIndex int    `json:"entryIndex"`
	EndIndex   int    `json:"endIndex"` // half-open [start, end)
}

AnnotationEntryTarget identifies an entry-level annotation target. EndIndex is a half-open range [EntryIndex, EndIndex).

type AnnotationFixtureSummary

type AnnotationFixtureSummary struct {
	Name                string `yaml:"name"`
	ID                  string `yaml:"id"`
	TargetKind          string `yaml:"targetKind"`
	TargetSessionID     string `yaml:"targetSessionId,omitempty"`
	TargetEntryIndex    *int   `yaml:"targetEntryIndex,omitempty"`
	TargetEntryEndIndex *int   `yaml:"targetEntryEndIndex,omitempty"`
	TargetAnnotationID  string `yaml:"targetAnnotationId,omitempty"`
	TargetProjectHash   string `yaml:"targetProjectHash,omitempty"`
	TargetAssociationID string `yaml:"targetAssociationId,omitempty"`
	TargetFilePath      string `yaml:"targetFilePath,omitempty"`
	TargetContentHash   string `yaml:"targetContentHash,omitempty"`
	IsPrimary           bool   `yaml:"isPrimary"`
	AnnotatorKind       string `yaml:"annotatorKind"`
	AnnotatorName       string `yaml:"annotatorName"`
	TypeID              string `yaml:"typeId"`
	TypeName            string `yaml:"typeName"`
	Value               string `yaml:"value"`
	CreatedAt           int64  `yaml:"createdAt"`
}

AnnotationFixtureSummary is a named annotation template in YAML.

func (*AnnotationFixtureSummary) ToAnnotationSummary

func (f *AnnotationFixtureSummary) ToAnnotationSummary() AnnotationSummary

ToAnnotationSummary converts the fixture to a real AnnotationSummary.

type AnnotationFixtures

type AnnotationFixtures struct {
	Summaries         []AnnotationFixtureSummary                                                   `yaml:"annotation_summaries"`
	Validations       []SubscriptionValidationCase                                                 `yaml:"subscription_validations"`
	TargetValidations testcase.Corpus[AnnotationSummary, bool]                                     `yaml:"annotation_target_validations"`
	TargetRepairs     testcase.Corpus[annotationTargetRepairInput, annotationTargetRepairExpected] `yaml:"annotation_target_repairs"`
}

AnnotationFixtures is the top-level YAML structure for annotation test data.

func LoadAnnotationFixtures

func LoadAnnotationFixtures() (*AnnotationFixtures, error)

LoadAnnotationFixtures parses AnnotationsYAML into structured fixtures.

func (*AnnotationFixtures) FindSummary

func (f *AnnotationFixtures) FindSummary(name string) *AnnotationFixtureSummary

FindSummary returns the fixture annotation with the given name, or nil.

type AnnotationManifestResponse

type AnnotationManifestResponse struct {
	// Hex-encoded SHA3-256 annotation content-hashes the village holds for the owner (sorted, de-duplicated).
	// Always emitted as a (possibly empty) NON-null array: NewAnnotationManifestResponse
	// normalizes via sortedUniqueHashes, which never returns nil — so nullable:"false"
	// is the correct wire contract (matches develop's served village-api spec).
	Hashes []string `` /* 148-byte string literal not displayed */
	// Deterministic, order-independent digest over the hash set; a client computing the same digest over its local set knows nothing diverged.
	Digest string `` /* 164-byte string literal not displayed */
}

AnnotationManifestResponse is the body returned by GET /api/v1/annotations/manifest. It advertises the SET of annotation content-hashes the village currently holds for the authenticated owner, so a push client can SKIP any local annotation whose hash already appears here (server-authoritative skip-gate).

Hashes are hex-encoded SHA3-256 content-hashes — the SAME identity the client already computes via content_hash.go (ComputeContentHash / ComputeAnnotationHash). No annotation CONTENT is carried, only its hash, so the manifest is privacy-safe.

Digest is a deterministic, ORDER-INDEPENDENT digest over the hash set (see ComputeManifestDigest). A no-op re-push can short-circuit: if the client computes the same digest over its own local hash set, nothing has diverged.

This type is ADDITIVE — it introduces a new endpoint's response shape and does not alter any existing publish/annotation-push wire contract.

func NewAnnotationManifestResponse

func NewAnnotationManifestResponse(hashes []string) AnnotationManifestResponse

NewAnnotationManifestResponse builds a manifest from a set of content-hashes, normalizing the set (sorted + de-duplicated) and computing the matching digest.

Normalizing on construction means the wire payload is canonical: two villages holding the same logical set emit byte-identical manifests, and the Digest is always consistent with the Hashes it accompanies.

func (AnnotationManifestResponse) ComputeDigest

func (r AnnotationManifestResponse) ComputeDigest() string

ComputeDigest recomputes the order-independent digest over this manifest's Hashes. It is provided so a client can verify the server's Digest field or compare against its own locally-derived digest for the no-op short-circuit.

type AnnotationPushItem

type AnnotationPushItem struct {
	ContentHash   string                 `json:"contentHash"`
	TargetKind    TargetKind             `json:"targetKind"`
	SessionID     *string                `json:"sessionId,omitempty"`
	EntryTarget   *AnnotationEntryTarget `json:"entryTarget,omitempty"`
	AnnotationID  *string                `json:"annotationId,omitempty"`
	ProjectHash   *ProjectHash           `json:"projectHash,omitempty"`
	TypeID        string                 `json:"typeId"`
	Value         string                 `json:"value"`
	IsPrimary     bool                   `json:"isPrimary"`
	Confidence    *float64               `json:"confidence,omitempty"`
	Reason        *string                `json:"reason,omitempty"`
	AnnotatorName string                 `json:"annotatorName,omitempty"`
	Provenance    *Provenance            `json:"provenance,omitempty"`
}

AnnotationPushItem is the wire type for a single annotation in a push request. ContentHash is SHA3-256 of the canonical JSON representation of all other fields, computed by ComputeContentHash(). Used for server-side deduplication.

func (*AnnotationPushItem) ComputeContentHash

func (item *AnnotationPushItem) ComputeContentHash() string

ComputeContentHash computes a SHA3-256 content hash over the canonical JSON representation of the AnnotationPushItem, excluding the ContentHash field itself.

The hash is deterministic: the same logical annotation always produces the same hex string regardless of struct field order. This is because encoding/json marshals struct fields in declaration order, producing stable output for the same values.

Use case: server-side deduplication. The caller sets item.ContentHash to this value before adding it to an AnnotationPushRequest.

type AnnotationPushRequest

type AnnotationPushRequest struct {
	Annotations []AnnotationPushItem `json:"annotations"`
	Retractions []string             `json:"retractions,omitempty"`
}

AnnotationPushRequest is the body sent to POST /api/v1/annotations.

Retractions is an ADDITIVE, backwards-compatible field: a set of content-hashes the client wants the village to DROP (tombstone) for this owner. It carries propagated deletions/supersessions inline on the existing push request rather than via a separate DELETE endpoint (avoids a second auth/owner-scoping path and round-trip). The hashes are the SAME hex SHA3 content-hashes used for dedup; only hashes the owner authored AND locally retired are sent, so a foreign machine's annotation can never be retracted. omitempty preserves the prior wire shape for clients that send no retractions.

type AnnotationPushResponse

type AnnotationPushResponse struct {
	Created int                    `json:"created"`
	Updated int                    `json:"updated"`
	Skipped int                    `json:"skipped"`
	Errors  int                    `json:"errors"`
	Results []AnnotationPushResult `json:"results,omitempty"`
}

AnnotationPushResponse is returned by the village after processing an annotation push.

type AnnotationPushResult

type AnnotationPushResult struct {
	ContentHash string               `json:"contentHash,omitempty"`
	Status      AnnotationPushStatus `json:"status"`
	Error       string               `json:"error,omitempty"`
}

AnnotationPushResult is the per-item result within an AnnotationPushResponse.

type AnnotationPushStatus

type AnnotationPushStatus string

AnnotationPushStatus is the per-item outcome status from the village.

const (
	PushStatusCreated AnnotationPushStatus = "created"
	PushStatusUpdated AnnotationPushStatus = "updated"
	PushStatusSkipped AnnotationPushStatus = "skipped"
	PushStatusError   AnnotationPushStatus = "error"
)

func (AnnotationPushStatus) IsValid

func (s AnnotationPushStatus) IsValid() bool

IsValid reports whether s is a defined annotation push outcome.

func (AnnotationPushStatus) JSONSchema

func (AnnotationPushStatus) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (AnnotationPushStatus) String

func (s AnnotationPushStatus) String() string

String returns the string representation of the push status.

type AnnotationRegistry

type AnnotationRegistry interface {
	AnnotationTypeReader

	// Register inserts a new annotation type from the given definition.
	// Returns the newly created AnnotationTypeSummary (status=proposed by default).
	Register(ctx context.Context, def TypeDefinition) (*AnnotationTypeSummary, error)

	// Activate transitions a type from proposed -> active.
	Activate(ctx context.Context, typeID string) error

	// Deprecate transitions a type from active -> deprecated, recording the superseding typeID.
	Deprecate(ctx context.Context, typeID string, supersededBy string) error

	// AddDependency records that typeID depends on dependsOn (V14: cycle detection enforced).
	// required=true means the dependency must be satisfied before typeID can produce a value.
	// rationale documents the reason for the dependency.
	AddDependency(ctx context.Context, typeID, dependsOn string, required bool, rationale string) error

	// GetDependencies returns the dependency entries for typeID.
	GetDependencies(ctx context.Context, typeID string) ([]TypeDependency, error)
}

AnnotationRegistry extends AnnotationTypeReader with mutation operations. Used by admin commands and the registry management layer.

type AnnotationStatus

type AnnotationStatus string

AnnotationStatus is the lifecycle state of an annotation type (ISO 11179 Part 6).

const (
	StatusProposed   AnnotationStatus = "proposed"
	StatusActive     AnnotationStatus = "active"
	StatusDeprecated AnnotationStatus = "deprecated"
	StatusRetired    AnnotationStatus = "retired"
)

func (AnnotationStatus) IsValid

func (s AnnotationStatus) IsValid() bool

IsValid returns true if the annotation status is one of the known variants.

func (AnnotationStatus) JSONSchema

func (AnnotationStatus) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (AnnotationStatus) String

func (s AnnotationStatus) String() string

type AnnotationSummary

type AnnotationSummary struct {
	ID                  string       `json:"id"`
	TargetKind          TargetKind   `json:"targetKind" yaml:"targetKind"`
	TargetSessionID     *string      `json:"targetSessionId,omitempty" yaml:"targetSessionId,omitempty"`
	TargetEntryIndex    *int         `json:"targetEntryIndex,omitempty" yaml:"targetEntryIndex,omitempty"`
	TargetEntryEndIndex *int         `json:"targetEntryEndIndex,omitempty" yaml:"targetEntryEndIndex,omitempty"` // V16: half-open [start, end)
	TargetAnnotID       *string      `json:"targetAnnotationId,omitempty" yaml:"targetAnnotationId,omitempty"`
	TargetProjectHash   *ProjectHash `json:"targetProjectHash,omitempty" yaml:"targetProjectHash,omitempty"`
	// TargetAssociationID identifies a durable session-to-commit association.
	// It is an ID target, never an embedded association copy.
	TargetAssociationID *AssociationID `json:"targetAssociationId,omitempty" yaml:"targetAssociationId,omitempty"`
	// TargetFilePath and TargetContentHash discriminate a TargetFileVersion
	// annotation (the 5th TPT arm): a whole-file
	// read-state receipt keyed to a specific content hash of a specific
	// repo-relative path, so an agent edit that changes the content hash
	// invalidates the receipt without deleting it.
	TargetFilePath    *string       `json:"targetFilePath,omitempty" yaml:"targetFilePath,omitempty"`
	TargetContentHash *string       `json:"targetContentHash,omitempty" yaml:"targetContentHash,omitempty"`
	IsPrimary         bool          `json:"isPrimary"`
	AnnotatorKind     AnnotatorKind `json:"annotatorKind"`
	AnnotatorName     string        `json:"annotatorName"`
	TypeID            string        `json:"typeId"`
	TypeName          string        `json:"typeName"`
	Value             string        `json:"value"`
	Confidence        *float64      `json:"confidence,omitempty"`
	Reason            *string       `json:"reason,omitempty"`
	Provenance        *Provenance   `json:"provenance,omitempty"`
	ContentHash       *string       `json:"contentHash,omitempty"` // V16: push dedup
	CreatedAt         int64         `json:"createdAt"`
	SupersededBy      *string       `json:"supersededBy,omitempty"`
}

AnnotationSummary is the wire format for annotations in API responses. TargetKind is derived via TPT child table JOINs (annotations_with_target view).

func (AnnotationSummary) Validate

func (a AnnotationSummary) Validate() error

Validate checks that TargetKind selects exactly one AnnotationSummary target arm. It validates the response contract at its shared boundary so producers cannot emit mixed target identities.

type AnnotationTypeReader

type AnnotationTypeReader interface {
	// GetType returns the annotation type summary for the given type_id string.
	// Returns an error wrapping ErrTypeNotFound if no matching type exists.
	GetType(ctx context.Context, typeID string) (*AnnotationTypeSummary, error)

	// ListTypes returns all annotation types matching the given filter.
	// An empty TypeFilter returns all non-deprecated/retired types.
	ListTypes(ctx context.Context, f TypeFilter) ([]AnnotationTypeSummary, error)

	// ValidateValue validates that value is permissible for the annotation type identified by typeID.
	// Returns nil if valid. Returns an error wrapping ErrTypeNotFound if the type does not exist,
	// or an error wrapping ErrInvalidValue if the value is not permissible.
	ValidateValue(ctx context.Context, typeID string, value string) error
}

AnnotationTypeReader provides read-only access to the annotation type registry. Consumed by classifiers, the ingest pipeline, and the REST API handler. Returns AnnotationTypeSummary (wire type) — the internal domain object stays in internal/annotations.

type AnnotationTypeSummary

type AnnotationTypeSummary struct {
	ID               string           `json:"id,omitempty"` // UUID PK — populated from store for CLI use; omitted in REST responses
	TypeID           string           `json:"typeId"`
	Version          int              `json:"version"`
	DisplayName      string           `json:"displayName"`
	Description      string           `json:"description,omitempty"`
	Family           string           `json:"family"`
	Class            string           `json:"class"`
	ScaleKind        ScaleKind        `json:"scaleKind,omitempty"` // measurement level (ISO 11179 Part 5)
	ValueDomain      ValueDomain      `json:"valueDomain"`
	LowerIsBetter    *bool            `json:"lowerIsBetter,omitempty"`
	Status           AnnotationStatus `json:"status"`
	Origin           TypeOrigin       `json:"origin"`
	PriorityOverride *int             `json:"priorityOverride,omitempty"`
	// AllowedTargetKinds lists the target kinds this type may annotate (V16).
	// Empty/omitted means the type places no restriction (all kinds allowed).
	// Clients filter entry-level pickers to types whose list includes "entry".
	AllowedTargetKinds []TargetKind `json:"allowedTargetKinds,omitempty"`
}

AnnotationTypeSummary is the wire format for annotation types in API responses. Class is derived via the annotation_families → annotation_classes join (BCNF: no redundant column).

type AnnotationsPayload

type AnnotationsPayload struct {
	Axis        AnnotationAxis      `json:"axis"`
	ID          string              `json:"id"`
	Annotations []AnnotationSummary `json:"annotations"`
}

AnnotationsPayload is the data sent on the annotations WebSocket channel. Axis and ID echo the subscription parameters so clients can correlate updates.

type AnnotatorKind

type AnnotatorKind string

AnnotatorKind identifies the type of entity that produced an annotation. Priority for effective annotation resolution: human(3) > agent(2) > rule(1).

const (
	AnnotatorHuman AnnotatorKind = "human"
	AnnotatorAgent AnnotatorKind = "agent"
	AnnotatorRule  AnnotatorKind = "rule"
)

func (AnnotatorKind) IsValid

func (k AnnotatorKind) IsValid() bool

IsValid returns true if the annotator kind is one of the known variants.

func (AnnotatorKind) JSONSchema

func (AnnotatorKind) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (AnnotatorKind) Priority

func (k AnnotatorKind) Priority() int

Priority returns the resolution priority for effective annotation selection. Higher value wins: human(3) > agent(2) > rule(1). Returns 0 for unknown kinds.

func (AnnotatorKind) String

func (k AnnotatorKind) String() string

type AnnotatorSummary

type AnnotatorSummary struct {
	ID          string        `json:"id"`
	Kind        AnnotatorKind `json:"kind"`
	Name        string        `json:"name"`
	DisplayName string        `json:"displayName"`
	Description string        `json:"description,omitempty"`
	ModelID     *string       `json:"modelId,omitempty"`
	// DO NOT TOUCH (TRAP): ProviderKey is the model-VENDOR credential
	// (e.g. "anthropic"), a DIFFERENT axis from the coding-tool Harness. The
	// harness-key changeover left this as json:"providerKey" on purpose.
	// Never flip it to json:"harness" — enforced by ast-grep/no-trap-harness-flip.yml.
	ProviderKey *string `json:"providerKey,omitempty"`
	Status      string  `json:"status"`
}

AnnotatorSummary is the wire format for annotators in API responses. ModelID and ProviderKey are only populated for agent annotators.

type AssociationConclusion

type AssociationConclusion string

AssociationConclusion is the producer-supplied conclusion for a session to commit relationship. Schema validates the closed set, not the inference policy that produced the conclusion.

const (
	AssociationConclusionConfirmed AssociationConclusion = "confirmed"
	AssociationConclusionCandidate AssociationConclusion = "candidate"
)

AssociationConclusion values.

func (AssociationConclusion) IsValid

func (c AssociationConclusion) IsValid() bool

IsValid reports whether c is a defined association conclusion.

func (AssociationConclusion) JSONSchema

func (AssociationConclusion) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (AssociationConclusion) String

func (c AssociationConclusion) String() string

String returns the wire representation of the association conclusion.

func (AssociationConclusion) Validate

func (c AssociationConclusion) Validate() error

Validate rejects values outside the closed association-conclusion set.

type AssociationEvidenceKind

type AssociationEvidenceKind string

AssociationEvidenceKind identifies one atomic observation supporting a session-to-commit association. The order in AllAssociationEvidenceKinds is also the required canonical evidence order.

const (
	AssociationEvidenceRecordedCommit   AssociationEvidenceKind = "recorded_commit"
	AssociationEvidenceTouchedFile      AssociationEvidenceKind = "touched_file"
	AssociationEvidenceBranchMembership AssociationEvidenceKind = "branch_membership"
	AssociationEvidenceTimeWindow       AssociationEvidenceKind = "time_window"
)

AssociationEvidenceKind values.

func (AssociationEvidenceKind) IsValid

func (k AssociationEvidenceKind) IsValid() bool

IsValid reports whether k is a defined association evidence kind.

func (AssociationEvidenceKind) JSONSchema

JSONSchema implements jsonschema.Exposer.

func (AssociationEvidenceKind) String

func (k AssociationEvidenceKind) String() string

String returns the wire representation of the association evidence kind.

func (AssociationEvidenceKind) Validate

func (k AssociationEvidenceKind) Validate() error

Validate rejects values outside the closed association-evidence-kind set.

type AssociationEvidenceObservation

type AssociationEvidenceObservation struct {
	Kind               AssociationEvidenceKind `json:"kind" yaml:"kind" required:"true"`
	RecordedCommitHash *string                 `json:"recordedCommitHash,omitempty" yaml:"recordedCommitHash,omitempty"`
	TouchedFilePath    *string                 `json:"touchedFilePath,omitempty" yaml:"touchedFilePath,omitempty"`
	BranchName         *string                 `json:"branchName,omitempty" yaml:"branchName,omitempty"`
	WindowStartMs      *int64                  `json:"windowStartMs,omitempty" yaml:"windowStartMs,omitempty"`
	WindowEndMs        *int64                  `json:"windowEndMs,omitempty" yaml:"windowEndMs,omitempty"`
}

AssociationEvidenceObservation is one atomic, typed observation supporting a session-to-commit association. Exactly the fields for Kind's selected arm are populated; producers must send canonical order and never rely on schema to normalize a wire value.

func (AssociationEvidenceObservation) Validate

Validate checks that Kind selects exactly one structurally valid detail arm. Git hash and branch-name grammars are producer policy; schema only requires that their supplied strings are non-empty.

type AssociationID

type AssociationID string

AssociationID is Peasant's opaque, durable identifier for one association between a project, session, and observed session-era commit. Consumers treat it as an identifier only: they do not derive, parse, rank, or recompute it.

func NewAssociationID

func NewAssociationID(raw string) (AssociationID, error)

NewAssociationID validates and constructs an opaque association identifier.

func (AssociationID) JSONSchema

func (AssociationID) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (AssociationID) String

func (id AssociationID) String() string

String returns the wire representation of the association identifier.

func (AssociationID) Validate

func (id AssociationID) Validate() error

Validate rejects an association identifier that cannot cross the wire boundary. The identifier is ASCII-only, one to 128 bytes, starts alphanumerically, and thereafter uses only alphanumeric, dot, underscore, colon, or hyphen characters.

type BatchCreateAnnotationsErrorResponse

type BatchCreateAnnotationsErrorResponse struct {
	Error        string `json:"error"`
	FailingIndex int    `json:"failingIndex"`
}

BatchCreateAnnotationsErrorResponse is the JSON error response for POST /api/v1/annotations/batch (400). FailingIndex is the zero-based index of the first annotation that failed validation.

type BatchCreateAnnotationsRequest

type BatchCreateAnnotationsRequest struct {
	Annotations []CreateAnnotationRequest `json:"annotations"`
}

BatchCreateAnnotationsRequest is the JSON body for POST /api/v1/annotations/batch. All annotations are committed as a single all-or-nothing SQLite transaction.

type BatchCreateAnnotationsResponse

type BatchCreateAnnotationsResponse struct {
	IDs []string `json:"ids"`
}

BatchCreateAnnotationsResponse is the JSON response for POST /api/v1/annotations/batch (201 Created). IDs are returned in the same order as the request Annotations slice.

type BuiltinCommand

type BuiltinCommand string

BuiltinCommand represents a built-in slash command supported by Claude Code. These are first-party commands that ship with the tool (e.g. /exit, /compact). Slash-command entries in transcripts whose name matches a BuiltinCommand are structural signals rather than user-initiated tool calls.

const (
	ClaudeBuiltinCmdExit             BuiltinCommand = "exit"
	ClaudeBuiltinCmdCompact          BuiltinCommand = "compact"
	ClaudeBuiltinCmdClear            BuiltinCommand = "clear"
	ClaudeBuiltinCmdNew              BuiltinCommand = "new"
	ClaudeBuiltinCmdModel            BuiltinCommand = "model"
	ClaudeBuiltinCmdUsage            BuiltinCommand = "usage"
	ClaudeBuiltinCmdCost             BuiltinCommand = "cost"
	ClaudeBuiltinCmdContext          BuiltinCommand = "context"
	ClaudeBuiltinCmdPlugin           BuiltinCommand = "plugin"
	ClaudeBuiltinCmdPermissions      BuiltinCommand = "permissions"
	ClaudeBuiltinCmdLogin            BuiltinCommand = "login"
	ClaudeBuiltinCmdResume           BuiltinCommand = "resume"
	ClaudeBuiltinCmdPlan             BuiltinCommand = "plan"
	ClaudeBuiltinCmdFast             BuiltinCommand = "fast"
	ClaudeBuiltinCmdVoice            BuiltinCommand = "voice"
	ClaudeBuiltinCmdTodos            BuiltinCommand = "todos"
	ClaudeBuiltinCmdReloadPlugins    BuiltinCommand = "reload-plugins"
	ClaudeBuiltinCmdSandbox          BuiltinCommand = "sandbox"
	ClaudeBuiltinCmdConfig           BuiltinCommand = "config"
	ClaudeBuiltinCmdStatusline       BuiltinCommand = "statusline"
	ClaudeBuiltinCmdUpgrade          BuiltinCommand = "upgrade"
	ClaudeBuiltinCmdExtraUsage       BuiltinCommand = "extra-usage"
	ClaudeBuiltinCmdRateLimitOptions BuiltinCommand = "rate-limit-options"
	ClaudeBuiltinCmdPrivacySettings  BuiltinCommand = "privacy-settings"
	ClaudeBuiltinCmdHelp             BuiltinCommand = "help"
	ClaudeBuiltinCmdCommands         BuiltinCommand = "commands"
)

func (BuiltinCommand) IsValid

func (c BuiltinCommand) IsValid() bool

IsValid returns true if the command is one of the known built-in variants. Derived from AllClaudeBuiltinCmds (single source of truth).

func (BuiltinCommand) JSONSchema

func (BuiltinCommand) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (BuiltinCommand) String

func (c BuiltinCommand) String() string

type CLILoginQuery

type CLILoginQuery struct {
	Port  int    `json:"port" query:"port" description:"Local callback server port"`
	State string `json:"state" query:"state" description:"OAuth state parameter for CSRF protection"`
}

CLILoginQuery represents the query parameters for the CLI login initiation endpoint. GET /api/v1/auth/cli/login?port={port}&state={state}

type ChangeBinding

type ChangeBinding string

ChangeBinding states how strongly a session is tied to a change (contract §2 binding rule, spec §6.2).

const (
	ChangeBindingBound     ChangeBinding = "bound"
	ChangeBindingCandidate ChangeBinding = "candidate"
)

ChangeBinding values. A session is bound when at least one of its linked commits is contained in the branch AND its recorded edits overlap the branch's changed files; one-arm matches (or git_branch equality alone) are candidates. Candidates are never silently dropped.

func (ChangeBinding) IsValid

func (b ChangeBinding) IsValid() bool

IsValid reports whether b is one of the defined bindings.

func (ChangeBinding) JSONSchema

func (ChangeBinding) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (ChangeBinding) String

func (b ChangeBinding) String() string

String returns the wire representation of the binding.

type ChangeDetailPayload

type ChangeDetailPayload struct {
	Branch            string          `json:"branch"`
	BaseRef           string          `json:"baseRef"` // merge-base hash
	DefaultBranch     string          `json:"defaultBranch"`
	Files             []FileChange    `json:"files"`
	Slice             MapSlice        `json:"slice"` // touched nodes + 1-hop
	NewEdges          []MapEdge       `json:"newEdges"`
	RemovedEdges      []MapEdge       `json:"removedEdges"`
	NewNodes          []string        `json:"newNodes"` // node IDs
	RemovedNodes      []string        `json:"removedNodes"`
	Violations        []EdgeViolation `json:"violations"` // NEW violations introduced by this change
	Work              []ChangeSession `json:"work"`
	UnrecordedCommits []CommitRef     `json:"unrecordedCommits"`
	// Unusual holds NEUTRAL rate-elevation observations vs the project baseline
	// (e.g. more retry loops per conversation than usual) — facts, never a
	// verdict or grade.
	Unusual []UnusualSignal `json:"unusual"`
	// Frictions holds NEUTRAL recurring-friction counts keyed by (kind, file):
	// "this kind of friction touched this file N times across M conversations"
	// Facts are for orientation, never a verdict.
	Frictions []FrictionCluster `json:"frictions"`
	// Insights carries mechanical and mined insight envelopes for this change.
	// It is additive alongside Unusual/Frictions above, never a replacement
	// for them.
	Insights     []SessionInsight `json:"insights" required:"true" nullable:"false"`
	LinesAdded   int              `json:"linesAdded"`
	LinesRemoved int              `json:"linesRemoved"`
	OutputTokens int64            `json:"outputTokens"` // SUM of output_tokens over bound sessions
	CostUsd      *float64         `json:"costUsd,omitempty"`
}

ChangeDetailPayload backs the Review change-detail surface, served by GET /api/v1/review/{projectHash}/change?branch=<name>.

func NewChangeDetailPayload

func NewChangeDetailPayload(branch string) *ChangeDetailPayload

NewChangeDetailPayload returns a ChangeDetailPayload with all slices (including the nested MapSlice's) initialized to empty (never-nil marshal guarantee).

func (ChangeDetailPayload) Validate

func (p ChangeDetailPayload) Validate() error

Validate checks that Insights is non-nil and every entry is well-formed, including the Classification-must-be-nil rule. It also validates each UnrecordedCommit's shape. Other ChangeDetailPayload fields do not currently define validation rules here.

type ChangeDiffPayload

type ChangeDiffPayload struct {
	Branch    string           `json:"branch"`
	File      string           `json:"file"` // the new path
	OldPath   *string          `json:"oldPath,omitempty"`
	Status    FileChangeStatus `json:"status"`
	Binary    bool             `json:"binary"`
	Truncated bool             `json:"truncated"`
	Hunks     []DiffHunk       `json:"hunks"`
}

ChangeDiffPayload is the rendered unified diff of ONE changed file of a change (branch vs its merge-base with the default branch) — the lazy per-file companion to ChangeDetailPayload (contract §3, GET /review/{projectHash}/diff ?branch=&file=). Binary files come back Binary=true with no hunks; files exceeding the size cap come back Truncated.

func NewChangeDiffPayload

func NewChangeDiffPayload(branch, file string) *ChangeDiffPayload

NewChangeDiffPayload returns a ChangeDiffPayload with Hunks initialized to empty (never-nil marshal guarantee).

type ChangeSession

type ChangeSession struct {
	SessionID string        `json:"sessionId"`
	Title     string        `json:"title"`
	Harness   string        `json:"harness"`
	StartMs   *int64        `json:"startMs,omitempty"`
	Binding   ChangeBinding `json:"binding"` // bound = commit-in-branch AND touch overlap; candidate = one arm only
	Tasks     []TaskSummary `json:"tasks"`
}

ChangeSession is one recorded session behind a change, with its tasks.

func NewChangeSession

func NewChangeSession(sessionID string, binding ChangeBinding) ChangeSession

NewChangeSession returns a ChangeSession with all slices initialized to empty (never-nil marshal guarantee).

type ChangeSummary

type ChangeSummary struct {
	Branch       string `json:"branch"`
	AheadCount   int    `json:"aheadCount"`
	BehindCount  int    `json:"behindCount"`
	FilesChanged int    `json:"filesChanged"`
	SessionCount int    `json:"sessionCount"`
	TaskCount    int    `json:"taskCount"`
	NewEdges     int    `json:"newEdges"`
	RemovedEdges int    `json:"removedEdges"`
	Violations   int    `json:"violations"`
	LastWorkMs   *int64 `json:"lastWorkMs,omitempty"`
	Merged       bool   `json:"merged"`
	MergedAtMs   *int64 `json:"mergedAtMs,omitempty"`
	// Reverted is true when this change was merged and later undone by a
	// `git revert` on the default branch (git-native signal only).
	Reverted bool `json:"reverted,omitempty"`

	// Graph anchors (Changes graph): how this row attaches to lane 0
	// (ReviewListPayload.RecentCommits). Open branches fork at BaseHash and
	// sit at TipCommitMs; merged rows rejoin at MergeCommitHash.
	BaseHash        string `json:"baseHash,omitempty"`        // merge-base commit hash (fork anchor; open branches)
	TipCommitMs     *int64 `json:"tipCommitMs,omitempty"`     // branch tip committer time (row position; open branches)
	MergeCommitHash string `json:"mergeCommitHash,omitempty"` // merge commit hash (join anchor; merged rows)
}

ChangeSummary is one row of the Review list: a local branch measured against the default branch.

type ChannelSubscription

type ChannelSubscription struct {
	Topic ChannelTopic   `json:"topic"`
	ID    string         `json:"id,omitempty"`
	Axis  AnnotationAxis `json:"axis,omitempty"`
}

ChannelSubscription describes a single channel subscription. Topic is always required. Additional fields are topic-specific:

  • TopicSessionDetail: ID = session ID
  • TopicAnnotations: Axis + ID

type ChannelTopic

type ChannelTopic string

ChannelTopic identifies a subscribable data stream.

const (
	TopicDashboard          ChannelTopic = "dashboard"
	TopicSessions           ChannelTopic = "sessions"
	TopicSessionDetail      ChannelTopic = "session_detail"
	TopicTrends             ChannelTopic = "trends"
	TopicQuality            ChannelTopic = "quality"
	TopicAnnotations        ChannelTopic = "annotations"
	TopicProjectFamiliarity ChannelTopic = "project_familiarity"
)

func (ChannelTopic) IsValid

func (t ChannelTopic) IsValid() bool

IsValid reports whether t is a defined WebSocket channel topic.

func (ChannelTopic) JSONSchema

func (ChannelTopic) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (ChannelTopic) String

func (t ChannelTopic) String() string

String returns the wire representation of the channel topic.

type ChildSessionRef

type ChildSessionRef struct {
	ID        string    `json:"id"`
	StartTime time.Time `json:"startTime"`
	Project   string    `json:"project,omitempty"`
}

ChildSessionRef is a lightweight reference to a child (subagent) session.

type ClientMessage

type ClientMessage struct {
	Type     MessageType           `json:"type"`
	Channels []ChannelSubscription `json:"channels,omitempty"`
}

ClientMessage is sent from the browser to the server via WebSocket.

type CommitInfo

type CommitInfo struct {
	Hash        string `json:"hash"`        // commit SHA-1 (full or abbreviated)
	Message     string `json:"message"`     // commit message first line
	AuthorName  string `json:"authorName"`  // author display name
	AuthorEmail string `json:"authorEmail"` // author email (used for attribution filtering)
	CommitTime  int64  `json:"commitTime"`  // committer date, Unix millis
	AuthorTime  int64  `json:"authorTime"`  // author date, Unix millis
}

CommitInfo records a single git commit linked to a session.

type CommitRef

type CommitRef struct {
	Hash       string `json:"hash" yaml:"hash"`
	Subject    string `json:"subject" yaml:"subject"`
	TimeMs     *int64 `json:"timeMs,omitempty" yaml:"timeMs,omitempty"`
	HasSession bool   `json:"hasSession" yaml:"hasSession"` // compatibility mirror of len(SessionIDs) > 0
	// SessionIDs names authoritative session_commits bindings in the same
	// strictly increasing rank order as ReviewListPayload.Sessions.
	SessionIDs []SessionID `json:"sessionIds" yaml:"sessionIds" required:"true" nullable:"false"`
	// Associations keeps each SessionIDs binding as a first-class durable
	// relationship with its conclusion, confidence, and atomic observations. It
	// mirrors SessionIDs one-for-one in the same rank order:
	// Associations[i].SessionID == SessionIDs[i] for every i.
	Associations []SessionAssociation `json:"associations" yaml:"associations" required:"true" nullable:"false"`
}

CommitRef is lightweight commit metadata for time strips and rail panels.

func NewCommitRef

func NewCommitRef(hash, subject string) CommitRef

NewCommitRef returns commit metadata with non-nil session ID and association arrays.

type Confidence

type Confidence string

Confidence classifies how strongly the evidence behind a derived relationship (a session<->commit association, or a ghost-commit rewrite resolution) supports its conclusion.

const (
	ConfidenceHigh   Confidence = "high"
	ConfidenceMedium Confidence = "medium"
	ConfidenceLow    Confidence = "low"
)

Confidence values.

func (Confidence) IsValid

func (c Confidence) IsValid() bool

IsValid reports whether c is one of the defined confidence levels.

func (Confidence) JSONSchema

func (Confidence) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (Confidence) String

func (c Confidence) String() string

String returns the wire representation of the confidence level.

func (Confidence) Validate

func (c Confidence) Validate() error

Validate rejects values that cannot cross the confidence wire boundary.

type ContentKind

type ContentKind string

ContentKind discriminates the concrete payload carried inside a TranscriptContent envelope. It exists so the village can dispatch on the kind without sniffing the payload, and so future kinds (e.g. raw-jsonl passthrough) can be added without changing the envelope shape.

const ContentKindSessionDetail ContentKind = "session_detail"

ContentKindSessionDetail marks an envelope whose SessionDetail field carries a normalized SessionDetailPayload. It is the only kind peasant currently emits.

func (ContentKind) IsValid

func (k ContentKind) IsValid() bool

IsValid reports whether k is a defined content envelope kind.

func (ContentKind) JSONSchema

func (ContentKind) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (ContentKind) String

func (k ContentKind) String() string

String returns the bare kind string for serialization/log boundaries.

type ContractVersion

type ContractVersion string

ContractVersion is the semantic version of a peasant/village WIRE contract. It is a newtype over string so that the version flows through the codebase typed rather than stringly. The same value-type carries BOTH axes (push and pull): they share one semver shape and one comparison/classification machinery, and the field/constant NAME disambiguates the axis (PushContractVersion vs PullContractVersion). See the PushContractVersion alias below.

It tracks the push/village wire SEPARATELY from:

  • MetadataSchemaVersion (the on-disk {sessionId}--metadata.json structure), and
  • ingest.CurrentIndexVersion (the local indexer evolution),

mirroring the CurrentIndexVersion precedent: a single canonical constant (defaults.PublishSchemaVersion) is the source of truth, bumped on a breaking change to the push wire format.

func (ContractVersion) String

func (v ContractVersion) String() string

String returns the bare semver string for serialization boundaries (OpenAPI filenames, JSON tags handled by the marshaller, CLI output).

type CreateAnnotationRequest

type CreateAnnotationRequest struct {
	SessionID     string   `json:"sessionId"`
	TypeID        string   `json:"typeId"`
	Value         string   `json:"value"`
	IsPrimary     bool     `json:"isPrimary"`
	Confidence    *float64 `json:"confidence,omitempty"`
	Reason        *string  `json:"reason,omitempty"`
	AnnotatorName string   `json:"annotatorName,omitempty"`
	// Entry-level targeting — if set, creates an annotation_target_entry row.
	// TargetEntryEndIndex defaults to TargetEntryIndex+1 (single-entry span) when omitted.
	TargetEntryIndex    *int `json:"targetEntryIndex,omitempty"`
	TargetEntryEndIndex *int `json:"targetEntryEndIndex,omitempty"`
	// Meta-annotation targeting — if set, creates an annotation_target_annotation row.
	TargetAnnotationID *string `json:"targetAnnotationId,omitempty"`
}

CreateAnnotationRequest is the JSON body for POST /api/v1/annotations. Target selection rules (mutually exclusive):

  • Session-level: SessionID set, no entry/annotation fields.
  • Entry-level: SessionID + TargetEntryIndex set; TargetEntryEndIndex optional (defaults to index+1).
  • Meta-annotation: TargetAnnotationID set (annotation on annotation).

type CreateAnnotationResponse

type CreateAnnotationResponse struct {
	ID string `json:"id"`
}

CreateAnnotationResponse is the JSON response for POST /api/v1/annotations (201 Created).

type DashboardPayload

type DashboardPayload struct {
	TotalSessions      int             `json:"totalSessions"`
	TotalTokens        int             `json:"totalTokens"`
	AvgDurationMins    float64         `json:"avgDurationMins"`
	HarnessBreakdown   map[Harness]int `json:"harnessBreakdown"`
	AvgTurnsPerSession float64         `json:"avgTurnsPerSession"`
	AcceptanceRate     float64         `json:"acceptanceRate"`
}

DashboardPayload is the data sent on the dashboard WebSocket channel.

type DayStats

type DayStats struct {
	Date     string `json:"date"` // "2006-01-02" format
	Tokens   int    `json:"tokens"`
	Sessions int    `json:"sessions"`
}

DayStats holds aggregated data for a single day in trends.

type DecayLevel

type DecayLevel string

DecayLevel classifies how recently a file was engaged.

const (
	DecayFresh      DecayLevel = "fresh"
	DecayFading     DecayLevel = "fading"
	DecayStale      DecayLevel = "stale"
	DecayUnexplored DecayLevel = "unexplored"
)

func (DecayLevel) IsValid

func (d DecayLevel) IsValid() bool

IsValid reports whether d is a defined familiarity decay level.

func (DecayLevel) JSONSchema

func (DecayLevel) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (DecayLevel) String

func (d DecayLevel) String() string

type DiagnosticEntry

type DiagnosticEntry struct {
	ErrorType   string `json:"errorType"`   // e.g. "parse_error", "permission_denied", "copy_failed"
	Location    string `json:"location"`    // e.g. "line 47", "debug/tool_output_3.json"
	Message     string `json:"message"`     // Human-readable description
	Remediation string `json:"remediation"` // Actionable fix suggestion
}

DiagnosticEntry is a structured error object recorded during ingestion or processing.

type DiagnosticsInfo

type DiagnosticsInfo struct {
	Warnings []DiagnosticEntry `json:"warnings"`
	Partial  *bool             `json:"partial,omitempty"` // true if any file copy failed; nil if not determined
}

DiagnosticsInfo records issues encountered during ingestion.

type DiffHunk

type DiffHunk struct {
	OldStart int        `json:"oldStart"`
	OldLines int        `json:"oldLines"`
	NewStart int        `json:"newStart"`
	NewLines int        `json:"newLines"`
	Header   string     `json:"header,omitempty"`
	Lines    []DiffLine `json:"lines"`
	// Attribution (the mission climax): the recorded conversation that wrote
	// most of this hunk's added lines, resolved via git blame → commit →
	// session. Empty when the hunk's new lines trace to no recorded session
	// (hand-written, or authored outside this tool).
	SessionID    string `json:"sessionId,omitempty"`
	SessionTitle string `json:"sessionTitle,omitempty"`
}

DiffHunk is one "@@ -oldStart,oldLines +newStart,newLines @@" section. Line numbers in the gutter are derivable from OldStart/NewStart plus position.

type DiffLine

type DiffLine struct {
	Kind DiffLineKind `json:"kind"`
	Text string       `json:"text"`
}

DiffLine is one line within a hunk. Kind is "context" | "add" | "del"; Text excludes the leading +/-/space marker.

type DiffLineKind

type DiffLineKind string

DiffLineKind classifies a unified-diff line.

const (
	DiffLineKindContext DiffLineKind = "context"
	DiffLineKindAdd     DiffLineKind = "add"
	DiffLineKindDelete  DiffLineKind = "del"
)

func (DiffLineKind) IsValid

func (k DiffLineKind) IsValid() bool

IsValid reports whether k is a canonical diff line kind.

func (DiffLineKind) JSONSchema

func (DiffLineKind) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (DiffLineKind) String

func (k DiffLineKind) String() string

String returns the wire representation of the diff line kind.

func (DiffLineKind) Validate

func (k DiffLineKind) Validate() error

Validate rejects values that cannot cross a diff-line wire boundary.

type EdgeViolation

type EdgeViolation struct {
	Kind EdgeViolationKind `json:"kind"`
	From string            `json:"from"`
	To   string            `json:"to"`
}

EdgeViolation flags an edge that breaks the layering discipline.

type EdgeViolationKind

type EdgeViolationKind string

EdgeViolationKind classifies a structural violation on the map.

const (
	EdgeViolationCycle    EdgeViolationKind = "cycle"
	EdgeViolationWrongWay EdgeViolationKind = "wrong_way"
)

EdgeViolationKind values (mirrors codegraph's violation kinds).

func (EdgeViolationKind) IsValid

func (k EdgeViolationKind) IsValid() bool

IsValid reports whether k is one of the defined violation kinds.

func (EdgeViolationKind) JSONSchema

func (EdgeViolationKind) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (EdgeViolationKind) String

func (k EdgeViolationKind) String() string

String returns the wire representation of the violation kind.

type EntryType

type EntryType string

EntryType classifies a single entry within an agent session transcript.

const (
	EntryTypeText       EntryType = "text"
	EntryTypeToolUse    EntryType = "tool_use"
	EntryTypeToolResult EntryType = "tool_result"
	EntryTypeThinking   EntryType = "thinking"
	EntryTypeSystem     EntryType = "system"
	EntryTypeError      EntryType = "error"
	EntryTypeResult     EntryType = "result"
)

func (EntryType) IsValid

func (e EntryType) IsValid() bool

IsValid returns true if the entry type is one of the known variants.

func (EntryType) JSONSchema

func (EntryType) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (EntryType) String

func (e EntryType) String() string

type ExchangeCodeRequest

type ExchangeCodeRequest struct {
	Code  string `json:"code"`
	State string `json:"state"`
}

ExchangeCodeRequest is the JSON body sent to the village CLI auth exchange endpoint. POST /api/v1/auth/cli/exchange

type ExchangeCodeResponse

type ExchangeCodeResponse struct {
	APIKey   string `json:"api_key"`
	KeyID    string `json:"key_id"`
	UserID   string `json:"user_id"`
	Username string `json:"username"`
}

ExchangeCodeResponse is the JSON response from the village CLI auth exchange endpoint.

type FamiliarityPayload

type FamiliarityPayload struct {
	ProjectHash     ProjectHash        `json:"projectHash"`
	FamiliarityPct  float64            `json:"familiarityPct"`  // % of source files engaged
	UnexploredCount int                `json:"unexploredCount"` // source files with 0 engagement
	FreshnessDays   *int               `json:"freshnessDays"`   // days since last learning session
	Files           []FileFamiliarity  `json:"files"`
	Trails          []WalkthroughTrail `json:"trails"`
	Suggestions     []ReviewSuggestion `json:"suggestions"`
}

FamiliarityPayload is the data sent on the project_familiarity WebSocket channel.

type FileChange

type FileChange struct {
	Path         string           `json:"path"`
	Status       FileChangeStatus `json:"status"`
	OldPath      *string          `json:"oldPath,omitempty"`
	LinesAdded   int              `json:"linesAdded"`
	LinesRemoved int              `json:"linesRemoved"`
}

FileChange is one file-level delta of a change (branch vs merge-base). LinesAdded/LinesRemoved are the per-file numstat churn (0 for binary files or when numstat is unavailable) — the change-weight treemap's sizing input Always present; 0 is meaningful, so no omitempty.

type FileChangeStatus

type FileChangeStatus string

FileChangeStatus classifies a file-level delta using Git's canonical one-letter status tokens.

const (
	FileChangeStatusModified FileChangeStatus = "M"
	FileChangeStatusAdded    FileChangeStatus = "A"
	FileChangeStatusDeleted  FileChangeStatus = "D"
	FileChangeStatusRenamed  FileChangeStatus = "R"
)

func (FileChangeStatus) IsValid

func (s FileChangeStatus) IsValid() bool

IsValid reports whether s is a canonical file change status.

func (FileChangeStatus) JSONSchema

func (FileChangeStatus) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (FileChangeStatus) String

func (s FileChangeStatus) String() string

String returns the wire representation of the file change status.

func (FileChangeStatus) Validate

func (s FileChangeStatus) Validate() error

Validate rejects values that cannot cross a file-change wire boundary.

type FileFamiliarity

type FileFamiliarity struct {
	Path          string     `json:"path"`
	Depth         int        `json:"depth"` // 0=unexplored, 1=touched, 2=engaged, 3=deep
	SessionCount  int        `json:"sessionCount"`
	TotalTurns    int        `json:"totalTurns"`
	HumanTurns    int        `json:"humanTurns"`
	LastEngagedAt *string    `json:"lastEngagedAt"` // ISO 8601, nil if never
	DaysSince     *int       `json:"daysSince"`     // nil if never engaged
	DecayLevel    DecayLevel `json:"decayLevel"`
	IsSourceFile  bool       `json:"isSourceFile"` // true for relevant source files, false for config/generated
}

FileFamiliarity represents familiarity data for a single file.

type FrictionCluster

type FrictionCluster struct {
	Kind     string `json:"kind"`     // signal slug, e.g. "retryLoop"
	Label    string `json:"label"`    // plain, neutral (e.g. "retry loops")
	File     string `json:"file"`     // repo-relative path
	Count    int    `json:"count"`    // occurrences (retry-loop tasks touching this file)
	Sessions int    `json:"sessions"` // distinct conversations those occurrences span
}

FrictionCluster is a NEUTRAL count of a recurring friction signal keyed to a file: "this kind of friction touched this file N times across M conversations". A fact for orientation — the surface shows, it does not grade Kind is a stable slug ("retryLoop") so more kinds can be added without a breaking change.

type GitContext

type GitContext struct {
	Branch   *string      `json:"branch,omitempty"`   // Current git branch
	Remote   *string      `json:"remote,omitempty"`   // Git remote URL
	Worktree *string      `json:"worktree,omitempty"` // Worktree path (if applicable)
	Tracking *string      `json:"tracking,omitempty"` // Upstream tracking branch (e.g. "origin/main")
	Commits  []CommitInfo `json:"commits,omitempty"`  // Commits produced during this session (v4+)
}

GitContext holds git repository state at the time of the session.

type Harness

type Harness = bestiary.Harness

Harness identifies the coding tool or AI-assisted development environment that is driving the model interaction. Re-exported from bestiary.

func Harnesses

func Harnesses() []Harness

Harnesses returns every harness identifier known to bestiary — the full set, a superset of AllHarnesses (which is only the ingestion-supported subset). Re-exported so callers can enumerate the canonical known set without importing bestiary directly.

type HealthResponse

type HealthResponse struct {
	Status string `json:"status"`
}

HealthResponse is the JSON response for GET /api/v1/health.

type HostSlug

type HostSlug string

HostSlug is a sanitized, filesystem-safe identifier derived from git remote. Contains [a-zA-Z0-9._<>-] characters. The <> characters support redaction placeholders like <USER> and <PATH> in redacted slugs.

func NewHostSlug

func NewHostSlug(raw string) (HostSlug, error)

NewHostSlug validates and constructs a HostSlug.

func (HostSlug) JSONSchema

func (HostSlug) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (HostSlug) String

func (h HostSlug) String() string

type IDCasing

type IDCasing struct {
	Name      string `yaml:"name"`
	Transform string `yaml:"transform"`
}

IDCasing is one entry of the id_casings axis: a named transform of values.uuid_lower (lower / upper / mixed).

type InsightClassification

type InsightClassification struct {
	Category      string `json:"category" yaml:"category"`
	Cause         string `json:"cause" yaml:"cause"`
	SeverityScope string `json:"severityScope" yaml:"severityScope"`
	SeverityLocus string `json:"severityLocus" yaml:"severityLocus"`
	Resolution    string `json:"resolution" yaml:"resolution"`
}

InsightClassification is the reserved taxonomy tuple (category x cause x severity(scope, locus) x resolution). Its bare string fields keep the wire shape stable for future closed sets. The current contract requires SessionInsight.Classification to remain nil; see SessionInsight.Validate.

type InsightEvidence

type InsightEvidence struct {
	SessionID  SessionID `json:"sessionId" yaml:"sessionId" required:"true"`
	EntryIndex *int      `json:"entryIndex,omitempty" yaml:"entryIndex,omitempty"`
	File       string    `json:"file,omitempty" yaml:"file,omitempty"`
	CommitHash string    `json:"commitHash,omitempty" yaml:"commitHash,omitempty"`
}

InsightEvidence is one traceability pointer for a SessionInsight: the recorded session (and, when known, the turn / file / commit) that grounds it. Every mechanical insight carries at least one.

func (InsightEvidence) Validate

func (e InsightEvidence) Validate() error

Validate checks that the evidence item carries a traceable session identity.

type InsightKind

type InsightKind string

InsightKind classifies a SessionInsight.

const (
	InsightKindDecision  InsightKind = "decision"
	InsightKindFriction  InsightKind = "friction"
	InsightKindUnusual   InsightKind = "unusual"
	InsightKindRetryLoop InsightKind = "retry_loop"
)

InsightKind values.

func (InsightKind) IsValid

func (k InsightKind) IsValid() bool

IsValid reports whether k is one of the defined insight kinds.

func (InsightKind) JSONSchema

func (InsightKind) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (InsightKind) String

func (k InsightKind) String() string

String returns the wire representation of the insight kind.

func (InsightKind) Validate

func (k InsightKind) Validate() error

Validate rejects values that cannot cross the insight-kind wire boundary.

type InsightProvenance

type InsightProvenance string

InsightProvenance classifies how a SessionInsight was produced: mechanical (rule-derived) or mined.

const (
	InsightProvenanceMechanical InsightProvenance = "mechanical"
	InsightProvenanceMined      InsightProvenance = "mined"
)

InsightProvenance values.

func (InsightProvenance) IsValid

func (p InsightProvenance) IsValid() bool

IsValid reports whether p is one of the defined insight provenances.

func (InsightProvenance) JSONSchema

func (InsightProvenance) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (InsightProvenance) String

func (p InsightProvenance) String() string

String returns the wire representation of the insight provenance.

func (InsightProvenance) Validate

func (p InsightProvenance) Validate() error

Validate rejects values that cannot cross the insight-provenance wire boundary.

type InteractionType

type InteractionType string

InteractionType classifies how deeply a session engaged with a file.

const (
	InteractionMentioned  InteractionType = "mentioned"
	InteractionRead       InteractionType = "read"
	InteractionDiscussed  InteractionType = "discussed"
	InteractionQuestioned InteractionType = "questioned"
)

func (InteractionType) IsValid

func (i InteractionType) IsValid() bool

IsValid reports whether i is a defined interaction type.

func (InteractionType) JSONSchema

func (InteractionType) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (InteractionType) String

func (i InteractionType) String() string

type InvalidRefCategory

type InvalidRefCategory struct {
	Category    string              `yaml:"category"`
	ErrContains string              `yaml:"err_contains"`
	Cases       []InvalidRefSubcase `yaml:"cases"`
}

InvalidRefCategory is a group of explicit reject cases sharing an expected error substring (attached to the category; a case may override it).

type InvalidRefSubcase

type InvalidRefSubcase struct {
	Name        string `yaml:"name"`
	Input       string `yaml:"input,omitempty"`
	Template    string `yaml:"template,omitempty"`
	ErrContains string `yaml:"err_contains,omitempty"` // overrides category default
}

InvalidRefSubcase is one reject case. Exactly one of Input/Template is set.

type License

type License string

License is the content license a contributor selects for a published transcript. Closed menu: the village `licenses` table (its migration 026) carries each license's obligations, and the peasant local store mirrors the set in a CHECK (migration v37). This is the single source of truth for the menu on the publish/pull wire.

const (
	LicenseCC0    License = "CC0-1.0"
	LicenseCCBY   License = "CC-BY-4.0"
	LicenseCCBYSA License = "CC-BY-SA-4.0"
)

func (License) IsValid

func (l License) IsValid() bool

IsValid reports whether the license is one of the known menu entries.

func (License) JSONSchema

func (License) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (License) String

func (l License) String() string

type MapEdge

type MapEdge struct {
	From  string `json:"from"` // node ID
	To    string `json:"to"`
	Count int    `json:"count"` // underlying import count (aggregated)
}

MapEdge is a structure (import) dependency between two nodes.

type MapGraphPayload

type MapGraphPayload struct {
	ProjectHash     ProjectHash     `json:"projectHash"`
	RepoFound       bool            `json:"repoFound"` // canonical_cwd resolved to a git repo
	RepoPath        string          `json:"repoPath,omitempty"`
	ParsedLanguages []string        `json:"parsedLanguages"` // e.g. ["go","typescript"]; empty => activity-only
	Nodes           []MapNode       `json:"nodes"`           // all zoom levels; parent links form the tree
	StructureEdges  []MapEdge       `json:"structureEdges"`  // parsed imports, aggregated per node pair
	ActivityEdges   []ActivityEdge  `json:"activityEdges"`   // co-EDIT observations
	Violations      []EdgeViolation `json:"violations"`      // cycles + wrong-way edges
	GeneratedAtMs   int64           `json:"generatedAtMs"`
	AtCommit        string          `json:"atCommit,omitempty"` // set when ?commit= was used
}

MapGraphPayload is the full map graph for one project, served by GET /api/v1/map/{projectHash}.

func NewMapGraphPayload

func NewMapGraphPayload(projectHash ProjectHash) *MapGraphPayload

NewMapGraphPayload returns a MapGraphPayload with all slices initialized to empty (never-nil marshal guarantee).

type MapNode

type MapNode struct {
	ID            string      `json:"id"`               // repo-relative path ("internal/ingest", "web/src/lib/api.ts")
	Parent        string      `json:"parent,omitempty"` // ID of parent node ("" for top-level modules)
	Kind          MapNodeKind `json:"kind"`
	Name          string      `json:"name"` // display leaf ("ingest")
	Language      string      `json:"language,omitempty"`
	Layer         int         `json:"layer"`         // 0 = top row; deterministic
	Order         int         `json:"order"`         // stable sort within layer
	Loc           int         `json:"loc"`           // size metric (lines)
	FileCount     int         `json:"fileCount"`     // 1 for files
	RecordedFiles int         `json:"recordedFiles"` // files whose last edit is attributable to a recorded session
	TotalFiles    int         `json:"totalFiles"`
	TouchCount    int         `json:"touchCount"`    // recorded edits in window (activity size metric)
	EffortDensity float64     `json:"effortDensity"` // 0..1 per-file re-edit/error density rollup (0 when unknown)

	// AgentEditedCount / ReadCount / ReadAttribution are the node-grain
	// comprehension signals behind the ranked entry list's tri-state debt
	// tag. ReadAttribution is the honesty field:
	// a zero ReadCount is "unavailable" (no recoverable per-file read
	// attribution for any editing session), "partial" (some do), or
	// "complete" (all do) - never silently indistinguishable from unread.
	AgentEditedCount int                  `json:"agentEditedCount"`
	ReadCount        int                  `json:"readCount"`
	ReadAttribution  ReadAttributionState `json:"readAttribution" required:"true"`

	// ReadState is the composed effective read-state grade for the node's
	// current content version. ChangedRegionCount
	// / AttributedRegionCount / ReviewedRegionCount are the minimal per-node
	// region-coverage counts over that same current version: total changed
	// hunks, hunks the server could attribute to a producing turn, and
	// attributed hunks whose producing turn carries a reviewed+ grade. They
	// supply the client's hunk-linked hover ("N of M changed regions
	// reviewed"). All are server-computed; the client-side debt
	// derivation stays a pure function over these MapNode scalars.
	ReadState             ReadStateGrade `json:"readState" required:"true"`
	ChangedRegionCount    int            `json:"changedRegionCount"`
	AttributedRegionCount int            `json:"attributedRegionCount"`
	ReviewedRegionCount   int            `json:"reviewedRegionCount"`
}

MapNode is one square card on the map: a module, package, or file.

func (MapNode) Validate

func (n MapNode) Validate() error

Validate checks a MapNode's closed-set fields fail closed. It does not check cross-region-count consistency (e.g. ReviewedRegionCount <= AttributedRegionCount <= ChangedRegionCount); those are producer-side invariants, not wire shape rules.

type MapNodeDetailPayload

type MapNodeDetailPayload struct {
	Path          string      `json:"path"`
	Kind          MapNodeKind `json:"kind"`
	Language      string      `json:"language,omitempty"` // e.g. "go", "typescript"; "" for activity-only nodes
	Loc           int         `json:"loc"`
	RecordedFiles int         `json:"recordedFiles"`
	TotalFiles    int         `json:"totalFiles"`
	SessionCount  int         `json:"sessionCount"`
	TaskCount     int         `json:"taskCount"`
	LastTouchMs   *int64      `json:"lastTouchMs,omitempty"`
	// DependsOn / UsedBy are the node's structural role, derived deterministically
	// from the parsed import graph (what this area does): the node IDs
	// this node imports, and those that import it. Most-connected first, capped.
	// Empty when there is no parsed graph (activity-only) or no edges.
	DependsOn     []string      `json:"dependsOn"`
	UsedBy        []string      `json:"usedBy"`
	ShapedBy      []TaskSummary `json:"shapedBy"`          // most recent first, cap 20
	RecentCommits []CommitRef   `json:"recentCommits"`     // touching this node, cap 10
	RetryLoops    int           `json:"retryLoops"`        // summed over touching sessions
	ReEdits       int           `json:"reEdits"`           // re-edited files within this node
	CostUsd       *float64      `json:"costUsd,omitempty"` // nil when unknown
	// RewrittenCommits lists ghost commits touching this node. It is empty when
	// the resolver found no ghosts here.
	RewrittenCommits []RewrittenCommit `json:"rewrittenCommits" required:"true" nullable:"false"`
	// Insights carries mechanical and mined insight envelopes for this node.
	// It is additive alongside the per-change Unusual/Frictions signals, never
	// a replacement for them.
	Insights []SessionInsight `json:"insights" required:"true" nullable:"false"`
}

MapNodeDetailPayload backs the node rail panel, served by GET /api/v1/map/{projectHash}/node?path=<id>.

func NewMapNodeDetailPayload

func NewMapNodeDetailPayload(path string) *MapNodeDetailPayload

NewMapNodeDetailPayload returns a MapNodeDetailPayload with all slices initialized to empty (never-nil marshal guarantee).

func (MapNodeDetailPayload) Validate

func (p MapNodeDetailPayload) Validate() error

Validate checks the additive rewrite and insight invariants: slices are non-nil, every RecentCommit and RewrittenCommit is well-formed, every RewrittenCommit's SuccessorHash (when set) is present in RecentCommits, shared successor and ledger associations are identical, and every SessionInsight is well-formed (including the Classification-must-be-nil rule). Unlike ReviewListPayload, a node detail payload carries no independent session table, so RewrittenCommits.SessionIDs are checked for well-formedness only (not cross-referenced against a session list this payload does not have).

type MapNodeKind

type MapNodeKind string

MapNodeKind classifies a map node within the path-derived tree.

const (
	MapNodeKindModule  MapNodeKind = "module"
	MapNodeKindPackage MapNodeKind = "package"
	MapNodeKindFile    MapNodeKind = "file"
)

MapNodeKind values. Top-level directories are modules, nested directories are packages, and files are leaves (mirrors codegraph's node kinds).

func (MapNodeKind) IsValid

func (k MapNodeKind) IsValid() bool

IsValid reports whether k is one of the defined node kinds.

func (MapNodeKind) JSONSchema

func (MapNodeKind) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (MapNodeKind) String

func (k MapNodeKind) String() string

String returns the wire representation of the node kind.

type MapSlice

type MapSlice struct {
	Nodes          []MapNode      `json:"nodes"` // layer/order preserved from full map
	StructureEdges []MapEdge      `json:"structureEdges"`
	ActivityEdges  []ActivityEdge `json:"activityEdges"`
}

MapSlice is a scoped sub-map: the touched nodes plus their one-hop neighborhood, with layer/order preserved from the full map.

func NewMapSlice

func NewMapSlice() MapSlice

NewMapSlice returns a MapSlice with all slices initialized to empty (never-nil marshal guarantee).

type MessageType

type MessageType string

MessageType represents the type discriminator for WebSocket messages.

const (
	MsgSubscribe          MessageType = "subscribe"
	MsgUnsubscribe        MessageType = "unsubscribe"
	MsgDashboard          MessageType = "dashboard"
	MsgSessions           MessageType = "sessions"
	MsgSessionDetail      MessageType = "session_detail"
	MsgTrends             MessageType = "trends"
	MsgQuality            MessageType = "quality"
	MsgAnnotations        MessageType = "annotations"
	MsgProjectFamiliarity MessageType = "project_familiarity"
	MsgConnected          MessageType = "connected"
	MsgError              MessageType = "error"
)

func (MessageType) IsValid

func (m MessageType) IsValid() bool

IsValid reports whether m is a defined WebSocket message discriminator.

func (MessageType) JSONSchema

func (MessageType) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (MessageType) String

func (m MessageType) String() string

String returns the wire representation of the message discriminator.

type MockConfigResponse

type MockConfigResponse struct {
	Enabled bool     `json:"enabled"`
	Web     []string `json:"web,omitempty"`
	TUI     []string `json:"tui,omitempty"`
	API     []string `json:"api,omitempty"`
}

MockConfigResponse is the JSON response for GET /api/v1/config/mock.

type ModelID

type ModelID string

ModelID identifies a specific model version (e.g. "claude-opus-4-6").

func NewModelID

func NewModelID(raw string) (ModelID, error)

NewModelID validates and constructs a ModelID.

func (ModelID) JSONSchema

func (ModelID) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (ModelID) String

func (m ModelID) String() string

type ModelInfo

type ModelInfo struct {
	Harness        Harness  `json:"harness" required:"true"`
	Model          ModelID  `json:"model" required:"true"`
	HarnessVersion string   `json:"version,omitempty"`
	HostSlug       HostSlug `json:"hostSlug,omitempty"`
}

ModelInfo holds harness and model version information for a session. JSON tags use camelCase to match CLI UnifiedMetadata wire format. The harness is keyed json:"harness" (emit-side flip; was json:"modelHarness").

rc2 (#118): Harness and Model carry required:"true" so swaggest emits a SchemaModelInfo.required:["harness","model"] array — the village rejects a model object missing either key (the harness/model-within-model contract). Metadata only: these tags change the GENERATED schema's `required`, not the Go wire shape.

type NegativeLookalike

type NegativeLookalike struct {
	Name        string `yaml:"name"`
	Template    string `yaml:"template"`
	ErrContains string `yaml:"err_contains"`
}

NegativeLookalike is a first-class reject case that LOOKS valid (e.g. a URL whose last path segment is a UUID but whose path is not the canonical /transcripts/<uuid> shape). ParseTranscriptRef rejects all of these, so each asserts LIVE in the InvalidCases loop.

type ProjectContext

type ProjectContext struct {
	Hash     ProjectHash `json:"hash"`               // SHA-256 of project origin URL or path
	FilePath string      `json:"filePath,omitempty"` // Local repo path
	Name     string      `json:"name"`               // Repo basename
}

ProjectContext identifies the project associated with a session.

type ProjectHash

type ProjectHash string

ProjectHash is a SHA-256 hex digest of the project's origin URL or local path.

func NewProjectHash

func NewProjectHash(raw string) (ProjectHash, error)

NewProjectHash validates and constructs a ProjectHash.

func (ProjectHash) JSONSchema

func (ProjectHash) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (ProjectHash) String

func (p ProjectHash) String() string

func (ProjectHash) Validate

func (p ProjectHash) Validate() error

Validate reports whether p is the canonical 64-character lowercase hex project identity accepted at wire boundaries.

type ProjectResolutionPayload

type ProjectResolutionPayload struct {
	Project     string      `json:"project" required:"true"`
	ProjectHash ProjectHash `json:"projectHash" required:"true"`
}

ProjectResolutionPayload resolves one explicitly requested project display identity to its opaque hash without enumerating sibling projects. It exists for stable deep links when discovery lists are narrowed by user selection.

type ProjectSummariesPayload

type ProjectSummariesPayload struct {
	Projects []ProjectSummary `json:"projects"`
}

ProjectSummariesPayload backs the home project picker, served by GET /api/v1/projects/summary.

func NewProjectSummariesPayload

func NewProjectSummariesPayload() *ProjectSummariesPayload

NewProjectSummariesPayload returns a ProjectSummariesPayload with all slices initialized to empty (never-nil marshal guarantee).

type ProjectSummary

type ProjectSummary struct {
	ProjectHash   ProjectHash `json:"projectHash"`
	Project       string      `json:"project"`       // display name (canonical cwd, else the hash)
	Sessions      int         `json:"sessions"`      // recorded session count
	RecordedFiles int         `json:"recordedFiles"` // coverage numerator (same rule as MapNode)
	TotalFiles    int         `json:"totalFiles"`    // coverage denominator
	LastWorkMs    *int64      `json:"lastWorkMs,omitempty"`
	OpenChanges   int         `json:"openChanges"` // local non-default branches not merged (0 when no repo)
}

ProjectSummary is one row of the home picker: a project with its recorded stats (sessions · recorded coverage · last work · open changes).

type ProjectTasksPayload

type ProjectTasksPayload struct {
	ProjectHash ProjectHash   `json:"projectHash"`
	Tasks       []TaskSummary `json:"tasks"` // reverse-chronological, cap 500
	FileFilter  string        `json:"fileFilter,omitempty"`
}

ProjectTasksPayload backs the Tasks lens, served by GET /api/v1/map/{projectHash}/tasks?file=<path>.

func NewProjectTasksPayload

func NewProjectTasksPayload(projectHash ProjectHash) *ProjectTasksPayload

NewProjectTasksPayload returns a ProjectTasksPayload with all slices initialized to empty (never-nil marshal guarantee).

type Provenance

type Provenance struct {
	Method   string            `json:"method"` // "heuristic", "regex", "llm_judge", "manual"
	Function string            `json:"function,omitempty"`
	Version  string            `json:"version,omitempty"`
	Details  map[string]string `json:"details,omitempty"`
}

Provenance records how a non-human annotator derived its annotation value. Only populated for rule-based and agent annotators; nil for human annotations.

type PublishRequest

type PublishRequest struct {
	Identity    SessionIdentity `json:"identity"`
	Model       ModelInfo       `json:"model" required:"true"`
	Timestamp   TimestampInfo   `json:"timestamp"`
	Source      SourceInfo      `json:"source"`
	Git         GitContext      `json:"git"`
	Project     ProjectContext  `json:"project"`
	Stats       SessionStats    `json:"stats"`
	Quality     *QualityMetrics `json:"quality,omitempty"`
	Entries     []SessionEntry  `json:"entries,omitempty"`
	Subagents   []SubagentRef   `json:"subagents,omitempty"`
	Diagnostics DiagnosticsInfo `json:"diagnostics"`
	// License is the content license the contributor selected for this transcript
	// (CC0-1.0 / CC-BY-4.0 / CC-BY-SA-4.0). Optional — omitempty ⇒ a publish with no
	// license stores NULL (legacy/un-set). The village persists it to
	// transcripts.license_id; the vendored schema enum makes an invalid value a
	// documented schema-422. NOT `required` (keeps the Village publish body required set at [model]).
	License License `json:"license,omitempty"`
}

PublishRequest is the canonical wire type for CLI → Village upload. The CLI sends this; the village validates and persists it.

Uses nested composites for logical grouping. The JSON tags on each composite struct preserve CLI wire compatibility — the top-level keys are identity, model, timestamp, source, git, project, stats, quality, subagents, and diagnostics.

MIGRATION NOTE: The CLI's current flat UnifiedMetadata will need a coordinated update to send this nested structure. This is NOT backward-compatible with the current village handler — both CLI and village must update together.

The Village operation-specific publish component requires model, so a body without it is rejected; this changes generated validation requiredness, not the canonical Go wire shape.

type PublishResponse

type PublishResponse struct {
	TranscriptID  string `json:"transcriptId"`  // Server-generated UUID
	BlobKey       string `json:"blobKey"`       // S3 storage path
	BlobSizeBytes int64  `json:"blobSizeBytes"` // Uploaded file size in bytes
	PublishedAt   int64  `json:"publishedAt"`   // Unix millis
	UpdatedAt     int64  `json:"updatedAt"`     // Unix millis
	Created       bool   `json:"created"`       // true if new, false if updated
}

PublishResponse is returned by the village after successful publish.

type PublishVerdictCase

type PublishVerdictCase struct {
	Name   string                    `yaml:"name"`
	Body   string                    `yaml:"body"`
	Expect PublishVerdictExpectation `yaml:"expect"`
}

PublishVerdictCase is one concrete publish body and its schema/HTTP verdict.

func (PublishVerdictCase) ModelHarness

func (c PublishVerdictCase) ModelHarness() (string, bool, error)

ModelHarness returns body.model.harness when the case body contains one.

type PublishVerdictExpectation

type PublishVerdictExpectation struct {
	SchemaAccepts bool   `yaml:"schema_accepts"`
	LegacyAccepts *bool  `yaml:"legacy_accepts,omitempty"`
	HTTPStatus    int    `yaml:"http_status,omitempty"`
	ErrorCategory string `yaml:"error_category,omitempty"`
	ErrorContains string `yaml:"error_contains,omitempty"`
}

PublishVerdictExpectation attaches expected outcomes to a publish verdict row.

type PublishVerdictFixtures

type PublishVerdictFixtures struct {
	Cases []PublishVerdictCase `yaml:"cases"`
}

PublishVerdictFixtures is the parsed testdata/publish/verdicts.yaml corpus.

func LoadPublishVerdictFixtures

func LoadPublishVerdictFixtures() (*PublishVerdictFixtures, error)

LoadPublishVerdictFixtures parses PublishVerdictsYAML into structured fixtures.

func (*PublishVerdictFixtures) Acceptances

func (f *PublishVerdictFixtures) Acceptances() []PublishVerdictCase

Acceptances returns the corpus rows the schema MUST accept (schema_accepts:true). It is the accept-pass input to RunPublishVerdicts; together with Rejections it partitions Cases exactly (the partition-completeness guard in RunPublishVerdicts depends on len(Acceptances)+len(Rejections)==len(Cases)).

func (*PublishVerdictFixtures) CaseByName

func (f *PublishVerdictFixtures) CaseByName(name string) (PublishVerdictCase, bool)

CaseByName returns the verdict row with the given stable name.

func (*PublishVerdictFixtures) Rejections

func (f *PublishVerdictFixtures) Rejections() []PublishVerdictCase

Rejections returns the corpus rows the schema MUST reject (schema_accepts:false). It is the reject-pass input to RunPublishVerdicts (see Acceptances).

type PullAnnotation

type PullAnnotation struct {
	AnnotationSummary        // embedded existing summary (annotator entity, content hash, etc.)
	AuthorUserID      string `json:"authorUserId"`
	AuthorUsername    string `json:"authorUsername"`
}

PullAnnotation is the authored-annotation row for the pull surface (GET /api/v1/pull/transcripts/{id}/annotations). It embeds the existing AnnotationSummary and adds the village account identity (AuthorUserID / AuthorUsername) the summary does not carry — required to foreign-mark pulled annotations and to exclude the requester's own authored rows during the annotation-refresh path (creds.UserID == AuthorUserID).

type PullListResponse

type PullListResponse struct {
	Transcripts []PullTranscriptInfo `json:"transcripts"`
	Page        int                  `json:"page"`
	Limit       int                  `json:"limit"`
	Total       int                  `json:"total"`
}

PullListResponse is the village's paginated listing of pullable transcripts (GET /api/v1/pull/transcripts) — own + group-shared (public excluded by the canPullTranscript policy).

type PullRefFixtures

type PullRefFixtures struct {
	Values            PullRefValues        `yaml:"values"`
	IDCasings         []IDCasing           `yaml:"id_casings"`
	RefForms          []RefForm            `yaml:"ref_forms"`
	ValidGeneration   ValidGeneration      `yaml:"valid_generation"`
	InvalidRefs       []InvalidRefCategory `yaml:"invalid_refs"`
	NegativeLookalike []NegativeLookalike  `yaml:"negative_lookalikes"`
}

PullRefFixtures is the top-level parsed transcript_refs.yaml structure.

func LoadPullRefFixtures

func LoadPullRefFixtures() (*PullRefFixtures, error)

LoadPullRefFixtures parses PullRefsYAML into structured fixtures. Mirrors LoadAnnotationFixtures.

func (*PullRefFixtures) AllCases

func (f *PullRefFixtures) AllCases() ([]RefCase, error)

AllCases is ValidCases followed by InvalidCases — the full materialised suite internal/pull/types_test.go ranges over.

func (*PullRefFixtures) InvalidCases

func (f *PullRefFixtures) InvalidCases() ([]RefCase, error)

InvalidCases materialises the explicit invalid_refs plus the negative_lookalikes. Every case expects an error with the category/case-attached substring.

func (*PullRefFixtures) UUIDLower

func (f *PullRefFixtures) UUIDLower() string

UUIDLower returns the canonical lowercase UUID the fixture owns (== testutil TestTranscriptUUID).

func (*PullRefFixtures) ValidCases

func (f *PullRefFixtures) ValidCases() ([]RefCase, error)

ValidCases materialises the valid cross-product (id_casings x ref_forms) with the generator-attached expectation: every case parses, normalizes its ID to values.uuid_lower, and reports FromURL per its ref_form.

func (*PullRefFixtures) VillageHost

func (f *PullRefFixtures) VillageHost() string

VillageHost returns the canonical village host the fixture owns (== testutil TestVillageHost).

type PullRefValues

type PullRefValues struct {
	UUIDLower   string `yaml:"uuid_lower"`
	VillageHost string `yaml:"village_host"`
}

PullRefValues are the self-contained canonical strings the fixture owns. They are ADOPTED VERBATIM from internal/testutil (which re-exports them), so the fixture is the single source of truth with zero behaviour change.

type PullSkipGateItem

type PullSkipGateItem struct {
	// The id of a transcript the client holds and is asking about.
	TranscriptID TranscriptID `json:"transcriptId" description:"The id of a transcript the client holds and is asking about."`
	// Hex-encoded SHA3-256 content-hash the client currently holds for this
	// transcript's served blob; compared by VALUE against the server's stored hash
	// to decide contentCurrent.
	ContentHash string `` /* 178-byte string literal not displayed */
	// The client's OWN annotation content-hashes for this transcript (the set it
	// already has locally). Compared as a SET against the owner-scoped server set to
	// decide annotationsCurrent. NewPullSkipGateRequest sorts + de-duplicates it, so it
	// is always a (possibly empty) NON-null array.
	AnnotationHashes []string `` /* 197-byte string literal not displayed */
}

PullSkipGateItem is one transcript the client holds and wants a currency answer for: the transcript id, the content-hash the client currently has for it, and the set of annotation content-hashes the client itself holds for that transcript.

type PullSkipGateRequest

type PullSkipGateRequest struct {
	// The per-transcript items the client is asking a currency question about.
	// NewPullSkipGateRequest orders them by transcriptId and never returns nil, so the
	// wire is a canonical, (possibly empty) NON-null array.
	Items []PullSkipGateItem `` /* 181-byte string literal not displayed */
}

PullSkipGateRequest is the body a pulling client POSTs to the pull skip-gate endpoint. For each transcript it already holds, the client sends the id plus the content-hash it holds and its OWN annotation-hash set for that id, so the server can answer, per id, whether the stored transcript and the client's annotations are still current, letting the client skip re-downloading what has not diverged. Only the client's held HASHES travel, never content, so the request is privacy-safe.

This type is ADDITIVE: it introduces a new endpoint's request shape and does not alter any existing pull/publish/annotation-push wire contract.

func NewPullSkipGateRequest

func NewPullSkipGateRequest(items []PullSkipGateItem) PullSkipGateRequest

NewPullSkipGateRequest builds a CANONICAL skip-gate request: each item's annotation-hash set is sorted + de-duplicated (the server compares it as a SET, so order and multiplicity are irrelevant), and the items are ordered by transcriptId. Provided the request's transcript ids are UNIQUE, two clients asking about the same logical state emit byte-identical requests: the items are ordered with an unstable sort on transcriptId, so byte-identity holds only when that key has no ties (one item per transcript id, which a well-formed request satisfies). Every item's AnnotationHashes is a non-null array.

type PullSkipGateResponse

type PullSkipGateResponse struct {
	// The per-id currency answers, present ONLY for pullable ids (non-pullable ids
	// are omitted; see the type doc). NewPullSkipGateResponse orders them by
	// transcriptId and never returns nil, so the wire is a canonical, (possibly
	// empty) NON-null array.
	Results []PullSkipGateResult `` /* 170-byte string literal not displayed */
}

PullSkipGateResponse is the per-id currency answer for a PullSkipGateRequest.

LEAK-FREE WITHHELD SEMANTICS: Results carries an entry ONLY for transcript ids the caller may PULL. A non-pullable id is OMITTED from Results entirely, never echoed with a "denied" or "unknown" marker, because any per-id echo would itself be an existence / currency oracle over arbitrary ids the caller cannot pull. So the caller sends N ids and receives <= N results; an ABSENT id means "unanswered / withheld", the 404-not-403 anti-enumeration spirit applied to a batch currency probe.

This is enforced in two distinct places. The RESPONSE SHAPE carries no denial or marker field a withheld id could ride on: it is exactly {results: [{transcriptId, contentCurrent, annotationsCurrent}]}, checked by this module's exact-key-set response test, so adding and populating a wire-visible extra field reddens the assertion. An inert zero-valued `omitempty` field is not emitted and is outside this check. The actual OMISSION of non-pullable ids from Results is the village handler's pull-scoping test, since only the server knows which ids are pullable; this constructor merely canonicalizes the entries it is given and never invents one.

This type is ADDITIVE: it introduces a new endpoint's response shape and does not alter any existing pull/publish/annotation-push wire contract.

func NewPullSkipGateResponse

func NewPullSkipGateResponse(results []PullSkipGateResult) PullSkipGateResponse

NewPullSkipGateResponse builds a CANONICAL skip-gate response from the per-id answers the server computed for the PULLABLE ids ONLY. Non-pullable ids must already be omitted by the caller (see PullSkipGateResponse's leak-free contract); this constructor does not invent entries. Results are ordered by transcriptId so the wire payload is deterministic, PROVIDED the response's transcript ids are UNIQUE: the results are ordered with an unstable sort on transcriptId, so determinism holds only when that key has no ties (one result per pullable id, which the pull-scope answer satisfies). The slice is never nil.

type PullSkipGateResult

type PullSkipGateResult struct {
	// The transcript id this answer is for (always one the caller may pull).
	TranscriptID TranscriptID `json:"transcriptId" description:"The transcript id this currency answer is for (always one the caller may pull)."`
	// True when the server's stored served-blob content-hash equals the hash the
	// client sent for this id; false when it has diverged (or the server holds none).
	ContentCurrent bool `` /* 174-byte string literal not displayed */
	// True when the owner-scoped annotation set the server holds for this id equals
	// the client's held annotation set; false when it differs (missing or extra).
	AnnotationsCurrent bool `` /* 172-byte string literal not displayed */
}

PullSkipGateResult is the currency answer for one PULLABLE transcript id: whether the stored blob still matches the client's held content-hash, and whether the owner-scoped annotation set still matches the client's held annotation set.

type PullStatusFixtures

type PullStatusFixtures struct {
	Statuses []PullStatusMapping `yaml:"statuses"`
}

PullStatusFixtures is the parsed pull_statuses.yaml structure.

func LoadPullStatusFixtures

func LoadPullStatusFixtures() (*PullStatusFixtures, error)

LoadPullStatusFixtures parses PullStatusesYAML into structured fixtures.

func (*PullStatusFixtures) WireFor

func (f *PullStatusFixtures) WireFor(constName string) (string, bool)

WireFor returns the expected wire string for a given const_name, or "".

type PullStatusMapping

type PullStatusMapping struct {
	Name      string `yaml:"name"`
	ConstName string `yaml:"const_name"`
	Wire      string `yaml:"wire"`
}

PullStatusMapping is one PullStatus<->wire row.

type PullTranscriptInfo

type PullTranscriptInfo struct {
	TranscriptID    TranscriptID    `json:"transcriptId"`
	LocalID         string          `json:"localId,omitempty"` // peasant SessionID at publish — round-trip correlation
	OwnerUserID     string          `json:"ownerUserId"`
	OwnerUsername   string          `json:"ownerUsername"`
	Title           string          `json:"title,omitempty"`
	Harness         Harness         `json:"harness,omitempty"` // existing typed form
	ProjectName     string          `json:"projectName,omitempty"`
	Visibility      Visibility      `json:"visibility"`                // existing typed form
	License         License         `json:"license,omitempty"`         // legal axis; omitempty ⇒ legacy/un-set
	ContentHash     string          `json:"contentHash,omitempty"`     // SERVED-BLOB hash; empty ⇒ server has none
	ContractVersion ContractVersion `json:"contractVersion,omitempty"` // push contract the blob was published under
	PublishedAt     int64           `json:"publishedAt"`
	UpdatedAt       int64           `json:"updatedAt"`
	AnnotationCount int             `json:"annotationCount"`
}

PullTranscriptInfo is the village's metadata view of a single pullable transcript (GET /api/v1/pull/transcripts/{id}). ContentHash is the SERVER-COMPUTED hash of the served blob bytes (empty when the village has not yet computed one), and is distinct from UnifiedMetadata.ContentHash (the ingest-time, pre-push-redaction hash). ContractVersion records the push content contract the blob was published under (the blob carries its own publish-time version; the pull envelope does not version the blob).

type PushContractVersion

type PushContractVersion = ContractVersion

PushContractVersion is a zero-churn alias for ContractVersion kept for the push axis. Existing references (SchemaVersionResponse push fields, the defaults push constants) keep compiling unchanged; new code may use either name (they are the identical type).

type QualityFixtureName

type QualityFixtureName string
const (
	QualityFixtureResolvedTypical    QualityFixtureName = "resolved_typical"
	QualityFixtureResolvedHighTokens QualityFixtureName = "resolved_high_tokens"
	QualityFixturePartialMedium      QualityFixtureName = "partial_medium"
	QualityFixtureFailedComplex      QualityFixtureName = "failed_complex"
	QualityFixtureResolvedMinimal    QualityFixtureName = "resolved_minimal"
)

type QualityFixtureSet

type QualityFixtureSet struct {
	Name  QualityFixtureSetName `json:"name" yaml:"name"`
	Cases []QualityFixtureName  `json:"cases" yaml:"cases"`
}

QualityFixtureSet is a named reusable list of quality-session fixture rows.

type QualityFixtureSetName

type QualityFixtureSetName string
const (
	QualityFixtureSetProjectMix QualityFixtureSetName = "project_mix"
)

type QualityFixtures

type QualityFixtures struct {
	Sessions   []QualitySessionFixture `json:"sessions" yaml:"quality_sessions"`
	Sets       []QualityFixtureSet     `json:"sets" yaml:"quality_fixture_sets"`
	Variations QualityVariations       `json:"variations" yaml:"quality_variations"`
}

QualityFixtures is the parsed testdata/quality/sessions.yaml corpus.

func LoadQualityFixtures

func LoadQualityFixtures() (*QualityFixtures, error)

LoadQualityFixtures parses QualitySessionsYAML into structured fixtures.

func (*QualityFixtures) QualitySessions

func (f *QualityFixtures) QualitySessions() []QualitySession

QualitySessions returns all quality-session fixtures as wire payload rows.

func (*QualityFixtures) QualitySessionsForSet

func (f *QualityFixtures) QualitySessionsForSet(name QualityFixtureSetName) ([]QualitySession, error)

QualitySessionsForSet returns a named fixture set as wire payload rows.

func (*QualityFixtures) SessionByName

SessionByName returns the named quality-session fixture row.

func (*QualityFixtures) SetByName

SetByName returns the named quality fixture set.

type QualityMetricVariation

type QualityMetricVariation struct {
	Name  string  `json:"name" yaml:"name"`
	Value float64 `json:"value" yaml:"value"`
}

type QualityMetricVariations

type QualityMetricVariations struct {
	RetryLoops       []QualityMetricVariation `json:"retryLoops" yaml:"retry_loops"`
	SignalDensity    []QualityMetricVariation `json:"signalDensity" yaml:"signal_density"`
	SpecQualityScore []QualityMetricVariation `json:"specQualityScore" yaml:"spec_quality_score"`
	FilesTouched     []QualityMetricVariation `json:"filesTouched" yaml:"files_touched"`
	LinesChanged     []QualityMetricVariation `json:"linesChanged" yaml:"lines_changed"`
}

type QualityMetrics

type QualityMetrics struct {
	// Basic session counts
	TurnCount            *int            `json:"turnCount,omitempty"`
	SubagentCount        *int            `json:"subagentCount,omitempty"`
	TotalTokens          *int            `json:"totalTokens,omitempty"`
	InputTokens          *int            `json:"inputTokens,omitempty"`
	OutputTokens         *int            `json:"outputTokens,omitempty"`
	ToolCalls            *int            `json:"toolCalls,omitempty"`
	TitleGenerated       *string         `json:"titleGenerated,omitempty"`
	Outcome              *SessionOutcome `json:"outcome,omitempty"`
	FilesTouched         *int            `json:"filesTouched,omitempty"`
	LinesChanged         *int            `json:"linesChanged,omitempty"`
	RetryLoops           *int            `json:"retryLoops,omitempty"`
	RetryTokensWasted    *int            `json:"retryTokensWasted,omitempty"`
	WithinSessionReverts *int            `json:"withinSessionReverts,omitempty"`
	SignalDensity        *float64        `json:"signalDensity,omitempty"`
	SpecQualityScore     *float64        `json:"specQualityScore,omitempty"`
	ExplorationRatio     *float64        `json:"explorationRatio,omitempty"`
	ScopeBreadth         *int            `json:"scopeBreadth,omitempty"`
	DiscoveryTurns       *int            `json:"discoveryTurns,omitempty"`
	DurationMinutes      *float64        `json:"durationMinutes,omitempty"`
	// M-series advanced metrics (v2 computed)
	M2TokenOutcomeRatio     *float64 `json:"m2TokenOutcomeRatio,omitempty"`
	M3UniqueToolCount       *int     `json:"m3UniqueToolCount,omitempty"`
	M4ErrorRecoveryCount    *int     `json:"m4ErrorRecoveryCount,omitempty"`
	M4ConsecutiveErrorMax   *int     `json:"m4ConsecutiveErrorMax,omitempty"`
	M5ContextUtilizationPct *float64 `json:"m5ContextUtilizationPct,omitempty"`
	M5PeakContextTokens     *int     `json:"m5PeakContextTokens,omitempty"`
	M5AvgMessageTokens      *int     `json:"m5AvgMessageTokens,omitempty"`
	M6OutputSurvivalPct     *float64 `json:"m6OutputSurvivalPct,omitempty"`
	M6LinesSurvived         *int     `json:"m6LinesSurvived,omitempty"`
	M6LinesTotal            *int     `json:"m6LinesTotal,omitempty"`
	M7SpecWordCount         *int     `json:"m7SpecWordCount,omitempty"`
	M7SpecHasExamples       *bool    `json:"m7SpecHasExamples,omitempty"`
	M7SpecHasConstraints    *bool    `json:"m7SpecHasConstraints,omitempty"`
	// v3 cost analytics
	CostInputUSD      *float64 `json:"costInputUsd,omitempty"`
	CostOutputUSD     *float64 `json:"costOutputUsd,omitempty"`
	CostReasoningUSD  *float64 `json:"costReasoningUsd,omitempty"`
	CostCacheReadUSD  *float64 `json:"costCacheReadUsd,omitempty"`
	CostCacheWriteUSD *float64 `json:"costCacheWriteUsd,omitempty"`
	CostTotalUSD      *float64 `json:"costTotalUsd,omitempty"`
	CostModelID       *string  `json:"costModelId,omitempty"`
	// v3 scope classification
	Scope *string `json:"scope,omitempty"`
	// Compute metadata
	ComputedAt     *int64 `json:"computedAt,omitempty"`     // Unix millis
	ComputeVersion *int   `json:"computeVersion,omitempty"` // 0=v1 migrated, 1+=v2 computed
}

QualityMetrics holds session statistics and derived quality signals for a session. The type name is intentionally broad post-unification: it covers two distinct groups.

Group A — Basic session stats (TurnCount, SubagentCount, TotalTokens, InputTokens, OutputTokens, ToolCalls, TitleGenerated, Outcome, DurationMinutes): populated for all fully-ingested sessions; a nil value here indicates the session has not been fully ingested.

Group B — Derived quality signals (FilesTouched, LinesChanged, RetryLoops, M-series fields, SignalDensity, SpecQualityScore, ExplorationRatio, etc.): populated only when quality analysis has run. Nil = "not computed" — analysis may not have been performed yet.

All fields are pointers with omitempty so that serialisation omits fields that have not been populated, regardless of which group they belong to. JSON tags use camelCase to match the backend data contract (QualitySession) field names.

type QualityPayload

type QualityPayload struct {
	Sessions []QualitySession `json:"sessions"`
}

QualityPayload is the data sent on the quality WebSocket channel.

type QualityRatioVariation

type QualityRatioVariation struct {
	Name       string  `json:"name" yaml:"name"`
	InputRatio float64 `json:"inputRatio" yaml:"inputRatio"`
}

type QualitySession

type QualitySession struct {
	ID              string  `json:"id"`
	Date            string  `json:"date"` // "2006-01-02" format
	Project         string  `json:"project"`
	TotalTokens     int     `json:"totalTokens"`
	InputTokens     int     `json:"inputTokens"`
	OutputTokens    int     `json:"outputTokens"`
	TurnCount       int     `json:"turnCount"`
	ToolCalls       int     `json:"toolCalls"`
	DurationMinutes float64 `json:"durationMinutes"`
	// v2 fields -- zero-valued until implemented.
	Scope                string  `json:"scope"`
	Title                string  `json:"title"`
	Outcome              string  `json:"outcome"`
	FilesTouched         int     `json:"filesTouched"`
	LinesChanged         int     `json:"linesChanged"`
	RetryLoops           int     `json:"retryLoops"`
	RetryTokensWasted    int     `json:"retryTokensWasted"`
	WithinSessionReverts int     `json:"withinSessionReverts"`
	SignalDensity        float64 `json:"signalDensity"`
	SpecQualityScore     float64 `json:"specQualityScore"`
	ExplorationRatio     float64 `json:"explorationRatio"`
	ScopeBreadth         int     `json:"scopeBreadth"`
	DiscoveryTurns       int     `json:"discoveryTurns"`
	// EffectiveAnnotations are the non-superseded annotations for this session.
	// Clients derive display labels (e.g. humanLabel, agentLabel) by filtering
	// on typeId and annotatorKind — no pre-computed string fields needed.
	EffectiveAnnotations []AnnotationSummary `json:"effectiveAnnotations,omitempty"`
}

QualitySession is the analytics payload for the quality dashboard.

type QualitySessionFixture

type QualitySessionFixture struct {
	Name                 QualityFixtureName `json:"name" yaml:"name"`
	ID                   string             `json:"id" yaml:"id"`
	Date                 string             `json:"date" yaml:"date"`
	Project              string             `json:"project" yaml:"project"`
	Scope                string             `json:"scope" yaml:"scope"`
	Title                string             `json:"title" yaml:"title"`
	TotalTokens          int                `json:"totalTokens" yaml:"totalTokens"`
	InputTokens          int                `json:"inputTokens" yaml:"inputTokens"`
	OutputTokens         int                `json:"outputTokens" yaml:"outputTokens"`
	TurnCount            int                `json:"turnCount" yaml:"turnCount"`
	ToolCalls            int                `json:"toolCalls" yaml:"toolCalls"`
	Outcome              string             `json:"outcome" yaml:"outcome"`
	FilesTouched         int                `json:"filesTouched" yaml:"filesTouched"`
	LinesChanged         int                `json:"linesChanged" yaml:"linesChanged"`
	DurationMinutes      float64            `json:"durationMinutes" yaml:"durationMinutes"`
	RetryLoops           int                `json:"retryLoops" yaml:"retryLoops"`
	RetryTokensWasted    int                `json:"retryTokensWasted" yaml:"retryTokensWasted"`
	WithinSessionReverts int                `json:"withinSessionReverts" yaml:"withinSessionReverts"`
	SignalDensity        float64            `json:"signalDensity" yaml:"signalDensity"`
	SpecQualityScore     float64            `json:"specQualityScore" yaml:"specQualityScore"`
	ExplorationRatio     float64            `json:"explorationRatio" yaml:"explorationRatio"`
	ScopeBreadth         int                `json:"scopeBreadth" yaml:"scopeBreadth"`
	DiscoveryTurns       int                `json:"discoveryTurns" yaml:"discoveryTurns"`
}

QualitySessionFixture is one named quality-session fixture row.

func (QualitySessionFixture) ToQualitySession

func (f QualitySessionFixture) ToQualitySession() QualitySession

ToQualitySession converts a named fixture row to the wire payload shape.

type QualityStringVariation

type QualityStringVariation struct {
	Value string `json:"value" yaml:"value"`
}

type QualityVariations

type QualityVariations struct {
	Outcomes    []QualityStringVariation `json:"outcomes" yaml:"outcomes"`
	Projects    []QualityStringVariation `json:"projects" yaml:"projects"`
	Scopes      []QualityStringVariation `json:"scopes" yaml:"scopes"`
	TaskTitles  []QualityStringVariation `json:"taskTitles" yaml:"task_titles"`
	TokenRatios []QualityRatioVariation  `json:"tokenRatios" yaml:"token_ratios"`
	Metrics     QualityMetricVariations  `json:"metrics" yaml:"metrics"`
}

QualityVariations is the reusable combinatorial input catalog carried by the canonical quality fixture document.

type ReadAttributionState

type ReadAttributionState string

ReadAttributionState reports whether per-file read attribution is recoverable for a node's editing sessions. It is the honesty axis that keeps a zero ReadCount from being misread as "known unread" when it is really "never recorded".

const (
	ReadAttributionComplete    ReadAttributionState = "complete"
	ReadAttributionPartial     ReadAttributionState = "partial"
	ReadAttributionUnavailable ReadAttributionState = "unavailable"
)

ReadAttributionState values.

func (ReadAttributionState) IsValid

func (s ReadAttributionState) IsValid() bool

IsValid reports whether s is one of the defined read attribution states.

func (ReadAttributionState) JSONSchema

func (ReadAttributionState) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (ReadAttributionState) String

func (s ReadAttributionState) String() string

String returns the wire representation of the read attribution state.

func (ReadAttributionState) Validate

func (s ReadAttributionState) Validate() error

Validate rejects values that cannot cross the read-attribution wire boundary.

type ReadStateGrade

type ReadStateGrade string

ReadStateGrade is the ordinal closed set of explicit read-state acts (the read-state grade design): none < viewed < reviewed < reviewed_in_detail. The ordering is registry data (the peasant-side system-origin TypeDefinition seed); this Go closed set is the sole typed copy on the wire, kept identical to the registry seed by ReadStateGradeRegistrySeedPermissibleValues.

const (
	ReadStateGradeNone             ReadStateGrade = "none"
	ReadStateGradeViewed           ReadStateGrade = "viewed"
	ReadStateGradeReviewed         ReadStateGrade = "reviewed"
	ReadStateGradeReviewedInDetail ReadStateGrade = "reviewed_in_detail"
)

ReadStateGrade values, in ascending ordinal order.

func (ReadStateGrade) IsValid

func (g ReadStateGrade) IsValid() bool

IsValid reports whether g is one of the defined read-state grades.

func (ReadStateGrade) JSONSchema

func (ReadStateGrade) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (ReadStateGrade) String

func (g ReadStateGrade) String() string

String returns the wire representation of the read-state grade.

func (ReadStateGrade) Validate

func (g ReadStateGrade) Validate() error

Validate rejects values that cannot cross the read-state-grade wire boundary.

type RedactionExample

type RedactionExample struct {
	// Name is the stable case key (snake_case). The web codegen joins its
	// presentation side-table (UI context snippets) to a case by this Name.
	Name string `yaml:"name"`
	// RuleID is the pkg/redact rule that fires on OriginalText (e.g. "github_pat").
	RuleID string `yaml:"ruleId"`
	// Category is the ENGINE category vocabulary: "secrets" | "pii" | "paths" |
	// "project". This is the ONE canonical category vocabulary; the web display
	// enum (CREDENTIAL|PII|PATH|INTERNAL) is a derived, audited projection.
	Category string `yaml:"category"`
	// Level is the minimum redaction level at which RuleID fires.
	Level RedactionFixtureLevel `yaml:"level"`
	// OriginalText is a realistic, public-safe secret FORMAT (non-functional
	// example value) that the engine genuinely detects.
	OriginalText string `yaml:"originalText"`
	// RedactedReplacement is the engine-APPLIED output, stored verbatim. For
	// back-reference rules this is the partially-redacted form
	// (e.g. "/Users/<USER>/Projects/internal-api"), not a bare label.
	RedactedReplacement string `yaml:"redactedReplacement"`
	// Confidence is a presentation-only 0-100 score shown in the mock UI.
	Confidence int `yaml:"confidence"`
	// LineNumber is a presentation-only source line shown in the mock UI.
	LineNumber int `yaml:"lineNumber"`
	// Description is a human-readable label shown in the mock UI.
	Description string `yaml:"description"`
}

RedactionExample is one entry in the redaction example corpus. It is the single source of truth for the redaction session-detail fixture: the leaf STORES this data and a format-only generator serialises it to testdata/session-detail/redactions.yaml. The leaf never recomputes RedactedReplacement — the redaction ENGINE lives only in peasant (pkg/redact), and a peasant-side behavioural conformance test binds RedactedReplacement to the real engine output (the no-drift guarantee).

func LoadRedactionExamples

func LoadRedactionExamples() ([]RedactionExample, error)

LoadRedactionExamples parses RedactionsYAML (the embedded, generated artifact) into typed cases. Consumers (peasant conformance test, web codegen) bind to the PUBLISHED bytes via this loader rather than the in-memory RedactionExamples slice, so they validate exactly what ships; the leaf freshness gate keeps the two in lockstep.

type RedactionFixtureLevel

type RedactionFixtureLevel string

RedactionFixtureLevel is the redaction level at which a fixture case's rule fires. The string values are byte-identical to peasant pkg/redact's RedactionLevel ("minimal"/"standard"/"maximum") so the peasant conformance test can construct a redactor at the exact firing level via redact.RedactionLevel(string(level)) with no translation table.

Default firing semantics are category-based, but the engine may give an individual rule a stricter minimum:

  • secrets, paths -> fire at Minimal and above (unconditional)
  • pii, project -> normally fire at Standard and above
  • selected project rules may require Maximum

The fixture stores the MINIMUM level at which each case's rule fires so the conformance test exercises the narrowest level that still triggers the rule (avoids entropy/AST over-redaction that only Maximum adds).

const (
	// RedactionLevelMinimal redacts only secrets and paths.
	RedactionLevelMinimal RedactionFixtureLevel = "minimal"
	// RedactionLevelStandard adds PII and most project-identity redaction.
	RedactionLevelStandard RedactionFixtureLevel = "standard"
	// RedactionLevelMaximum adds stricter project rules, AST anonymization, and entropy detection.
	RedactionLevelMaximum RedactionFixtureLevel = "maximum"
)

func (RedactionFixtureLevel) IsValid

func (l RedactionFixtureLevel) IsValid() bool

IsValid reports whether l is one of the three known levels.

func (RedactionFixtureLevel) String

func (l RedactionFixtureLevel) String() string

String returns the wire form of the level.

type RedactionInfo

type RedactionInfo struct {
	Applied             bool   `json:"applied"`
	Level               string `json:"level,omitempty"`                  // redaction level used (validate with redact.RedactionLevel)
	RuleSetVersion      string `json:"rule_set_version,omitempty"`       // rule set version that produced this redaction (e.g. "1.1.0")
	RedactedAtMs        *int64 `json:"redacted_at_ms,omitempty"`         // unix ms when redacted
	ContentHashAtRedact string `json:"content_hash_at_redact,omitempty"` // content hash snapshot at redaction time
}

RedactionInfo tracks whether and when redaction was applied to a session's transcript. Level is stored as a string because this schema module is a public contract module that must not import internal packages. Callers should validate using redact.RedactionLevel(level).IsValid().

func (RedactionInfo) IsCurrent

func (r RedactionInfo) IsCurrent(currentContentHash string) bool

IsCurrent returns true if the redaction matches the current content.

func (RedactionInfo) IsRaw

func (r RedactionInfo) IsRaw() bool

IsRaw returns true if no redaction has been applied.

func (RedactionInfo) IsStale

func (r RedactionInfo) IsStale(currentContentHash string) bool

IsStale returns true if the content has changed since redaction was applied.

type RefCase

type RefCase struct {
	// Name is a stable, human-readable case identifier (used as the t.Run name).
	Name string
	// Input is the raw string fed to ParseTranscriptRef.
	Input string
	// WantID is the expected canonical (lowercase) TranscriptID string for a
	// PARSING case; empty for a reject case.
	WantID string
	// WantFromURL is the expected TranscriptRef.FromURL for a parsing case.
	WantFromURL bool
	// WantErr is true when ParseTranscriptRef is expected to return an error.
	WantErr bool
	// ErrContains is a substring the returned error must contain (reject cases).
	ErrContains string
}

RefCase is a single concrete ParseTranscriptRef test case, materialised from the axes/categories. It is what internal/pull/types_test.go ranges over.

type RefForm

type RefForm struct {
	Name     string `yaml:"name"`
	Template string `yaml:"template"`
	FromURL  bool   `yaml:"from_url"`
}

RefForm is one entry of the ref_forms axis: a templated reference shape plus the FromURL the parser is expected to report for it.

type ReviewListPayload

type ReviewListPayload struct {
	ProjectHash   ProjectHash          `json:"projectHash"`
	RepoFound     bool                 `json:"repoFound"`
	DefaultBranch string               `json:"defaultBranch,omitempty"`
	Changes       []ChangeSummary      `json:"changes" required:"true" nullable:"false"`       // open first, then merged
	RecentCommits []CommitRef          `json:"recentCommits" required:"true" nullable:"false"` // default-branch, cap 200 (time strip)
	Sessions      []TimelineSessionRef `json:"sessions" required:"true" nullable:"false"`      // complete visible project timeline identities, including sessions not linked to displayed commits
	// RewrittenCommits lists the project's full session-era commit resolution
	// ledger. Only non-live rows render as ghosts; live rows remain valid history
	// entries. It is empty when the resolver found no relevant session-era rows.
	RewrittenCommits []RewrittenCommit `json:"rewrittenCommits" required:"true" nullable:"false"`
}

ReviewListPayload lists a project's changes, served by GET /api/v1/review/{projectHash}.

func NewReviewListPayload

func NewReviewListPayload(projectHash ProjectHash) *ReviewListPayload

NewReviewListPayload returns a ReviewListPayload with all slices initialized to empty (never-nil marshal guarantee).

func (ReviewListPayload) Validate

func (p ReviewListPayload) Validate() error

Validate checks the normalized timeline relationship and compatibility invariants. It does not infer candidate or temporal associations, and it validates each CommitRef's shape before checking timeline membership and rank-order rules.

type ReviewSuggestion

type ReviewSuggestion struct {
	Path            string `json:"path"`
	LastEngaged     string `json:"lastEngaged"`
	DaysSince       int    `json:"daysSince"`
	SuggestedPrompt string `json:"suggestedPrompt"`
}

ReviewSuggestion nudges the user to revisit a fading file.

type RewriteMethod

type RewriteMethod string

RewriteMethod names the mechanism the resolver used to map a ghost commit to its successor, in the order the resolver attempts them.

const (
	RewriteMethodHash            RewriteMethod = "hash"
	RewriteMethodPatchID         RewriteMethod = "patch_id"
	RewriteMethodAuthorIdentity  RewriteMethod = "author_identity"
	RewriteMethodMessageEmbedded RewriteMethod = "message_embedded"
	RewriteMethodTemporal        RewriteMethod = "temporal"
	RewriteMethodNone            RewriteMethod = "none"
)

RewriteMethod values.

func (RewriteMethod) IsValid

func (m RewriteMethod) IsValid() bool

IsValid reports whether m is one of the defined rewrite methods.

func (RewriteMethod) JSONSchema

func (RewriteMethod) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (RewriteMethod) String

func (m RewriteMethod) String() string

String returns the wire representation of the rewrite method.

func (RewriteMethod) Validate

func (m RewriteMethod) Validate() error

Validate rejects values that cannot cross the rewrite-method wire boundary.

type RewriteResolution

type RewriteResolution string

RewriteResolution classifies whether a ledger-observed commit hash is still live on the default branch, was rewritten to a resolvable successor, or could not be resolved.

const (
	RewriteResolutionLive       RewriteResolution = "live"
	RewriteResolutionRewritten  RewriteResolution = "rewritten"
	RewriteResolutionUnresolved RewriteResolution = "unresolved"
)

RewriteResolution values.

func (RewriteResolution) IsValid

func (r RewriteResolution) IsValid() bool

IsValid reports whether r is one of the defined rewrite resolutions.

func (RewriteResolution) JSONSchema

func (RewriteResolution) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (RewriteResolution) String

func (r RewriteResolution) String() string

String returns the wire representation of the rewrite resolution.

func (RewriteResolution) Validate

func (r RewriteResolution) Validate() error

Validate rejects values that cannot cross the rewrite-resolution wire boundary.

type RewrittenCommit

type RewrittenCommit struct {
	GhostHash string `json:"ghostHash" yaml:"ghostHash" required:"true"`
	// Subject and AuthorTimeMs are "" / nil when the ledger row never
	// recorded that metadata (degraded providers).
	Subject      string      `json:"subject" yaml:"subject"`
	AuthorTimeMs *int64      `json:"authorTimeMs,omitempty" yaml:"authorTimeMs,omitempty"`
	SessionIDs   []SessionID `json:"sessionIds" yaml:"sessionIds" required:"true" nullable:"false"`
	// Associations mirrors SessionIDs one-for-one in the same order. These are
	// the original session-era relationships and retain their IDs even when a
	// successor commit is displayed.
	Associations []SessionAssociation `json:"associations" yaml:"associations" required:"true" nullable:"false"`
	// SuccessorHash is nil when Resolution is unresolved; non-nil when
	// rewritten. It is never populated for Resolution=live (a live ledger
	// hash is not a ghost).
	SuccessorHash *string           `json:"successorHash,omitempty" yaml:"successorHash,omitempty"`
	Resolution    RewriteResolution `json:"resolution" yaml:"resolution" required:"true"`
	Method        RewriteMethod     `json:"method" yaml:"method" required:"true"`
	Confidence    Confidence        `json:"confidence" yaml:"confidence" required:"true"`
}

RewrittenCommit is one session-era commit resolution ledger row. The row may record a live commit, a rewritten ghost, or an unresolved ghost; only non-live rows render as ghosts in timeline views.

func (RewrittenCommit) Validate

func (r RewrittenCommit) Validate() error

Validate checks a single RewrittenCommit's own fields: the resolution and method enums are in-set, SessionIDs are present and non-empty, SuccessorHash presence matches Resolution, and Method==none iff Resolution==unresolved. It does not check cross-references to a payload's session table or commit set; callers with that context use validateRewrittenCommits.

type Role

type Role string

Role represents the sender of a message turn.

const (
	RoleUser      Role = "user"
	RoleAssistant Role = "assistant"
	RoleTool      Role = "tool"
	RoleSystem    Role = "system"
)

func (Role) IsValid

func (r Role) IsValid() bool

IsValid returns true if the role is one of the known variants.

func (Role) JSONSchema

func (Role) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (Role) String

func (r Role) String() string

type ScaleKind

type ScaleKind string

ScaleKind classifies the measurement level of an annotation value domain (Stevens 1946 levels of measurement, ISO 11179 Part 5).

  • nominal: categories without order (e.g. session scope: feature/bug/docs)
  • ordinal: ordered categories with no meaningful interval (e.g. approval: deny<approve)
  • continuous: numeric range with meaningful intervals (e.g. confidence 0.0–1.0)

Valid combinations with ValueDomainKind:

  • enumerated + nominal: OK (categories without order)
  • enumerated + ordinal: OK (ordered categories with permissible values list)
  • described + continuous: OK (range with JSON schema constraint spec)
  • described + nominal: OK (pattern-constrained categories)
  • described + ordinal: REJECTED (ordinal requires explicit ordering via permissible values)
  • enumerated + continuous: REJECTED (continuous ranges must be described, not enumerated)
const (
	ScaleNominal    ScaleKind = "nominal"
	ScaleOrdinal    ScaleKind = "ordinal"
	ScaleContinuous ScaleKind = "continuous"
)

func (ScaleKind) IsValid

func (k ScaleKind) IsValid() bool

IsValid returns true if the scale kind is one of the known variants.

func (ScaleKind) JSONSchema

func (ScaleKind) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (ScaleKind) String

func (k ScaleKind) String() string

type SchemaVersionResponse

type SchemaVersionResponse struct {
	AnnotationSchemaVersion string              `json:"annotationSchemaVersion"`
	SupportedTargetKinds    []string            `json:"supportedTargetKinds"`
	SupportedTypeIDs        []string            `json:"supportedTypeIds"`
	PushContractVersion     PushContractVersion `json:"pushContractVersion"`
	MinPushContractVersion  PushContractVersion `json:"minPushContractVersion"`
	PullContractVersion     PushContractVersion `json:"pullContractVersion,omitempty"`
	MinPullContractVersion  PushContractVersion `json:"minPullContractVersion,omitempty"`
}

SchemaVersionResponse is returned by GET /api/v1/schema/version. It communicates which annotation schema AND which push CONTENT contract the village currently supports, so the CLI can preflight and version-negotiate.

PushContractVersion / MinPushContractVersion advertise the village's accept WINDOW [Min, Current] for the TranscriptContent push wire:

  • PushContractVersion is the CURRENT contract the village emits/prefers.
  • MinPushContractVersion is the PUSH-ACCEPTANCE FLOOR: the oldest contract the village will still accept on the publish path. A CLI ahead of Current downgrade-emits toward this window (never "upgrade the village").

TWO DISTINCT FLOORS: MinPushContractVersion is the push-acceptance floor (gates INCOMING uploads). It is deliberately SEPARATE from the village's display MIGRATE-ON-READ floor (how far back stored blobs can be normalized for rendering), which may reach FURTHER back than MinPushContractVersion — the village can still render a legacy stored blob it would no longer ACCEPT as a fresh push. The migrate-on-read floor lives village-side and is not advertised here; only the push-acceptance window is negotiated over the wire.

PullContractVersion / MinPullContractVersion advertise the village's PULL envelope WINDOW [Min, Current] (PullTranscriptInfo/PullListResponse/ PullAnnotation shapes, the /api/v1/pull/* endpoint semantics, ETag behaviour). This window is DISTINCT from the push window: it does NOT version the blob (the stored blob carries its own publish-time push contract version). Both fields are `omitempty` so an OLDER village that predates the pull surface emits the prior wire shape; the CLI treats an ABSENT advertisement as "village too old for pull" (actionable error), not as compatible.

type SearchPayload

type SearchPayload struct {
	Query   string         `json:"query"`
	Results []SearchResult `json:"results"`
}

SearchPayload is the result set for one query, served by GET /api/v1/search.

func NewSearchPayload

func NewSearchPayload(query string) *SearchPayload

NewSearchPayload returns a SearchPayload with Results initialized to empty (never-nil marshal guarantee).

type SearchResult

type SearchResult struct {
	SessionID   string      `json:"sessionId"`
	Project     string      `json:"project"`               // raw canonical_cwd (else hash); web formats for display
	ProjectHash ProjectHash `json:"projectHash,omitempty"` // for round-trips
	EntryIndex  int         `json:"entryIndex"`            // depth-0 turn index — deep-link coordinate
	Role        string      `json:"role"`                  // user | assistant | ... (display facet)
	Snippet     string      `json:"snippet"`               // FTS5 snippet() with [match] markers
	Score       float64     `json:"score"`                 // negated bm25: higher = more relevant (result order is authoritative)
}

SearchResult is one FTS5 hit: a single message entry, ranked by relevance, with a snippet for display and the coordinates to deep-link to it.

type ServerMessage

type ServerMessage struct {
	Type    MessageType    `json:"type"`
	Data    any            `json:"data,omitempty"`
	Message string         `json:"message,omitempty"` // for error type
	Version string         `json:"version,omitempty"` // for connected type
	Topic   ChannelTopic   `json:"topic,omitempty"`   // failed subscription topic for error type
	ID      string         `json:"id,omitempty"`      // failed topic identity, when applicable
	Axis    AnnotationAxis `json:"axis,omitempty"`    // failed annotation axis, when applicable
}

ServerMessage is a message sent from the server to the browser via WebSocket.

type SessionAssociation

type SessionAssociation struct {
	ID         AssociationID                    `json:"id" yaml:"id" required:"true"`
	SessionID  SessionID                        `json:"sessionId" yaml:"sessionId" required:"true"`
	Conclusion AssociationConclusion            `json:"conclusion" yaml:"conclusion" required:"true"`
	Confidence Confidence                       `json:"confidence" yaml:"confidence" required:"true"`
	Evidence   []AssociationEvidenceObservation `json:"evidence" yaml:"evidence" required:"true" nullable:"false"`
}

SessionAssociation keeps an authoritative session-to-commit relationship as a durable identity, producer conclusion, confidence, and ordered atomic evidence observations.

func (SessionAssociation) Validate

func (a SessionAssociation) Validate() error

Validate checks a single association's own fields are well-formed. It does not check cross-references to a payload's session table or its surrounding parent shape.

type SessionDetailPayload

type SessionDetailPayload struct {
	SchemaVersion PushContractVersion `json:"schemaVersion,omitempty"`
	ID            string              `json:"id"`
	Harness       Harness             `json:"harness"`
	StartTime     time.Time           `json:"startTime"`
	EndTime       time.Time           `json:"endTime"`
	DurationMins  float64             `json:"durationMins"`
	TotalTokens   int                 `json:"totalTokens"`
	TokensIn      int                 `json:"tokensIn"`
	TokensOut     int                 `json:"tokensOut"`
	TurnCount     int                 `json:"turnCount"`
	ToolCallCount int                 `json:"toolCallCount"`
	Turns         []TurnDetail        `json:"turns"`
	// Optional fields — populated when backend has the data.
	Source           string            `json:"source,omitempty"`
	Status           string            `json:"status,omitempty"`
	Project          string            `json:"project,omitempty"`
	Model            string            `json:"model,omitempty"`
	WorkingDirectory string            `json:"workingDirectory,omitempty"`
	GitBranch        string            `json:"gitBranch,omitempty"`
	GitRemote        string            `json:"gitRemote,omitempty"`
	ChildSessions    []ChildSessionRef `json:"childSessions,omitempty"`
	// Outcome is the heuristic resolution status of the session
	// (resolved/partial/failed), sourced from session_metrics.outcome. Empty
	// when the session has no computed outcome. The metadata columns expose no
	// per-signal reason, so no reason field accompanies it yet.
	Outcome SessionOutcome `json:"outcome,omitempty"`
	// Scorecard carries the per-session quality signals used by the "How this
	// session went" self-assessment card. Nil when the session has no computed
	// metrics. Sourced from the same session_metrics row that backs QualitySession.
	Scorecard *SessionScorecard `json:"scorecard,omitempty"`
}

SessionDetailPayload is the data sent on the session_detail WebSocket channel AND promoted to the versioned `peasant push` wire body inside a TranscriptContent envelope.

SchemaVersion is the EMBEDDED push-contract version. It is advisory: when this payload travels inside a TranscriptContent envelope the envelope's ContractVersion is authoritative (see TranscriptContent's conflict-winner note). The embedded copy keeps the payload self-describing when stored on its own. It is omitempty so the local WebSocket session_detail channel (which never sets it) does not gain a spurious "schemaVersion":"" field; the push builder sets it explicitly.

type SessionEntry

type SessionEntry struct {
	SessionID      SessionID     `json:"sessionId"`
	EntryIndex     int           `json:"entryIndex"`
	Harness        Harness       `json:"harness"`
	EntryType      EntryType     `json:"entryType"`
	Role           Role          `json:"role"`
	TimestampMs    *int64        `json:"timestampMs,omitempty"`
	ContentPreview *string       `json:"contentPreview,omitempty"` // max 500 chars
	TokensIn       *int          `json:"tokensIn,omitempty"`
	TokensOut      *int          `json:"tokensOut,omitempty"`
	HasToolUse     bool          `json:"hasToolUse"`
	ToolKind       *ToolCallKind `json:"toolKind,omitempty"` // ACP-aligned tool classification
	ToolNamesCSV   *string       `json:"toolNamesCsv,omitempty"`
	HasThinking    bool          `json:"hasThinking"`
	IsError        bool          `json:"isError"`
	StopReason     *StopReason   `json:"stopReason,omitempty"` // ACP per-turn stop reason
	RawByteLength  *int          `json:"rawByteLength,omitempty"`
	ToolCallID     *string       `json:"toolCallId,omitempty"`    // MCP correlation (was toolUseId)
	EntryID        *string       `json:"entryId,omitempty"`       // Provider-native ID
	ParentEntryID  *string       `json:"parentEntryId,omitempty"` // Parent entry link
	Depth          int           `json:"depth"`                   // 0 = message, 1 = content part
	ParentIndex    *int          `json:"parentIndex,omitempty"`   // entryIndex of parent (nil for depth=0)
	ToolInput      *string       `json:"toolInput,omitempty"`     // tool_use input JSON
	ToolOutput     *string       `json:"toolOutput,omitempty"`    // tool_result output JSON
	Extra          *string       `json:"extra,omitempty"`         // JSON overflow for provider-specific data
	PartType       *string       `json:"partType,omitempty"`      // provider's original part type label (nil for depth=0)
}

SessionEntry represents a single indexed entry within a session transcript. Defined for v2 content-layer use; NOT used in v1 PublishRequest wire format. Maps 1:1 to a row in the session_entries table. All optional fields use pointer types to distinguish absent from zero. JSON tags use camelCase aligned with ACP content model.

type SessionID

type SessionID string

SessionID is a validated session identifier from a source provider. Accepted formats:

  • UUID: "99d59925-36bc-424c-a789-8be54d9702ba"
  • Claude subagent: "agent-a3aee4f"
  • ACP session: "sess_3cd91f52effeXd3QAJ54jOyzv5" (ACP sess_ prefix)
  • OpenCode session: "ses_3cd91f52effeXd3QAJ54jOyzv5"
  • OpenCode message: "msg_001abc"

func NewSessionID

func NewSessionID(raw string) (SessionID, error)

NewSessionID validates and constructs a SessionID.

func (SessionID) JSONSchema

func (SessionID) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (SessionID) String

func (s SessionID) String() string

type SessionIdentity

type SessionIdentity struct {
	SessionID       SessionID  `json:"sessionId"`
	ParentSessionID *SessionID `json:"parentUuid,omitempty"`
	SchemaVersion   int        `json:"schemaVersion"`
}

SessionIdentity holds the identification fields for a session. JSON tags use camelCase to match CLI UnifiedMetadata wire format.

type SessionInsight

type SessionInsight struct {
	Kind       InsightKind       `json:"kind" yaml:"kind" required:"true"`
	Provenance InsightProvenance `json:"provenance" yaml:"provenance" required:"true"`
	Confidence Confidence        `json:"confidence" yaml:"confidence" required:"true"`
	Title      string            `json:"title" yaml:"title" required:"true"`
	Summary    string            `json:"summary,omitempty" yaml:"summary,omitempty"`
	// Subjects names the node ids / file paths the insight is about.
	Subjects []string `json:"subjects" yaml:"subjects" required:"true" nullable:"false"`
	// Evidence is the traceability spine: every mechanical insight carries
	// at least one item.
	Evidence []InsightEvidence `json:"evidence" yaml:"evidence" required:"true" nullable:"false"`
	// Classification MUST be nil under the current contract (see Validate).
	// The field is reserved until its per-field taxonomy sets are defined.
	Classification *InsightClassification `json:"classification,omitempty" yaml:"classification,omitempty"`
}

SessionInsight is one insight: a (kind x provenance x confidence) envelope with evidence and subjects, additive alongside ChangeDetailPayload's existing Unusual/Frictions signals. Current mechanical producers leave Classification nil. A future contract may define closed classification sets without changing this envelope's shape.

func (SessionInsight) Validate

func (i SessionInsight) Validate() error

Validate checks the insight invariants: Kind/Provenance/Confidence are in-set, Subjects and Evidence are non-nil, every evidence item carries a non-empty session identity, every mechanical insight carries at least one evidence item, and Classification is nil. A future contract may replace the must-be-nil rule with per-field closed sets without changing the shape.

type SessionOutcome

type SessionOutcome string

SessionOutcome represents the resolution status of a session.

const (
	OutcomeResolved SessionOutcome = "resolved"
	OutcomePartial  SessionOutcome = "partial"
	OutcomeFailed   SessionOutcome = "failed"
)

func (SessionOutcome) IsValid

func (o SessionOutcome) IsValid() bool

IsValid returns true if the outcome is one of the known variants.

func (SessionOutcome) JSONSchema

func (SessionOutcome) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (SessionOutcome) String

func (o SessionOutcome) String() string

type SessionScorecard

type SessionScorecard struct {
	// Token efficiency inputs.
	M2TokenOutcomeRatio     *float64 `json:"m2TokenOutcomeRatio,omitempty"`
	M5ContextUtilizationPct *float64 `json:"m5ContextUtilizationPct,omitempty"`
	M6OutputSurvivalPct     *float64 `json:"m6OutputSurvivalPct,omitempty"`
	RetryTokensWasted       *int     `json:"retryTokensWasted,omitempty"`
	TotalTokens             *int     `json:"totalTokens,omitempty"`
	CostTotalUSD            *float64 `json:"costTotalUsd,omitempty"`
	// Prompt quality inputs.
	SpecQualityScore     *float64 `json:"specQualityScore,omitempty"`
	SignalDensity        *float64 `json:"signalDensity,omitempty"`
	M7SpecHasExamples    *bool    `json:"m7SpecHasExamples,omitempty"`
	M7SpecHasConstraints *bool    `json:"m7SpecHasConstraints,omitempty"`
	// Loop efficiency inputs.
	M4ConsecutiveErrorMax *int `json:"m4ConsecutiveErrorMax,omitempty"`
	WithinSessionReverts  *int `json:"withinSessionReverts,omitempty"`
	// Outcome echoes the session outcome so the card can apply the
	// "failed outcome with above-median cost" token-efficiency trigger.
	Outcome SessionOutcome `json:"outcome,omitempty"`
}

SessionScorecard holds the deterministic per-session quality signals needed by the Highlights self-assessment card. It is a flat projection of the session_metrics fields the three axis cards (token efficiency, prompt quality, loop efficiency) consume. Fields are pointers so the client can distinguish "not computed" (nil) from a real zero value when applying threshold bands.

type SessionStats

type SessionStats struct {
	TurnCount     int   `json:"turnCount"`
	ToolCallCount int   `json:"toolCallCount"`
	SubagentCount int   `json:"subagentCount"`
	DurationMs    int64 `json:"durationMs"`
	TokensIn      int   `json:"tokensIn"`
	TokensOut     int   `json:"tokensOut"`
	// ACP-aligned token breakdown (optional — not all providers report these).
	ThoughtTokens     *int `json:"thoughtTokens,omitempty"`     // Reasoning/thinking tokens
	CachedReadTokens  *int `json:"cachedReadTokens,omitempty"`  // Prompt cache hits
	CachedWriteTokens *int `json:"cachedWriteTokens,omitempty"` // Prompt cache writes
}

SessionStats holds aggregate metrics extracted from transcript data.

type SessionSummary

type SessionSummary struct {
	ID            string    `json:"id"`
	Harness       Harness   `json:"harness"`
	StartTime     time.Time `json:"startTime"`
	DurationMins  float64   `json:"durationMins"`
	TotalTokens   int       `json:"totalTokens"`
	TurnCount     int       `json:"turnCount"`
	ToolCallCount int       `json:"toolCallCount"`
	Project       string    `json:"project,omitempty"`
	// ProjectHash is the opaque project identifier (projects.project_hash).
	// The frontend resolves display name → hash from this field for the
	// Map/Review REST endpoints (contract §9.1).
	ProjectHash     ProjectHash `json:"projectHash,omitempty"`
	Outcome         string      `json:"outcome,omitempty"`
	ParentSessionID *string     `json:"parentSessionId,omitempty"`
	// Preview is the raw first user message of the session, sourced from the
	// already-redacted indexed transcript (session_entries.content_preview). It
	// is redaction-safe by construction. Empty when the session has no indexed
	// user entry. The web client formats it for display.
	Preview string `json:"preview,omitempty"`
}

SessionSummary is a session without turns, used in the sessions list.

type SessionsPayload

type SessionsPayload struct {
	Sessions []SessionSummary `json:"sessions"`
}

SessionsPayload is the data sent on the sessions WebSocket channel.

type ShutdownResponse

type ShutdownResponse struct {
	Status string `json:"status"`
}

ShutdownResponse is the JSON response for POST /api/v1/shutdown.

type SourceFormat

type SourceFormat string

SourceFormat identifies the transcript file format.

const (
	SourceFormatJSONL SourceFormat = "jsonl" // Claude Code JSONL transcripts
	SourceFormatJSON  SourceFormat = "json"  // OpenCode JSON transcripts
)

func (SourceFormat) IsValid

func (f SourceFormat) IsValid() bool

IsValid returns true if the SourceFormat is one of the known variants.

func (SourceFormat) JSONSchema

func (SourceFormat) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (SourceFormat) String

func (f SourceFormat) String() string

type SourceInfo

type SourceInfo struct {
	FilePath string       `json:"filePath,omitempty"` // Original source transcript path
	Format   SourceFormat `json:"format"`             // "jsonl" or "json"
}

SourceInfo identifies the original transcript file and its format.

type StopReason

type StopReason string

StopReason represents why a session or turn ended. ACP per-turn stop reasons; content-layer type for future use.

const (
	StopReasonEndTurn         StopReason = "end_turn"
	StopReasonCancelled       StopReason = "cancelled"
	StopReasonMaxTokens       StopReason = "max_tokens"
	StopReasonMaxTurnRequests StopReason = "max_turn_requests"
	StopReasonRefusal         StopReason = "refusal"
)

func (StopReason) IsValid

func (r StopReason) IsValid() bool

IsValid returns true if the stop reason is one of the known variants.

func (StopReason) JSONSchema

func (StopReason) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (StopReason) String

func (r StopReason) String() string

type SubagentRef

type SubagentRef struct {
	SessionID  SessionID `json:"sessionId"`
	ParentUUID SessionID `json:"parentUuid"`
}

SubagentRef records a reference to a subagent session spawned during a parent session.

type SubscriptionValidationCase

type SubscriptionValidationCase struct {
	Name  string `yaml:"name"`
	Topic string `yaml:"topic"`
	Axis  string `yaml:"axis,omitempty"`
	ID    string `yaml:"id,omitempty"`
	Valid bool   `yaml:"valid"`
}

SubscriptionValidationCase is a test case for ValidateSubscription.

type TargetKind

type TargetKind string

TargetKind identifies which of an annotation's six target arms is populated: session, transcript entry, annotation, project, file_version, or association. The file_version arm identifies one repository-relative file at one content hash; the association arm identifies a durable association ID.

const (
	TargetSession     TargetKind = "session"
	TargetEntry       TargetKind = "entry"      // turn, tool call, tool result
	TargetAnnotation  TargetKind = "annotation" // meta-annotation
	TargetProject     TargetKind = "project"    // project-level annotation
	TargetFileVersion TargetKind = "file_version"
	TargetAssociation TargetKind = "association"
)

func (TargetKind) IsValid

func (k TargetKind) IsValid() bool

IsValid returns true if the target kind is one of the known variants.

func (TargetKind) JSONSchema

func (TargetKind) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (TargetKind) String

func (k TargetKind) String() string

type TaskSummary

type TaskSummary struct {
	SessionID   string   `json:"sessionId"`
	EntryIndex  int      `json:"entryIndex"` // depth-0 user-turn entry index (task identity)
	Title       string   `json:"title"`      // first words of the user turn, <=80 chars
	StartMs     *int64   `json:"startMs,omitempty"`
	Outcome     string   `json:"outcome,omitempty"` // session-level outcome
	EditedFiles []string `json:"editedFiles"`
	ReadCount   int      `json:"readCount"`
	// ReadFiles is the per-file derivation of ReadCount: repo-relative paths,
	// sorted, distinct, non-nil, mirroring
	// EditedFiles' invariants. Retroactively recoverable for any already-
	// ingested session with at least one depth-1 tool_use entry carrying
	// non-NULL tool_input (see MapNode.ReadAttribution for the honest
	// residual-gap signal when it is not).
	ReadFiles []string `json:"readFiles" required:"true" nullable:"false"`
	RetryLoop bool     `json:"retryLoop"` // an error streak >=2 occurs inside this task's range
	Labels    []string `json:"labels"`    // effective auto/manual annotation values, plain strings
}

TaskSummary is one task: a depth-0 user turn and everything until the next user turn (spec §2 "Task", v1 grain).

func NewTaskSummary

func NewTaskSummary(sessionID string, entryIndex int) TaskSummary

NewTaskSummary returns a TaskSummary with all slices initialized to empty (never-nil marshal guarantee).

func (TaskSummary) Validate

func (t TaskSummary) Validate() error

Validate checks TaskSummary's ReadFiles invariant: non-nil, sorted ascending, and free of duplicates (mirroring the invariants EditedFiles is already expected to carry).

type TaxonomyFamilyNode

type TaxonomyFamilyNode struct {
	Family string                  `json:"family"`
	Types  []AnnotationTypeSummary `json:"types"`
}

TaxonomyFamilyNode represents a family node with its associated annotation types.

type TaxonomyNode

type TaxonomyNode struct {
	Class    string               `json:"class"`
	Families []TaxonomyFamilyNode `json:"families"`
}

TaxonomyNode represents a class node in the class > family > type taxonomy tree.

type TimelineFixtureCase

type TimelineFixtureCase struct {
	Family         string                  `json:"family" yaml:"family"`
	Name           string                  `json:"name" yaml:"name"`
	Input          TimelineFixtureInput    `json:"input" yaml:"input"`
	Expected       TimelineFixtureExpected `json:"expected" yaml:"expected"`
	Classification testcase.Classification `json:"classification" yaml:"classification"`
	Provenance     testcase.Provenance     `json:"provenance" yaml:"provenance"`
	Mutation       testcase.Mutation       `json:"mutation" yaml:"mutation"`
}

TimelineFixtureCase is one public relationship case. Family is the stable behavioral identity; Name remains the executable testcase identity.

type TimelineFixtureCorpus

type TimelineFixtureCorpus struct {
	Cases                           []TimelineFixtureCase `json:"cases" yaml:"cases"`
	SuccessorAssociationMirrorCases []TimelineFixtureCase `json:"successorAssociationMirrorCases" yaml:"successorAssociationMirrorCases"`
}

TimelineFixtureCorpus is the project Git timeline validation corpus.

func LoadTimelineFixtures

func LoadTimelineFixtures() (TimelineFixtureCorpus, error)

LoadTimelineFixtures parses and validates the shared public timeline corpus.

func (TimelineFixtureCorpus) CheckMin

func (c TimelineFixtureCorpus) CheckMin(minimum int) error

CheckMin rejects a timeline corpus smaller than the required behavioral floor.

type TimelineFixtureExpected

type TimelineFixtureExpected struct {
	ErrorContains string                 `json:"errorContains,omitempty" yaml:"error_contains"`
	Repair        *timelineFixtureRepair `json:"repair,omitempty" yaml:"repair,omitempty"`
}

TimelineFixtureExpected records the validation error for a rejected input. A must-pass case leaves ErrorContains empty.

type TimelineFixtureInput

type TimelineFixtureInput struct {
	Sessions         []TimelineSessionRef `json:"sessions" yaml:"sessions"`
	Commits          []CommitRef          `json:"commits" yaml:"commits"`
	RewrittenCommits []RewrittenCommit    `json:"rewrittenCommits,omitempty" yaml:"rewrittenCommits,omitempty"`
}

TimelineFixtureInput is one normalized session and commit relationship.

type TimelineSessionRef

type TimelineSessionRef struct {
	SessionID        SessionID `json:"sessionId" yaml:"sessionId"`
	Title            string    `json:"title" yaml:"title"`
	Harness          Harness   `json:"harness" yaml:"harness"`
	StartMs          *int64    `json:"startMs,omitempty" yaml:"startMs,omitempty"`
	HasCommitBinding bool      `json:"hasCommitBinding" yaml:"hasCommitBinding"`
}

TimelineSessionRef is identity and display metadata for a recorded session available to the project timeline. Producers order these references by known startMs descending, then sessionId ascending; missing startMs follows every known timestamp and is likewise ordered by sessionId. HasCommitBinding is computed from the complete authoritative session_commits relation, not merely the bounded default-branch commit window returned alongside it. CommitRef.SessionIDs names bindings that are visible inside that window.

type TimestampInfo

type TimestampInfo struct {
	Start    int64  `json:"start"`              // Unix millis
	End      int64  `json:"end"`                // Unix millis
	Ingested *int64 `json:"ingested,omitempty"` // Unix millis; nil if not yet ingested
}

TimestampInfo records session timing in Unix milliseconds.

type ToolCallDetail

type ToolCallDetail struct {
	ID         string       `json:"id"`
	Name       string       `json:"name"`
	Arguments  string       `json:"arguments"`
	Result     string       `json:"result"`
	DurationMs *int         `json:"durationMs,omitempty"`
	ExitCode   *int         `json:"exitCode,omitempty"`
	FilePath   string       `json:"filePath,omitempty"`
	IsError    bool         `json:"isError,omitempty"`
	ToolKind   ToolCallKind `json:"toolKind,omitempty"`
}

ToolCallDetail is a tool call in the detail view.

type ToolCallKind

type ToolCallKind string

ToolCallKind classifies a tool call in an agent session. Aligns with ACP's ToolCallUpdate.kind — enables ExplorationRatio without heuristic parsing.

const (
	ToolCallKindRead    ToolCallKind = "read"
	ToolCallKindEdit    ToolCallKind = "edit"
	ToolCallKindDelete  ToolCallKind = "delete"
	ToolCallKindMove    ToolCallKind = "move"
	ToolCallKindSearch  ToolCallKind = "search"
	ToolCallKindExecute ToolCallKind = "execute"
	ToolCallKindThink   ToolCallKind = "think"
	ToolCallKindFetch   ToolCallKind = "fetch"
	ToolCallKindOther   ToolCallKind = "other"
)

func (ToolCallKind) IsValid

func (k ToolCallKind) IsValid() bool

IsValid returns true if the tool call kind is one of the known variants.

func (ToolCallKind) JSONSchema

func (ToolCallKind) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (ToolCallKind) String

func (k ToolCallKind) String() string

type TranscriptContent

type TranscriptContent struct {
	ContractVersion PushContractVersion   `json:"contractVersion"`
	Kind            ContentKind           `json:"kind"`
	SessionDetail   *SessionDetailPayload `json:"sessionDetail,omitempty"`
}

TranscriptContent is the versioned, self-describing wire body that `peasant push` uploads in place of raw provider JSONL. The village decodes this envelope (migrate-on-read for legacy/older blobs) and renders SessionDetail.

VERSION CONFLICT-WINNER: a TranscriptContent envelope carries TWO version markers — the envelope's ContractVersion and the embedded SessionDetailPayload.SchemaVersion. They are emitted IN LOCKSTROKE by peasant (both equal defaults.PublishSchemaVersion). If a decoder ever observes them to DISAGREE (e.g. a hand-edited or partially-migrated blob), the ENVELOPE's ContractVersion WINS and is authoritative for migrate-on-read dispatch; the embedded SchemaVersion is advisory and exists so a SessionDetailPayload extracted and stored on its OWN (outside any envelope) remains self-describing. The village ContentMigrator MUST honor this same rule.

type TranscriptID

type TranscriptID string

TranscriptID is a validated village-side transcript identifier. The village generates a UUID per published transcript (the same value carried in PublishResponse.TranscriptID); the pull surface keys off it. Newtype over string so the identifier flows typed across the pull pipeline, mirroring the SessionID/ProjectHash precedent.

func NewTranscriptID

func NewTranscriptID(raw string) (TranscriptID, error)

NewTranscriptID validates and constructs a TranscriptID. The input must be a canonical lowercase-hex UUID; anything else is rejected so a pasted URL slug, truncated id, or path-bearing string never reaches the filesystem layout ({villageHost}/{transcriptId}/...).

func (TranscriptID) JSONSchema

func (TranscriptID) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (TranscriptID) String

func (t TranscriptID) String() string

type TrendsPayload

type TrendsPayload struct {
	Days          []DayStats `json:"days"`
	TotalTokens   int        `json:"totalTokens"`
	TotalSessions int        `json:"totalSessions"`
}

TrendsPayload is the data sent on the trends WebSocket channel.

type TurnDetail

type TurnDetail struct {
	Index       int              `json:"index"`
	Role        Role             `json:"role"`
	Content     string           `json:"content"`
	ToolCalls   []ToolCallDetail `json:"toolCalls,omitempty"`
	Timestamp   time.Time        `json:"timestamp"`
	Depth       int              `json:"depth"`
	ParentIndex *int             `json:"parentIndex,omitempty"`
	AgentName   string           `json:"agentName,omitempty"`

	// Enrichment fields — propagated from session_entries.
	EntryType   EntryType   `json:"entryType,omitempty"`
	HasThinking bool        `json:"hasThinking,omitempty"`
	StopReason  *StopReason `json:"stopReason,omitempty"`
	TokensIn    *int        `json:"tokensIn,omitempty"`
	TokensOut   *int        `json:"tokensOut,omitempty"`
}

TurnDetail is a turn with full content for the detail view.

type TypeDefinition

type TypeDefinition struct {
	// TypeID is the dot-notation identifier (e.g., "quality.my_signal").
	// Must match the CHECK (type_id LIKE '%.%') constraint.
	TypeID string

	// DisplayName is the human-readable name.
	DisplayName string

	// Description is optional free-text documentation.
	Description string

	// FamilyID is the UUID FK to annotation_families.id.
	FamilyID string

	// ValueDomain defines permissible values for this type.
	ValueDomain ValueDomain

	// LowerIsBetter is nil for non-ordinal types, false for higher-is-better, true for lower-is-better.
	LowerIsBetter *bool

	// Origin is who created this type (system, user, group).
	Origin TypeOrigin

	// AllowedTargetKinds specifies which target kinds this type allows (V16).
	// Nil or empty means all target kinds are allowed.
	AllowedTargetKinds []TargetKind
}

TypeDefinition is the input for registering a new annotation type.

type TypeDependency

type TypeDependency struct {
	// TypeID is the dependent annotation type.
	TypeID string

	// DependsOn is the type that must be computed first.
	DependsOn string

	// Required: true means this dependency must be satisfied before TypeID can produce a value.
	Required bool

	// Rationale documents why this dependency exists.
	Rationale string
}

TypeDependency represents a dependency edge in the annotation_type_deps table.

type TypeFilter

type TypeFilter struct {
	// Status filters to types with this status (e.g., StatusActive).
	// Zero value includes all statuses except deprecated/retired (unless IncludeDeprecated is set).
	Status AnnotationStatus

	// FamilyID filters to types in this family by UUID FK. "" means all families.
	FamilyID string

	// Origin filters to types from this origin. Zero value means all origins.
	Origin TypeOrigin

	// IncludeDeprecated includes deprecated types when true.
	// Has no effect when Status is set (Status takes precedence).
	IncludeDeprecated bool
}

TypeFilter constrains which annotation types ListTypes returns. Zero values mean "no filter" (include all non-deprecated types).

type TypeOrigin

type TypeOrigin string

TypeOrigin identifies who created an annotation type.

const (
	OriginSystem TypeOrigin = "system"
	OriginUser   TypeOrigin = "user"
	OriginGroup  TypeOrigin = "group"
)

func (TypeOrigin) IsValid

func (o TypeOrigin) IsValid() bool

IsValid returns true if the type origin is one of the known variants.

func (TypeOrigin) JSONSchema

func (TypeOrigin) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (TypeOrigin) String

func (o TypeOrigin) String() string

type UnifiedMetadata

type UnifiedMetadata struct {
	SchemaVersion int             `json:"schemaVersion"`
	SessionID     SessionID       `json:"sessionId"`
	ParentUUID    *SessionID      `json:"parentUuid"` // nil for root sessions, pointer for nullable JSON
	ModelHarness  Harness         `json:"harness"`
	Model         ModelID         `json:"model"`
	Version       string          `json:"version"` // provider tool version (e.g. "2.1.47")
	Timestamp     TimestampInfo   `json:"timestamp"`
	Source        SourceInfo      `json:"source"`
	Git           GitContext      `json:"git"`
	Project       ProjectContext  `json:"project"`
	HostSlug      HostSlug        `json:"hostSlug"`
	Stats         SessionStats    `json:"stats"`
	Subagents     []SubagentRef   `json:"subagents"`
	CWD           string          `json:"cwd,omitempty"`       // Real project working directory (v7+)
	DerivedAt     *int64          `json:"derivedAt,omitempty"` // Unix ms when metadata.json was derived from DB (v8+); nil if written before DB insert
	Diagnostics   DiagnosticsInfo `json:"diagnostics"`
	ContentHash   string          `json:"contentHash"`  // SHA3-256 of transcript bytes
	MetadataHash  string          `json:"metadataHash"` // SHA3-256 of metadata (excluding hashes + redaction)
	Redaction     RedactionInfo   `json:"redaction"`
}

UnifiedMetadata is the on-disk JSON stored alongside each raw transcript. It drives the adapter layer for downstream consumers and incremental diff logic.

func NewUnifiedMetadata

func NewUnifiedMetadata() UnifiedMetadata

NewUnifiedMetadata creates a UnifiedMetadata with SchemaVersion set to MetadataSchemaVersion and empty slices initialized (not nil) so JSON serialization produces [] instead of null.

func (*UnifiedMetadata) UnmarshalJSON

func (m *UnifiedMetadata) UnmarshalJSON(data []byte) error

UnmarshalJSON decodes UnifiedMetadata, accepting the legacy pre-v9 on-disk harness key. The canonical key is json:"harness" (v9+); pre-v9 files wrote json:"modelHarness". When the canonical key is absent but the legacy key is present, the legacy value is adopted so a pre-v9 file still reads its harness correctly in the window before the v9 DIFF-stage re-extract rewrites it. Marshalling is unaffected (struct tags emit only "harness").

type UnusualSignal

type UnusualSignal struct {
	Kind       string  `json:"kind"`       // e.g. "retryLoops"
	Label      string  `json:"label"`      // plain, neutral
	PerChange  float64 `json:"perChange"`  // this change's per-conversation rate
	PerProject float64 `json:"perProject"` // the project's per-conversation baseline
}

UnusualSignal is one neutral rate-elevation: a per-conversation rate for this change that runs notably above the project baseline. Facts for orientation — the surface shows, it does not grade.

type ValidGenExpectation

type ValidGenExpectation struct {
	Parses         bool   `yaml:"parses"`
	WantID         string `yaml:"want_id"`           // casing name whose value is the expected normalized ID
	FromURLPerForm bool   `yaml:"from_url_per_form"` // take FromURL from each ref_form
}

ValidGenExpectation is the expectation attached to the valid generator.

type ValidGeneration

type ValidGeneration struct {
	Axes   []string            `yaml:"axes"`
	Expect ValidGenExpectation `yaml:"expect"`
}

ValidGeneration declares the valid cross-product and its attached expectation.

type ValueDomain

type ValueDomain struct {
	Kind              ValueDomainKind    `json:"kind"`
	Datatype          AnnotationDatatype `json:"datatype"`
	PermissibleValues []string           `json:"permissibleValues,omitempty"` // for enumerated
	ConstraintSpec    string             `json:"constraintSpec,omitempty"`    // for described; JSON
}

ValueDomain defines the permissible values for an annotation type (ISO 11179). For enumerated domains, PermissibleValues holds the finite set of allowed strings. For described domains, ConstraintSpec holds a JSON-encoded range or pattern.

type ValueDomainKind

type ValueDomainKind string

ValueDomainKind distinguishes enumerated (finite set of allowed values) from described (range or pattern constraint) annotation value domains (ISO 11179).

const (
	DomainEnumerated ValueDomainKind = "enumerated"
	DomainDescribed  ValueDomainKind = "described"
)

func (ValueDomainKind) IsValid

func (k ValueDomainKind) IsValid() bool

IsValid returns true if the value domain kind is one of the known variants.

func (ValueDomainKind) JSONSchema

func (ValueDomainKind) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (ValueDomainKind) String

func (k ValueDomainKind) String() string

type Visibility

type Visibility string

Visibility controls who can access a published transcript.

const (
	VisibilityPrivate Visibility = "private"
	VisibilityGroup   Visibility = "group"
	VisibilityPublic  Visibility = "public"
)

func (Visibility) IsValid

func (v Visibility) IsValid() bool

IsValid returns true if the visibility is one of the known variants.

func (Visibility) JSONSchema

func (Visibility) JSONSchema() (jsonschema.Schema, error)

JSONSchema implements jsonschema.Exposer.

func (Visibility) String

func (v Visibility) String() string

type WalkthroughStep

type WalkthroughStep struct {
	File    string `json:"file"`
	Line    *int   `json:"line,omitempty"`
	Excerpt string `json:"excerpt"`
}

WalkthroughStep is a single file visit in a session trail.

type WalkthroughTrail

type WalkthroughTrail struct {
	SessionID  string            `json:"sessionId"`
	Title      string            `json:"title"`
	Date       string            `json:"date"`
	TurnCount  int               `json:"turnCount"`
	Steps      []WalkthroughStep `json:"steps"`
	IsCoherent bool              `json:"isCoherent"` // true if linear path, false if scattered
}

WalkthroughTrail is the file path extracted from a single session.

Directories

Path Synopsis
cmd
gen-enum-corpora command
Command gen-enum-corpora writes the Local API 0.5.0 enum-exhaustion corpora to their committed artifacts.
Command gen-enum-corpora writes the Local API 0.5.0 enum-exhaustion corpora to their committed artifacts.
gen-license-corpus command
Command gen-license-corpus writes the enum-exhaustion license corpus to the committed artifact.
Command gen-license-corpus writes the enum-exhaustion license corpus to the committed artifact.
release-guard command
Command release-guard is the thin CLI the release workflows shell out to.
Command release-guard is the thin CLI the release workflows shell out to.
schema-gen command
Package enumcorpus generates the enum-exhaustion test corpora for the Local API 0.5.0 git+session timeline and insight-first code map closed sets (AssociationConclusion, AssociationEvidenceKind, Confidence, RewriteResolution, RewriteMethod, InsightKind, InsightProvenance, ReadAttributionState, ReadStateGrade) plus a regenerated TargetKind corpus (the file_version member added in the same tag).
Package enumcorpus generates the enum-exhaustion test corpora for the Local API 0.5.0 git+session timeline and insight-first code map closed sets (AssociationConclusion, AssociationEvidenceKind, Confidence, RewriteResolution, RewriteMethod, InsightKind, InsightProvenance, ReadAttributionState, ReadStateGrade) plus a regenerated TargetKind corpus (the file_version member added in the same tag).
internal
contractgates
Package contractgates holds the SYNTHETIC-BREAK tests for the schema repo's breaking-change contract gates: oasdiff for the OpenAPI specs and go-apidiff for the exported Go API.
Package contractgates holds the SYNTHETIC-BREAK tests for the schema repo's breaking-change contract gates: oasdiff for the OpenAPI specs and go-apidiff for the exported Go API.
release
Package release holds the pure, table-driven-testable logic that the release CI workflows depend on: the release-PR title grammar, the git-tag grammar, the typed release-kind derivation, and the final-release guard decision.
Package release holds the pure, table-driven-testable logic that the release CI workflows depend on: the release-PR title grammar, the git-tag grammar, the typed release-kind derivation, and the final-release guard decision.
Package licensecorpus generates the enum-exhaustion test corpus for the closed license menu (schema.AllLicenses).
Package licensecorpus generates the enum-exhaustion test corpus for the closed license menu (schema.AllLicenses).
Package openapi builds the committed OpenAPI 3.1 / JSON-Schema artifacts from the Go schema source.
Package openapi builds the committed OpenAPI 3.1 / JSON-Schema artifacts from the Go schema source.
Package testcase is the pure-data foundation for this module's canonical test-case corpus: a typed, generic Case/Corpus model with closed-set classification and provenance metadata, a pure YAML loader, and pure validators.
Package testcase is the pure-data foundation for this module's canonical test-case corpus: a typed, generic Case/Corpus model with closed-set classification and provenance metadata, a pure YAML loader, and pure validators.
assert
Package assert is the testing seam for the test-case corpus: helpers that take *testing.T and fail a test when a corpus violates its own invariants.
Package assert is the testing seam for the test-case corpus: helpers that take *testing.T and fail a test when a corpus violates its own invariants.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL