Expose reconcile state command

This commit is contained in:
2026-06-08 19:19:43 +00:00
parent de6723c5de
commit 2abd09bde3
10 changed files with 408 additions and 5 deletions

View File

@@ -16,7 +16,7 @@ Outputs include `RunReport`, `ReconcileStateReport`, validate/inspect/manifest r
`internal/app` wires packages together but does not own manifest validation rules, destination state comparison, storage path rules, publish safety policy, transform rendering, config schema validation, or backend protocol behavior.
User-facing command parsing stays in `internal/cli`. User-facing config reference stays in `docs/config.md`. External contracts live under `docs/integrations/`.
User-facing command parsing stays in `internal/cli`, including `reconcile-state` flag validation and help text. User-facing config reference stays in `docs/config.md`. External contracts live under `docs/integrations/`.
## Config Fields Used
@@ -34,7 +34,7 @@ The app layer registers default transforms, including Markdown-to-HTML, and supp
Run workflows discover and validate source bundles through `internal/bundle`. Destination state actions are prepared and written through `internal/publish` and `internal/state`; the app layer records report projections of those actions and results.
Reconcile-state workflows load one configured pipeline/destination selector, open that destination root, parse the root `.distributor.json`, and report missing managed output records plus unmanaged storage entries. Managed output existence checks use storage `Stat`; unmanaged reporting uses bounded storage `Walk` and excludes `.distributor.json` plus all paths already recorded as managed. Apply mode removes missing managed output records from state and rewrites valid state only; dry-run reports the same repair without writing. It does not validate output digests, delete destination files, adopt unmanaged files, or rewrite invalid or mismatched state.
Reconcile-state workflows load one configured pipeline/destination selector, open that destination root, parse the root `.distributor.json`, and report missing managed output records plus unmanaged storage entries. Managed output existence checks use storage `Stat`; unmanaged reporting uses bounded storage `Walk` and excludes `.distributor.json` plus all paths already recorded as managed. Apply mode removes missing managed output records from state and rewrites valid state only; dry-run reports the same repair without writing. Text output reports `changed`, `would_change`, or `unchanged`; JSON output uses the shared app envelope. It does not validate output digests, delete destination files, adopt unmanaged files, or rewrite invalid or mismatched state.
HTTP uploads stage and validate archives before enqueueing a pipeline run with a local staged source root. Go producers can use the public `pkg/upload` package to create client-side gzip tar uploads for this server contract; `internal/app` remains the server-side orchestration boundary and does not import that producer package.
@@ -57,6 +57,7 @@ HTTP upload startup fails if upload tokens are missing, empty, or duplicated. Up
## Tests To Inspect
- `internal/app/*_test.go`
- `internal/cli/reconcile_state_test.go`
- `internal/cli/root_test.go`
- `internal/config/*_test.go`
- `internal/ingest/*_test.go`

View File

@@ -48,7 +48,7 @@ Comparison is pure. It returns outcomes for absent state, unmanaged content, inv
Shared-root comparison is owner-scoped. It compares only the owner keyed by the current pipeline id and destination id, treats an absent owner as absent destination state for that owner, and can compare compatible single-owner state for the current owner without converting unrelated single-owner state.
Missing-output removal helpers are pure state transformations. They remove matching output records only and leave storage inspection, timestamp updates, validation, and state rewrites to callers.
Missing-output removal helpers are pure state transformations used by app-level state repair. They remove matching output records only and leave storage inspection, timestamp updates, validation, and state rewrites to callers.
## Failure Behavior
@@ -59,6 +59,8 @@ Parsing rejects invalid JSON, trailing data, missing required fields, invalid ti
- `internal/state/distributor_test.go`
- `internal/state/shared_root_test.go`
- `internal/state/compare_test.go`
- `internal/app/reconcile_state_test.go`
- `internal/cli/reconcile_state_test.go`
- `internal/publish/*_test.go`
## Architectural Invariants

View File

@@ -30,9 +30,11 @@ Storage owns `.distributor.json` path helpers through `StateFileName`, `StatePat
Logical paths are slash-separated and relative to a backend root. Prefix validation allows an empty prefix to mean the backend root; file path validation requires a non-empty path.
Reconcile-state callers use `Stat` to check whether managed output paths still exist and bounded recursive `Walk` to report unmanaged entries under a selected destination root. Storage does not decide whether entries are managed; callers compare entries against destination state.
## Skip And Resume Behavior
Storage has no publication skip policy. It supplies `HasAny` for unmanaged-content checks, `DeleteManagedBundle` target construction for normal replacement cleanup, and `DeletePrefix` semantics for explicit forced replacement.
Storage has no publication skip policy. It supplies `HasAny` for unmanaged-content checks, `Stat` and `Walk` for state repair inspection, `DeleteManagedBundle` target construction for normal replacement cleanup, and `DeletePrefix` semantics for explicit forced replacement.
## Failure Behavior
@@ -42,6 +44,7 @@ Storage errors use typed categories: not found, already exists, not empty, inval
- `internal/storage/*_test.go`
- `internal/storage/fake/*_test.go`
- `internal/app/reconcile_state_test.go`
- `internal/adapters/local/*_test.go`
- `internal/adapters/ssh/*_test.go`
- `internal/adapters/s3/*_test.go`