Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
---
# Copyright 2026 Ego Hygiene
# SPDX-License-Identifier: MIT
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json

name: Validate Pace lock contract

on:
pull_request:
push:
branches:
- main
workflow_dispatch:

permissions:
contents: read

concurrency:
group: "pace-validation-${{ github.workflow }}-${{ github.ref }}"
cancel-in-progress: true

jobs:
validate:
name: Validate schema, example, implementation, and tests
runs-on: ubuntu-latest
timeout-minutes: 10

steps:
- name: Harden runner
# step-security/harden-runner v2.21.0
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c
with:
egress-policy: audit

- name: Checkout Pace
# actions/checkout v7.0.1
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
with:
persist-credentials: false

- name: Validate the complete example lock
run: >-
python3 scripts/validate_lock.py
examples/pace.lock.json
--as-of "2026-08-22T00:00:00Z"

- name: Run adversarial validator tests
run: >-
python3 -m unittest discover
--start-directory tests
--pattern "test_*.py"
--verbose

- name: Compile Python sources
run: python3 -m compileall -q scripts tests

- name: Parse checked-in JSON
shell: bash
run: |
set -euo pipefail
while IFS= read -r document; do
python3 -m json.tool "${document}" >/dev/null
done < <(find examples schemas -type f -name "*.json" -print | sort)
22 changes: 20 additions & 2 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ status: provisional
owners:
- egohygiene
created: 2026-08-19
updated: 2026-08-19
updated: 2026-08-21
governed_by:
- architecture-architecture
depends_on:
Expand Down Expand Up @@ -60,6 +60,21 @@ flowchart LR

The diagram is conceptual. [SYSTEM.md](SYSTEM.md) remains authoritative for responsibilities and implementation evidence determines current availability.

## Implemented lock-validation slice

```text
schemas/pace-lock-v1.schema.json # closed desired-state contract
examples/pace.lock.json # six-kind conformance example
scripts/validate_lock.py # offline independent validator
tests/test_validate_lock.py # adversarial contract evidence
.github/workflows/validate.yml # least-privilege validation gate
```

The validator is deliberately independent from future source resolvers and
updaters. It reads one lock, validates immutable provenance, ownership,
compatibility, rollback, and exception time bounds, and emits evidence without
network or write capabilities.

## Dependency rules

- Sibling domain capabilities integrate through versioned public contracts, not direct access to internals.
Expand All @@ -83,7 +98,10 @@ The architecture favors independently usable local and self-hosted operation. Op

## Evidence and uncertainty

- **Observed:** The repository README establishes the intended boundary as the repository adoption, reconciliation, synchronization, and conformance mechanism for the Ego Hygiene organization; significant implementation remains incomplete.
- **Observed:** Pace owns a versioned dependency-lock schema, six-kind example,
standalone offline validator, adversarial test suite, and least-privilege CI
gate. Update resolution, drift detection, planning, and application remain
unimplemented.
- **Decided for this draft:** The repository owns the bounded concern described here and participates through versioned contracts.
- **Proposed:** Target systems and later roadmap phases remain proposals until accepted and implemented.
- **Open question:** Which parts of this draft should become active in the first independently versioned release?
14 changes: 12 additions & 2 deletions DECISIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ status: provisional
owners:
- egohygiene
created: 2026-08-19
updated: 2026-08-19
updated: 2026-08-21
governed_by:
- architecture-decisions
depends_on:
Expand Down Expand Up @@ -40,6 +40,7 @@ Do not rewrite historical context to fit current understanding. Amend a record f
- ADR-001: Separate detection, planning, and application
- ADR-002: Preserve repository-local overrides as first-class records
- ADR-003: Require reviewable changes for synchronization
- ADR-004: Make desired-state locks independently verifiable

## ADR-001: Separate detection, planning, and application

Expand Down Expand Up @@ -68,9 +69,18 @@ Do not rewrite historical context to fit current understanding. Amend a record f
- **Consequences:** The choice improves ownership and predictability while requiring maintained contracts, validation, and migration discipline.
- **Reconsider when:** New evidence shows that the boundary prevents standalone usefulness, safety, portability, or maintainability.

## ADR-004: Make desired-state locks independently verifiable

- **Status:** Accepted for the v1 lock contract
- **Date:** 2026-08-21
- **Context:** A synchronization tool cannot be the sole authority asserting that its own update output is safe. Repositories need a portable record of source identity, content integrity, generated ownership, compatibility, rollback, and temporary exceptions before any updater receives write authority.
- **Decision:** Define a closed JSON lock contract covering foundation, Aether, workflow, container, site, and schema dependencies. Require immutable references and SHA-256 digests. Validate the lock with a standard-library-only tool that has no network, updater, or write capability. Treat exceptions as approved records with bounded expiry, never as integrity bypasses.
- **Consequences:** Desired state is reviewable and independently testable before drift or apply exists. The lock duplicates some upstream metadata, and later resolvers must prove that fetched bytes match it. Contract-breaking changes require a new lock schema major and migration.
- **Reconsider when:** A portable signed manifest standard can express the same repository ownership, compatibility, rollback, and exception semantics without weakening offline validation.

