# internal/app/harden

Package harden opens and completes spec hardening rounds.

## ErrMissingSpecStore

```go
var (
	// ErrMissingSpecStore is returned when hardening has no spec store.
	ErrMissingSpecStore = errors.New("missing spec store")
	// ErrNoHardenRound is returned when marking pass without an open round.
	ErrNoHardenRound = errors.New("no harden round exists")
	// ErrSpecNotDraft is returned when hardening a non-draft spec.
	ErrSpecNotDraft = errors.New("harden only operates on drafts")
	// ErrInvalidHardenEvidence is returned when a hardening round has unverified citations.
	ErrInvalidHardenEvidence = errors.New("invalid harden evidence")
	// ErrHardenRoundOpen is returned when another harden round is still open.
	ErrHardenRoundOpen = errors.New("harden round already in progress")
	// ErrHardenRevisionRequired is returned when a provider harden rerun is attempted without draft edits.
	ErrHardenRevisionRequired = errors.New("harden revision required before rerun")
	// ErrHardenRepairPacketInvalid is returned when a repaired provider packet cannot be accepted.
	ErrHardenRepairPacketInvalid = errors.New("harden repair packet cannot be accepted")
)
```

## ErrNoHardenRound

```go
var (
	// ErrMissingSpecStore is returned when hardening has no spec store.
	ErrMissingSpecStore = errors.New("missing spec store")
	// ErrNoHardenRound is returned when marking pass without an open round.
	ErrNoHardenRound = errors.New("no harden round exists")
	// ErrSpecNotDraft is returned when hardening a non-draft spec.
	ErrSpecNotDraft = errors.New("harden only operates on drafts")
	// ErrInvalidHardenEvidence is returned when a hardening round has unverified citations.
	ErrInvalidHardenEvidence = errors.New("invalid harden evidence")
	// ErrHardenRoundOpen is returned when another harden round is still open.
	ErrHardenRoundOpen = errors.New("harden round already in progress")
	// ErrHardenRevisionRequired is returned when a provider harden rerun is attempted without draft edits.
	ErrHardenRevisionRequired = errors.New("harden revision required before rerun")
	// ErrHardenRepairPacketInvalid is returned when a repaired provider packet cannot be accepted.
	ErrHardenRepairPacketInvalid = errors.New("harden repair packet cannot be accepted")
)
```

## ErrSpecNotDraft

```go
var (
	// ErrMissingSpecStore is returned when hardening has no spec store.
	ErrMissingSpecStore = errors.New("missing spec store")
	// ErrNoHardenRound is returned when marking pass without an open round.
	ErrNoHardenRound = errors.New("no harden round exists")
	// ErrSpecNotDraft is returned when hardening a non-draft spec.
	ErrSpecNotDraft = errors.New("harden only operates on drafts")
	// ErrInvalidHardenEvidence is returned when a hardening round has unverified citations.
	ErrInvalidHardenEvidence = errors.New("invalid harden evidence")
	// ErrHardenRoundOpen is returned when another harden round is still open.
	ErrHardenRoundOpen = errors.New("harden round already in progress")
	// ErrHardenRevisionRequired is returned when a provider harden rerun is attempted without draft edits.
	ErrHardenRevisionRequired = errors.New("harden revision required before rerun")
	// ErrHardenRepairPacketInvalid is returned when a repaired provider packet cannot be accepted.
	ErrHardenRepairPacketInvalid = errors.New("harden repair packet cannot be accepted")
)
```

## ErrInvalidHardenEvidence

```go
var (
	// ErrMissingSpecStore is returned when hardening has no spec store.
	ErrMissingSpecStore = errors.New("missing spec store")
	// ErrNoHardenRound is returned when marking pass without an open round.
	ErrNoHardenRound = errors.New("no harden round exists")
	// ErrSpecNotDraft is returned when hardening a non-draft spec.
	ErrSpecNotDraft = errors.New("harden only operates on drafts")
	// ErrInvalidHardenEvidence is returned when a hardening round has unverified citations.
	ErrInvalidHardenEvidence = errors.New("invalid harden evidence")
	// ErrHardenRoundOpen is returned when another harden round is still open.
	ErrHardenRoundOpen = errors.New("harden round already in progress")
	// ErrHardenRevisionRequired is returned when a provider harden rerun is attempted without draft edits.
	ErrHardenRevisionRequired = errors.New("harden revision required before rerun")
	// ErrHardenRepairPacketInvalid is returned when a repaired provider packet cannot be accepted.
	ErrHardenRepairPacketInvalid = errors.New("harden repair packet cannot be accepted")
)
```

## ErrHardenRoundOpen

```go
var (
	// ErrMissingSpecStore is returned when hardening has no spec store.
	ErrMissingSpecStore = errors.New("missing spec store")
	// ErrNoHardenRound is returned when marking pass without an open round.
	ErrNoHardenRound = errors.New("no harden round exists")
	// ErrSpecNotDraft is returned when hardening a non-draft spec.
	ErrSpecNotDraft = errors.New("harden only operates on drafts")
	// ErrInvalidHardenEvidence is returned when a hardening round has unverified citations.
	ErrInvalidHardenEvidence = errors.New("invalid harden evidence")
	// ErrHardenRoundOpen is returned when another harden round is still open.
	ErrHardenRoundOpen = errors.New("harden round already in progress")
	// ErrHardenRevisionRequired is returned when a provider harden rerun is attempted without draft edits.
	ErrHardenRevisionRequired = errors.New("harden revision required before rerun")
	// ErrHardenRepairPacketInvalid is returned when a repaired provider packet cannot be accepted.
	ErrHardenRepairPacketInvalid = errors.New("harden repair packet cannot be accepted")
)
```

