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
13 changes: 12 additions & 1 deletion BOOTSTRAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,18 @@ plus history-preserving promotion; implementation remains PLANNED.
scaffolder. This design neither starts a Mission nor changes Mission 3, live
policies, credentials, runtime schemas or package versions.

## Current pickup checkpoint — 17 September 2026
## Criterion completion source checkpoint — 18 September 2026

[Implementation PR #149](https://github.com/pcvantol/forge/pull/149) is
protected-merged at `6199a7645c15f078aa69d6246023b078069a9742`.
Read the [separate source finalization](docs/operations/CRITERION_COMPLETION_SOURCE_FINALIZATION.md)
and [qualification boundaries](docs/operations/CRITERION_COMPLETION_QUALIFICATION.md)
for criterion-bound assessment, durable successor planning and the distinct
source, provider, peer and installed-composition evidence. Publication and
installed activation remain required under the same repair assignment;
this checkpoint does not authorize a reset or Mission 3.

## Previous pickup checkpoint — 17 September 2026

Implementation PR #128 merged the deterministic aggregate-health timeout-boundary
correction at `1726f774cb42894d3d3386e80adee9444c7a7914`. The evaluated candidate
Expand Down
80 changes: 80 additions & 0 deletions docs/operations/CRITERION_COMPLETION_SOURCE_FINALIZATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# Criterion completion source finalization

Assignment: `L1-CRITERION-PLANNING-REPAIR-20260918`, 18 September 2026.
This is the separate source finalization for
[implementation PR #149](https://github.com/pcvantol/forge/pull/149), merged
through the protected route at
`6199a7645c15f078aa69d6246023b078069a9742`.
It is an intermediate delivery checkpoint: publication, exact registry
artifacts, safe installed activation and the final completion record remain
required within this same assignment.

## Immutable source and assurance

The independently reviewed implementation candidate is
`b368052ed59b18b19182ee724802f5d67d264340`, tree
`085c7b419efc10b782002167642a7462ec03958a`.
Separate Quality and Security reviewers did not author the implementation.
Both returned PASS with no open findings on this exact candidate. Quality
reran 171 focused tests with one opt-in skip; Security reran 50 focused tests.
The earlier three Quality findings and their corrections remain documented in
the [qualification record](CRITERION_COMPLETION_QUALIFICATION.md).

Owning validation passed 817 tests with one existing optional exact-artifact
test skipped, plus compilation, version policy, projection, JSON and whitespace
checks. The hosted required
[Test and static validation run](https://github.com/pcvantol/forge/actions/runs/35336005960)
passed; CodeQL, version validation and advisory TDE checks also passed before
merge. No branch protection or check requirement was bypassed.

A clean Git archive of that candidate produced qualified wheel and sdist
payloads. The noneditable wheel passed all eight normal installed composition
scenarios across separate processes. Candidate artifact digests are:

| Candidate artifact | SHA-256 |
| --- | --- |
| `forge_autonomy-2.7.25-py3-none-any.whl` | `3e288c76ec0b53a4aba795103eb72a53a7bb98667c7c9584ba87c02267762d45` |
| `forge_autonomy-2.7.25.tar.gz` | `9cf5f07cf16464cf531cfe89cf6d5133f14562b94ff3c7b61d57acaf717d91d9` |

These are candidate-only bytes, not the later published release artifacts.
The real provider result, retained failed attempt, EP HTTP qualification and
actual schema-38 migration fixture are separately scoped in the qualification
record. None represents a production Mission run.

## Delivered behavior and remaining delivery gates

Finalization review caught a producer/consumer mismatch before publication:
the release workflow now retains installed-composition summaries, while the
updater's original strict receipt shape rejected those additional fields.
This finalization binds both qualification and registry-readback summaries
to the exact 2.7.25 wheel and requires all eight expected outcomes, counts and
history/reopen guarantees. Captured summary-shape tests reject missing,
malformed, mismatched or incomplete evidence. Older release receipt shapes
remain unchanged. This is a bounded release-to-updater correction within the
same version and assignment; no published receipt is rewritten.

The [criterion assessment contract](../architecture/criterion-completion-v2.md)
binds substantive evidence to approved criterion semantics and preserves
original observations. Partial completion enters the durable successor route;
fully proven criteria can finish after one Action. Current-revision properties
are reobserved on later Repository Truth. Safe legacy readback, finite planning
and replay retain their explicit failure boundaries.

The release version is selected once as **2.7.25**, with schema **39** and the
bounded supported updater transition from **2.7.24/schema 38**. The normal
production workflow must build from the final protected source, retain exact
qualification/publication/completion receipts, verify downloaded PyPI bytes
and repeat the installed composition qualification. The existing updater must
then qualify and activate those exact bytes with preservation checks and a
new concrete peer-coordinated activation window.

The repository JSON route proves only its approved structural assertion;
`host_control` remains unsupported until authoritative EP control receipts
are exported. Provider usage is checked after generation, not guaranteed by a
hard token preflight. Those limitations remain prerequisites to evaluate for
any later Mission-3 preflight.

No production reset, Mission allocation/intake/planning or historical Mission
requalification is part of this finalization. The #148 results remain
`AUTONOMY_E2E_ACCEPTANCE = NIET_GEHAALD` and
`MISSION_EXECUTION_STATE = NIET_GESTART`.
75 changes: 73 additions & 2 deletions scripts/update_installed_forge.py
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,73 @@ def _validated_wheel(request: UpdateRequest) -> tuple[bytes, dict[str, str]]:
return wheel_bytes, manifest


def _validate_criterion_qualification(report: object, request: UpdateRequest) -> None:
"""Require the exact installed composition evidence added by release 2.7.25."""
expected = {
"partial": ("COMPLETED", 2), "single": ("COMPLETED", 1),
"misleading": ("COMPLETED", 2), "invalid": ("BLOCKED", 1),
"missing": ("BLOCKED", 1), "no-progress": ("BLOCKED", 1),
"limit": ("BLOCKED", 1), "regression": ("BLOCKED", 2),
}
row_keys = {"scenario", "status", "waiting_reason", "criteria", "actions", "assessments",
"planner_invocations", "submissions", "original_observations_preserved",
"same_mission_and_approval", "separate_process_reopen"}
if (
not isinstance(report, Mapping)
or set(report) != {"qualification", "artifact", "scenarios", "limitations"}
or report.get("qualification") != "INSTALLED_COMPOSITION_WITH_EXTERNAL_FIXTURES"
or report.get("artifact") != {
"version": request.version,
"wheel_sha256": request.wheel_sha256.removeprefix("sha256:"),
}
or not isinstance(report.get("scenarios"), list)
or len(report["scenarios"]) != len(expected)
or not isinstance(report.get("limitations"), list)
or not report["limitations"]
or any(not isinstance(item, str) or not item for item in report["limitations"])
):
raise InstalledForgeUpdateError("installed criterion qualification is noncanonical")
seen = set()
for row in report["scenarios"]:
if (not isinstance(row, Mapping) or set(row) != row_keys
or not isinstance(row.get("scenario"), str)):
raise InstalledForgeUpdateError("installed criterion scenario is noncanonical")
name = row["scenario"]
if name not in expected or name in seen:
raise InstalledForgeUpdateError("installed criterion scenarios are missing or duplicated")
seen.add(name)
status, count = expected[name]
expected_proven = ({"SYNTHETIC-K1", "SYNTHETIC-K2"} if status == "COMPLETED" else
{"SYNTHETIC-K1"} if name == "limit" else
{"SYNTHETIC-K2"} if name == "regression" else set())
expected_reason = (None if status == "COMPLETED" else
"MISSION_ACTION_LIMIT_REACHED" if name in {"limit", "regression"} else
"MISSION_NO_PROGRESS_LIMIT_REACHED")
criteria = row.get("criteria")
if (
row.get("status") != status
or any(type(row.get(key)) is not int or row[key] != count
for key in ("actions", "assessments", "planner_invocations", "submissions"))
or any(row.get(key) is not True for key in (
"original_observations_preserved", "same_mission_and_approval", "separate_process_reopen",
))
or not isinstance(criteria, list) or len(criteria) != 2
or any(not isinstance(item, Mapping) or set(item) != {"criterion", "status", "reason"}
for item in criteria)
or any(not isinstance(item.get("criterion"), str)
or not isinstance(item.get("status"), str) for item in criteria)
or {item.get("criterion") for item in criteria} != {"SYNTHETIC-K1", "SYNTHETIC-K2"}
or any(item.get("status") not in {"PROVEN", "UNSATISFIED"} for item in criteria)
or {item["criterion"] for item in criteria if item["status"] == "PROVEN"} != expected_proven
or row.get("waiting_reason") != expected_reason
or any(item.get("reason") != (
"ALL_APPROVED_REQUIREMENTS_PROVEN" if item["status"] == "PROVEN"
else "REQUIRED_OBSERVATIONS_UNPROVEN"
) for item in criteria)
):
raise InstalledForgeUpdateError("installed criterion outcome does not qualify the release")


def _normal_release_evidence(
request: UpdateRequest, receipt: Mapping[str, Any], manifest: Mapping[str, str],
receipt_path: Path,
Expand All @@ -425,6 +492,7 @@ def _normal_release_evidence(
f"dist/{sdist_name}": sdist_digest,
}
exact_observed = {expected_name: request.wheel_sha256, sdist_name: sdist_digest}
composition_keys = {"criterion_completion"} if request.version == "2.7.25" else set()
if (
(request.existing_version, request.version) not in NORMAL_RELEASE_TRANSITIONS
or set(receipt) != expected_top
Expand All @@ -441,12 +509,12 @@ def _normal_release_evidence(
or not isinstance(sdist_digest, str)
or re.fullmatch(r"sha256:[0-9a-f]{64}", sdist_digest) is None
or not isinstance(qualification, Mapping)
or set(qualification) != {"artifact_digests", "exact_main_sha", "qualification"}
or set(qualification) != {"artifact_digests", "exact_main_sha", "qualification"} | composition_keys
or qualification.get("exact_main_sha") != request.product_source
or qualification.get("qualification") != "forge-production-distribution"
or qualification.get("artifact_digests") != exact_qualified
or not isinstance(publication, Mapping)
or set(publication) != {"observed_artifact_digests", "readback", "registry"}
or set(publication) != {"observed_artifact_digests", "readback", "registry"} | composition_keys
or publication.get("observed_artifact_digests") != exact_observed
or publication.get("readback") != "PASS"
or publication.get("registry") != "pypi"
Expand All @@ -461,6 +529,9 @@ def _normal_release_evidence(
raise InstalledForgeUpdateError(
"normal release-complete publication, policy, or cleanup lineage is noncanonical"
)
if composition_keys:
_validate_criterion_qualification(qualification["criterion_completion"], request)
_validate_criterion_qualification(publication["criterion_completion"], request)
return {
"wheel": str(Path(request.wheel)),
"wheel_sha256": request.wheel_sha256,
Expand Down
Loading
Loading