## Open decisions

- Release and compatibility policy for the first stable version.
- Signing and transparency policy for future resolved locks and update plans.
- Exact self-hosted, managed, and organization-integrated deployment boundaries.
- Which target systems must exist before the architecture status may become active.

Expand Down
130 changes: 130 additions & 0 deletions LOCK_POLICY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# Pace lock, provenance, exception, and update policy

## Purpose

A Pace lock is a repository-owned record of the exact foundation, Aether,
workflow, container, site, and schema inputs a repository has adopted. It makes
desired state reviewable without giving Pace permission to update anything.

The v1 contract is [`egohygiene.pace.lock/v1`](schemas/pace-lock-v1.schema.json).
Locks are JSON so standard review tools, JSON Schema tooling, and the standalone
validator can inspect the same closed representation.

## Required provenance

Every lock entry records:

- a stable entry ID and one of the six supported dependency kinds;
- the source owner, locator, human version, immutable reference type, immutable
reference, and SHA-256 content digest;
- the target repository path, its owner, whether it is generated or
consumer-owned, and the generator when applicable;
- the compatibility contract and accepted major version;
- migration and rollback state;
- either no exception or one approved, tracked, time-bounded exception.

Git sources use a full lowercase 40-character commit SHA. OCI sources use an
immutable `sha256:` manifest digest. Content-addressed site or schema inputs use
a `sha256:` reference. For OCI and content-addressed sources, the reference and
recorded digest must agree. A future resolver may additionally fetch and verify
bytes, but the independent validator performs no network calls and never trusts
an updater's result.

## Generated ownership

Target ownership controls what a future Pace apply phase may change:

| Management | Generator | Required rollback | Meaning |
| --- | --- | --- | --- |
| `generated` | Required owner/repository identity | `restore-lock-and-generated-targets` | The named generator owns regeneration; reviewed rollback restores both the previous lock and generated target bytes |
| `consumer-owned` | Must be `null` | `restore-lock-only` | Pace records desired source state but never rewrites the target; the consumer owns migration and content rollback |

A lock does not grant write authority. Detection, update planning, application,
verification, and publication remain separate operations.

## Compatibility and migration

Every entry names a contract ending in `/vMAJOR`; `accepted_major` must match.
Unknown contracts fail closed. Compatibility within a major does not imply that
an update is behaviorally safe—it means the source declares the same contract
family and may proceed to review and verification.

Migration states are:

- `not-required`: the selected source is compatible with the target state;
- `required`: migration work is known but incomplete, so validation fails and
the lock is not adoptable;
- `completed`: required migration evidence is included in the reviewed change.

A major transition requires a new contract declaration, explicit migration,
and a reviewed lock update. Pace never silently widens a compatibility range.

## Update sequence

A future updater must preserve these boundaries:

1. Read and independently validate the existing lock.
2. Resolve candidate source versions without modifying the repository.
3. Verify immutable references and content digests.
4. Compare declared contract majors and identify migration requirements.
5. Produce a deterministic plan containing lock and owned-target changes.
6. Open a reviewable pull request; never push directly to the default branch.
7. Run the standalone validator on the proposed lock independently of the
updater.
8. Regenerate only targets marked `generated` and owned by the named generator.
9. Verify resulting bytes and repository tests before merge.

The v1 work implements steps 1 and 7. Resolution, planning, and application are
deliberately outside this issue.

## Rollback

The previous accepted lock is the rollback anchor. A failed or reverted update:

- restores the previous lock document;
- restores previous bytes for targets whose management is `generated`;
- leaves consumer-owned target content under consumer control;
- reruns independent validation and repository verification;
- records the failed source version so automation does not immediately repeat
the same unsafe update.

Rollback never replaces a lock with an unreviewed mutable reference.

## Exceptions

Exceptions are first-class lock records, not comments or hidden repository
settings. Each includes a unique `EXC-YYYY-NNN` ID, reason, approver, issue time,
expiry time, and HTTPS tracking URL.

- Repository policy bounds exceptions to 1–90 days.
- An entry's expiry must be after issuance and within the repository maximum.
- Future and expired exceptions fail validation at the selected validation
instant.
- Exceptions never bypass JSON structure, immutable-reference, digest,
ownership, compatibility-major, or rollback requirements.
- Renewal is a new reviewed decision with a new bounded interval; expiry is not
extended silently.

Use `--as-of` in tests and evidence pipelines for deterministic evaluation.
Normal local validation uses the current UTC instant.

## Independent validation

```bash
python3 scripts/validate_lock.py "path/to/pace.lock.json"

python3 scripts/validate_lock.py \
"path/to/pace.lock.json" \
--as-of "2026-08-22T00:00:00Z" \
--format "json"
```

The validator uses only the Python standard library. It rejects duplicate JSON
keys, unknown fields, malformed or mutable references, inconsistent digests,
ambiguous ownership, unsafe rollback declarations, duplicate IDs or targets,
unsorted entries, pending migrations, and invalid exception windows.