## ErrHardenRevisionRequired

```go
var (
	// ErrMissingSpecStore is returned when hardening has no spec store.
	ErrMissingSpecStore = errors.New("missing spec store")
	// ErrNoHardenRound is returned when marking pass without an open round.
	ErrNoHardenRound = errors.New("no harden round exists")
	// ErrSpecNotDraft is returned when hardening a non-draft spec.
	ErrSpecNotDraft = errors.New("harden only operates on drafts")
	// ErrInvalidHardenEvidence is returned when a hardening round has unverified citations.
	ErrInvalidHardenEvidence = errors.New("invalid harden evidence")
	// ErrHardenRoundOpen is returned when another harden round is still open.
	ErrHardenRoundOpen = errors.New("harden round already in progress")
	// ErrHardenRevisionRequired is returned when a provider harden rerun is attempted without draft edits.
	ErrHardenRevisionRequired = errors.New("harden revision required before rerun")
	// ErrHardenRepairPacketInvalid is returned when a repaired provider packet cannot be accepted.
	ErrHardenRepairPacketInvalid = errors.New("harden repair packet cannot be accepted")
)
```

## ErrHardenRepairPacketInvalid

```go
var (
	// ErrMissingSpecStore is returned when hardening has no spec store.
	ErrMissingSpecStore = errors.New("missing spec store")
	// ErrNoHardenRound is returned when marking pass without an open round.
	ErrNoHardenRound = errors.New("no harden round exists")
	// ErrSpecNotDraft is returned when hardening a non-draft spec.
	ErrSpecNotDraft = errors.New("harden only operates on drafts")
	// ErrInvalidHardenEvidence is returned when a hardening round has unverified citations.
	ErrInvalidHardenEvidence = errors.New("invalid harden evidence")
	// ErrHardenRoundOpen is returned when another harden round is still open.
	ErrHardenRoundOpen = errors.New("harden round already in progress")
	// ErrHardenRevisionRequired is returned when a provider harden rerun is attempted without draft edits.
	ErrHardenRevisionRequired = errors.New("harden revision required before rerun")
	// ErrHardenRepairPacketInvalid is returned when a repaired provider packet cannot be accepted.
	ErrHardenRepairPacketInvalid = errors.New("harden repair packet cannot be accepted")
)
```

## Run

```go
func Run(ctx context.Context, store SpecStore, clock Clock, input Input) (Output, error)
```

Run opens a hardening round or marks the latest round passed.

## Clock

```go
type Clock interface {
	Now() time.Time
}
```

Clock supplies hardening timestamps.

- `Now: func() time.Time`: 

## Input

```go
type Input struct {
	TaskID                  string
	MarkPassed              bool
	Root                    string
	Prompt                  string
	Contract                agentcontract.Contract
	Provider                Provider
	ContextMaxBytes         int
	RequiredContextMaxBytes int
	EvidenceRoots           []string
	SuppressContext         bool
	RepairPacketPath        string
}
```

Input describes a hardening operation.

- `TaskID: string`: 
- `MarkPassed: bool`: 
- `Root: string`: 
- `Prompt: string`: 
- `Contract: agentcontract.Contract`: 
- `Provider: Provider`: 
- `ContextMaxBytes: int`: 
- `RequiredContextMaxBytes: int`: 
- `EvidenceRoots: []string`: 
- `SuppressContext: bool`: 
- `RepairPacketPath: string`: 

## Output

```go
type Output struct {
	TaskID       string            `json:"task_id"`
	Path         string            `json:"path"`
	HardenStatus spec.HardenStatus `json:"harden_status"`
	RoundID      string            `json:"round_id"`
	MarkedPassed bool              `json:"marked_passed"`
	NextCommand  string            `json:"next_command"`
	Prompt       string            `json:"prompt"`
	Context      string            `json:"context,omitempty"`
	Verdict      string            `json:"verdict,omitempty"`
	Summary      string            `json:"summary,omitempty"`
	Provider     string            `json:"provider,omitempty"`
	Model        string            `json:"model,omitempty"`
	SpecDigest   string            `json:"spec_digest,omitempty"`
	Warnings     []string          `json:"warnings"`
}
```

Output describes the opened or completed hardening round.

- `TaskID: string` (json:"task_id"): 
- `Path: string` (json:"path"): 
- `HardenStatus: spec.HardenStatus` (json:"harden_status"): 
- `RoundID: string` (json:"round_id"): 
- `MarkedPassed: bool` (json:"marked_passed"): 
- `NextCommand: string` (json:"next_command"): 
- `Prompt: string` (json:"prompt"): 
- `Context: string` (json:"context,omitempty"): 
- `Verdict: string` (json:"verdict,omitempty"): 
- `Summary: string` (json:"summary,omitempty"): 
- `Provider: string` (json:"provider,omitempty"): 
- `Model: string` (json:"model,omitempty"): 
- `SpecDigest: string` (json:"spec_digest,omitempty"): 
- `Warnings: []string` (json:"warnings"): 

## Provider

```go
type Provider interface {
	Invoke(context.Context, coreharden.Request) (coreharden.Dossier, error)
}
```

Provider is the external hardening provider port.

- `Invoke: func(context.Context, coreharden.Request) (coreharden.Dossier, error)`: 

## SpecStore

```go
type SpecStore interface {
	Load(context.Context, string) (spec.Model, string, error)
	Save(context.Context, string, spec.Model) error
}
```

SpecStore is the spec persistence port used by hardening.

- `Load: func(context.Context, string) (spec.Model, string, error)`: 
- `Save: func(context.Context, string, spec.Model) error`:
