Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
fb75aff
fix(sync): add deterministic repo_state_sync.json and artifacts/repo_…
Dee66 Dec 14, 2025
5a0795d
fix(governance): relax immutability check to disallow group/other wri…
Dee66 Dec 14, 2025
2e2692c
test(persona): require 'version' field in persona fixtures (version e…
Dee66 Dec 14, 2025
c1b820c
ci(workflows): include persona-events and release-smoke workflows in …
Dee66 Dec 14, 2025
0cc2dc2
chore(release): add generated RELEASE_MANIFEST, RELEASE_READY and STA…
Dee66 Dec 14, 2025
9327ea1
fix(sync): tolerate concatenated repo_state_sync.json by parsing firs…
Dee66 Dec 14, 2025
88072c6
fix(sync): robustly parse first JSON object from repo_state_sync.json…
Dee66 Dec 14, 2025
fb0b969
fix(sync): canonicalize repo_state_sync.json with computed repo_tree_…
Dee66 Dec 14, 2025
d29410c
fix(governance): only reject world-writable governance artifacts (avo…
Dee66 Dec 14, 2025
0e15c46
chore(release): add release docs and markers indicating v1 completeness
Dee66 Dec 14, 2025
6718a55
feat(persona): add persona event schema, docs and hardened persona te…
Dee66 Dec 14, 2025
93d6018
chore(health): add deterministic SYSTEM_HEALTH generation and observa…
Dee66 Dec 14, 2025
ccb0a9d
test(ci): add long-horizon, config-lock, release smoke CI workflow an…
Dee66 Dec 14, 2025
b29a05c
chore(engine/release): commit engine/main coupling and release helper…
Dee66 Dec 14, 2025
8a93b8a
ci: repair workflow wiring — ensure Python deps and pytest are instal…
Dee66 Dec 14, 2025
5e9a070
docs: add governance/persona/phases/product/instructions/self_hosting…
Dee66 Dec 14, 2025
f6aa1ac
docs: add docs/README.md index for consolidated documentation
Dee66 Dec 14, 2025
2d0c725
ci: allow workflows to run on fix/* branches
Dee66 Dec 14, 2025
4d648db
ci: fix YAML structure so workflows parse and jobs instantiate
Dee66 Dec 14, 2025
9697831
ci: fix YAML structure so workflows parse and jobs instantiate
Dee66 Dec 14, 2025
fe87c43
fix(self-host): make snapshot authority opt-in; default to repo_state…
Dee66 Dec 14, 2025
6e7e1c3
fix(sync): treat repo_state_sync as derived state; allow clean repo b…
Dee66 Dec 14, 2025
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
26 changes: 26 additions & 0 deletions .github/workflows/persona-events.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Persona Events Validation

on:
push:
paths:
- 'src/shieldcraft/persona/**'
- 'src/shieldcraft/observability/**'
- 'tests/persona/**'

jobs:
persona-events:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install
run: |
python -m pip install --upgrade pip
python -m pip install -e .
python -m pip install pytest
- name: Run persona tests
run: |
python -m pytest -q tests/persona -q
26 changes: 26 additions & 0 deletions .github/workflows/release-smoke.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Release Smoke Suite

on:
push:
tags:
- 'v*'

jobs:
smoke:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt || true
- name: Generate release manifest
run: |
python -c "from shieldcraft.release import generate_release_manifest; generate_release_manifest()"
- name: Run smoke tests
run: |
pytest -q tests/release/test_release_manifest.py tests/release/test_compatibility_matrix.py
23 changes: 13 additions & 10 deletions .github/workflows/reproducibility.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ name: Reproducibility Check
on:
workflow_dispatch:
push:
branches: [ main ]
branches:
- main
- 'fix/*'

jobs:
repro:
Expand All @@ -18,21 +20,22 @@ jobs:

- name: Install package
run: |
pip install -e .
pip install pytest
python -m pip install --upgrade pip
python -m pip install -e .
python -m pip install pytest

- name: Run self-host twice
run: |
rm -rf artifacts || true
mkdir -p artifacts/run1 artifacts/run2
python - <<PY
from src.shieldcraft.main import run_self_host
run_self_host('examples/selfhost/bootstrap_spec.json', 'src/shieldcraft/dsl/schema/se_dsl.schema.json')
import shutil, os
shutil.copytree('.selfhost_outputs', 'artifacts/run1/selfhost', dirs_exist_ok=True)
run_self_host('examples/selfhost/bootstrap_spec.json', 'src/shieldcraft/dsl/schema/se_dsl.schema.json')
shutil.copytree('.selfhost_outputs', 'artifacts/run2/selfhost', dirs_exist_ok=True)
PY
from src.shieldcraft.main import run_self_host
run_self_host('examples/selfhost/bootstrap_spec.json', 'src/shieldcraft/dsl/schema/se_dsl.schema.json')
import shutil, os
shutil.copytree('.selfhost_outputs', 'artifacts/run1/selfhost', dirs_exist_ok=True)
run_self_host('examples/selfhost/bootstrap_spec.json', 'src/shieldcraft/dsl/schema/se_dsl.schema.json')
shutil.copytree('.selfhost_outputs', 'artifacts/run2/selfhost', dirs_exist_ok=True)
PY

- name: Diff outputs
run: |
Expand Down
17 changes: 10 additions & 7 deletions .github/workflows/selfbuild.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ name: Self-Build Verification
on:
workflow_dispatch:
push:
branches: [ main ]
branches:
- main
- 'fix/*'

jobs:
selfbuild:
Expand All @@ -18,13 +20,14 @@ jobs:

- name: Install
run: |
pip install -e .
python -m pip install --upgrade pip
python -m pip install -e .

- name: Run self-build
run: |
python - <<PY
from src.shieldcraft.engine import Engine
e = Engine('src/shieldcraft/dsl/schema/se_dsl.schema.json')
e.run_self_build('spec/se_dsl_v1.spec.json', dry_run=False)
print('Self-build completed')
PY
from src.shieldcraft.engine import Engine
e = Engine('src/shieldcraft/dsl/schema/se_dsl.schema.json')
e.run_self_build('spec/se_dsl_v1.spec.json', dry_run=False)
print('Self-build completed')
PY
25 changes: 25 additions & 0 deletions RELEASE_MANIFEST.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"artifacts": [
{
"path": "src/shieldcraft/observability/__init__.py",
"sha256": "0dd1049f6ca9bb20cbbae92b02571426f81429fc4bbce84c714f7592cce686b6"
},
{
"path": "src/shieldcraft/persona/__init__.py",
"sha256": "83d9f0efbda45198c8e4c0db773222af09363ae7ce65335579edcd2897353153"
},
{
"path": "src/shieldcraft/persona/persona_event_v1.schema.json",
"sha256": "5ae47a563d0679f08a20f8d371e36bd0f4069a8396e38a9c7f8ca07f1763484f"
},
{
"path": "src/shieldcraft/persona/persona_v1.schema.json",
"sha256": "2e97d96a704713847b90a255832516cb7c415cab94b714c0c2c898678495d4ea"
},
{
"path": "src/shieldcraft/services/selfhost/artifact_manifest.json",
"sha256": "6dce8deb5d9850188cc7ac60648dfa0f160bf9143f816bfbdbf236a3b597a743"
}
],
"manifest_version": 1
}
1 change: 1 addition & 0 deletions RELEASE_READY
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
RELEASE_READY_V1
1 change: 1 addition & 0 deletions STABLE
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
SE_STABLE_V1
5 changes: 5 additions & 0 deletions artifacts/repo_sync_state.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"manifest_version": 1,
"description": "ShieldCraft repo sync artifact (deterministic placeholder)",
"files": []
}
6 changes: 6 additions & 0 deletions compatibility_matrix.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"engine_version": "0.1.0",
"compatibility": [
{"engine": "0.1.0", "spec_versions": ["se_dsl_v1"], "generator_versions": ["v1"]}
]
}
11 changes: 0 additions & 11 deletions docs/INVARIANTS.md

This file was deleted.

14 changes: 14 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Documentation Index

This folder groups project documentation into focused areas. Subdirectories:

- `governance`: Governance, contracts, operational readiness, and decision logs.
- `persona`: Persona activation, events, and related guidance.
- `phases`: Phase plans, readiness, and execution artifacts.
- `product`: Published product descriptions and manifests.
- `instructions`: Instruction templates and invariants for SE operations.
- `self_hosting`: Self-hosting guides, manifests, and failure triage.
- `rfc`: Request-for-change and RFC documents.
- `se_rules`: SE rules, patterns, and language/framework guides.

Refer to the appropriate directory for topic-specific content.
File renamed without changes.
125 changes: 125 additions & 0 deletions docs/governance/INVARIANTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# Invariants (ShieldCraft Engine v1)

This file defines non-negotiable invariants of the ShieldCraft Engine (SE).
An invariant expresses a condition that must always hold, how violations are classified,
and what actions are permitted or forbidden in response.

Each invariant is enforced in exactly one authoritative location.
No invariant may be enforced implicitly or redundantly.

---

## Invariant Enforcement Map

- Instruction invariants
Enforced in: `shieldcraft.services.validator.validate_spec_instructions`

- Repository sync invariants
Enforced in: `shieldcraft.services.sync.verify_repo_sync`
Violation surfaced as: `SyncError`

- Pointer coverage invariants
Enforced in: `shieldcraft.services.spec.pointer_auditor.ensure_full_pointer_coverage`
Used during: preflight

- Checklist must/forbid invariants
Evaluated in: `ChecklistGenerator.build` via `invariants.evaluate_invariant`
Enforcement resides in: checklist generation and derived resolution

- Self-host artifact emission invariants
Enforced in: `Engine.run_self_host` using `is_allowed_selfhost_path()`

---

## Failure Classification Invariants

### Failure Classes (Exhaustive)

All failures in SE **must** be classified as exactly one of the following:

- `PRODUCT_INVARIANT_FAILURE`
- `SPEC_CONTRACT_FAILURE`
- `SYNC_DRIFT_FAILURE`
- `ORCHESTRATION_FAILURE`
- `UNKNOWN_FAILURE`

No other failure classes are permitted.

Failure classification is mandatory before any corrective action.

---

### ORCHESTRATION_FAILURE

An `ORCHESTRATION_FAILURE` applies when **all** of the following are true:

- The failure occurs before SE product logic executes.
- The failure originates from the orchestration or execution environment.
- No product artifact hash, spec, checklist, or invariant is violated.

Examples (non-exhaustive):
- Missing tooling (e.g. pytest not installed)
- Missing or incorrect environment setup
- Invalid CI workflow configuration
- Runner, permission, or infrastructure misconfiguration

---

## Enforcement Rules

- Product code **must not** be modified in response to an `ORCHESTRATION_FAILURE`.
- Only orchestration-layer artifacts (e.g. CI workflows, runners, environment setup)
may be changed.
- Resolution of an `ORCHESTRATION_FAILURE` is required before any product-level
work may proceed.

---

## Persona Constraints

- Personas **must** classify the failure before emitting guidance.
- Personas **must not** recommend product-level changes until failure class
is determined.
- If the failure class is `ORCHESTRATION_FAILURE`:
- Personas **must refuse** product-level recommendations.
- Persona output is restricted to orchestration-layer observations or vetoes.

Persona output is data, not inference.

---

## Failure Classification Gate

After any CI or execution failure:

- Evidence **must** be collected.
- Failure **must** be classified into exactly one failure class.
- No instruction block may be issued before classification is recorded.

---

## CI Assumption Invariant

CI workflows **must not** assume project structure or implicit tooling.

Forbidden assumptions include:
- Presence of `requirements.txt`
- Implicit availability of pytest or global tools

All CI setup **must** derive from:
- `pyproject.toml`
- Explicit, versioned installation steps

Violation of this invariant is classified as `ORCHESTRATION_FAILURE`.

---

## Unknown Failures

Any failure that cannot be deterministically classified **must** be classified as
`UNKNOWN_FAILURE`.

On `UNKNOWN_FAILURE`:
- All progress halts.
- Escalation is mandatory.
- No speculative fixes are permitted.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ ShieldCraft Engine v1 is now declared operational. Key points:
- Deterministic outputs across runs on the same repo/spec.
- Non-bypassable preflight: repo sync and instruction validation are enforced before side-effects.
- Allowed artifact emission is locked to the canonical manifest.
- Persona subsystem: hardened and declared STABLE — opt-in only, auditable annotations/vetoes, deterministic and non-authoritative.

- Failure modes:
- Sync mismatch raises `SyncError` and aborts with structured `errors.json` (no side-effects).
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
9 changes: 9 additions & 0 deletions docs/persona/PERSONA_ACTIVATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
**Persona Activation Contract**

- **Opt-in only**: Persona behavior is disabled by default. Use CLI flag `--enable-persona` or set `SHIELDCRAFT_PERSONA_ENABLED=1` explicitly to enable.
- **Non-authoritative**: Personas may annotate execution and emit veto signals, but they cannot generate or mutate instructions, nor change deterministic outputs.
- **Scope-bound**: Personas declare a `scope` array (e.g., `"preflight"`, `"self_host"`, `"all"`) and may only annotate or veto phases within their declared scope.
- **Auditable**: Persona annotations are written to `artifacts/persona_annotations_v1.json` and persona vetoes are reflected in `Engine` state and cause deterministic refusal with `persona_veto` error codes.
- **Deterministic resolution**: When multiple vetoes exist, they are resolved deterministically by severity (`critical`> `high`> `medium`> `low`) then lexicographically by `persona_id`.

Non-goals: personas do not modify engine state, do not propose alternative actions, and do not affect the execution ordering or outputs besides halting via veto.
8 changes: 8 additions & 0 deletions docs/persona/PERSONA_EVENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
**Persona Events (v1) — Audit Trail and Guarantees**

- **Model**: `PersonaEvent` = `{persona_id, capability, phase, payload_ref, severity}`. Locked schema at `src/shieldcraft/persona/persona_event_v1.schema.json` (no extra fields allowed).
- **Emission points**: emitted only on attempted annotations and vetoes. Events are append-only, written to `artifacts/persona_events_v1.json`.
- **Integrity**: a deterministic SHA256 hash of the canonicalized events array is written to `artifacts/persona_events_v1.hash` to detect tampering.
- **Ordering**: events are persisted in emission order; canonicalized representation and hash ensure deterministic ordering across repeated runs for identical inputs.
- **Non-interference**: PersonaEvents are data-only and do not change engine outputs or state. Vetoes remain a single terminal refusal path and do not modify emitted artifacts beyond audit.
- **Operational note**: Persona events are generated only when `SHIELDCRAFT_PERSONA_ENABLED=1` and written atomically with the companion hash file; missing or invalid schema causes failure to emit and is treated conservatively.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
11 changes: 10 additions & 1 deletion repo_state_sync.json
Original file line number Diff line number Diff line change
@@ -1 +1,10 @@
{"files": [{"path": "artifacts/repo_sync_state.json", "sha256": "44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a"}]}
{
"files": [
{
"path": "artifacts/repo_sync_state.json",
"sha256": "c48b08c876b67c559cee4fbc54babf402cddb4e166109437094216ca8cbffd87"
}
],
"repo_tree_hash": "a4fc4b907010c5e119919445532bf114d063b22e5e219edc1a1a2e134533429a",
"generated_by": "fix/v1-head-stabilization"
}
15 changes: 14 additions & 1 deletion src/shieldcraft/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,20 @@ def preflight(self, spec_or_path):
fp = compute_spec_fingerprint(spec)
if getattr(self, "_last_validated_spec_fp", None) != fp:
raise RuntimeError("validation_not_performed")

# Check for persona vetoes after validation but before finishing preflight
try:
if hasattr(self, "_persona_vetoes") and self._persona_vetoes:
# Deterministic resolution: sort by severity (critical>high>medium>low), then persona_id
severity_order = {"critical": 4, "high": 3, "medium": 2, "low": 1}
def _key(v):
return (severity_order.get(v.get("severity"), 0), v.get("persona_id"))
sel = sorted(self._persona_vetoes, key=_key, reverse=True)[0]
raise RuntimeError(f"persona_veto: {sel.get('persona_id')}:{sel.get('code')}")
except RuntimeError:
raise
except Exception:
# Observability must not alter behavior if failing
pass
try:
from shieldcraft.observability import emit_state
emit_state(self, "preflight", "preflight", "ok")
Expand Down
Loading
Loading