Exit status `0` means the lock is valid at the evaluation instant. Status `1`
means the document could not be loaded or violates the lock contract. Argument
errors use the standard status `2`. JSON output uses
`egohygiene.pace.lock-validation/v1`.
34 changes: 34 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,36 @@
# pace

⚡ Automation, CI/CD, adoption, reconciliation, and synchronization infrastructure for evolving repositories.

Pace begins with a read-only, independently verifiable desired-state lock. The
`egohygiene.pace.lock/v1` contract records exact foundation, Aether, workflow,
container, site, and schema sources; their immutable references and SHA-256
digests; target ownership; compatibility and migration state; rollback mode;
and bounded exceptions.

## Validate a lock

```bash
python3 scripts/validate_lock.py "examples/pace.lock.json"
```

The validator has no updater dependency, third-party Python packages, network
access, or write behavior. It validates the example, contract semantics,
generated ownership, and exception expiry independently.

```bash
python3 scripts/validate_lock.py \
"examples/pace.lock.json" \
--as-of "2026-08-22T00:00:00Z" \
--format "json"
```

See the complete [lock and update policy](LOCK_POLICY.md), the
[JSON Schema](schemas/pace-lock-v1.schema.json), and the
[six-kind example](examples/pace.lock.json).

## Current authority boundary

Pace v1 validates desired state only. It does not resolve updates, edit files,
open pull requests, or apply changes. Future detection, planning, application,
verification, and publication phases remain separate authority boundaries.
9 changes: 7 additions & 2 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ status: provisional
owners:
- egohygiene
created: 2026-08-19
updated: 2026-08-19
updated: 2026-08-21
governed_by:
- architecture-roadmap
depends_on:
Expand All @@ -32,6 +32,9 @@ This roadmap describes capability evolution, not promised dates or an issue queu

## Phase 1: Define desired and observed state schemas

**Status:** Desired dependency lock v1 is implemented and independently
validated. Observed-state and drift schemas remain planned for Phase 2.

**Outcome:** A bounded capability advances from documented intent to validated, independently usable behavior.

**Exit signals:**
Expand Down Expand Up @@ -104,7 +107,9 @@ Optional managed services, enterprise controls, marketplaces, and the conversati

## Evidence and uncertainty

- **Observed:** The repository README establishes the intended boundary as the repository adoption, reconciliation, synchronization, and conformance mechanism for the Ego Hygiene organization; significant implementation remains incomplete.
- **Observed:** Pace owns `egohygiene.pace.lock/v1`, an offline validator,
adversarial exception and provenance tests, a six-kind example, and a CI gate.
No updater or repository mutation path exists.
- **Decided for this draft:** The repository owns the bounded concern described here and participates through versioned contracts.
- **Proposed:** Target systems and later roadmap phases remain proposals until accepted and implemented.
- **Open question:** Which parts of this draft should become active in the first independently versioned release?
8 changes: 6 additions & 2 deletions SYSTEM.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ status: provisional
owners:
- egohygiene
created: 2026-08-19
updated: 2026-08-19
updated: 2026-08-21
governed_by:
- architecture-system
depends_on:
Expand All @@ -32,6 +32,8 @@ This document identifies Pace's logical systems and responsibilities. It answers

| System | State | Responsibility |
| --- | --- | --- |
| Desired-state lock contract | Active | Records immutable source identity, content digest, target ownership, compatibility, rollback, and bounded exceptions for six dependency kinds. |
| Independent lock validator | Active | Validates lock structure and semantics offline without trusting an updater or receiving write authority. |
| Repository inventory reader | Target | Owns its bounded portion of the repository adoption, reconciliation, synchronization, and conformance mechanism for the Ego Hygiene organization; exposes explicit inputs, outputs, failure states, and evidence. |
| Desired-state resolver | Target | Owns its bounded portion of the repository adoption, reconciliation, synchronization, and conformance mechanism for the Ego Hygiene organization; exposes explicit inputs, outputs, failure states, and evidence. |
| Drift engine | Target | Owns its bounded portion of the repository adoption, reconciliation, synchronization, and conformance mechanism for the Ego Hygiene organization; exposes explicit inputs, outputs, failure states, and evidence. |
Expand Down Expand Up @@ -61,7 +63,9 @@ Systems fail closed at destructive, publication, privacy, and security boundarie

## Evidence and uncertainty

- **Observed:** The repository README establishes the intended boundary as the repository adoption, reconciliation, synchronization, and conformance mechanism for the Ego Hygiene organization; significant implementation remains incomplete.
- **Observed:** Desired-state lock validation is active. Repository inventory,
drift, planning, application, override storage, and reporting remain target
systems.
- **Decided for this draft:** The repository owns the bounded concern described here and participates through versioned contracts.
- **Proposed:** Target systems and later roadmap phases remain proposals until accepted and implemented.
- **Open question:** Which parts of this draft should become active in the first independently versioned release?
Loading