@mc-and-his-agents/loom-installer 0.1.10 → 0.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/payload/manifest.json +42 -42
- package/payload/plugin/loom/skills/shared/scripts/loom_check.py +84 -0
- package/payload/plugin/loom/skills/shared/scripts/loom_flow.py +259 -0
- package/payload/skills/loom-adopt/.loom-runtime/shared/scripts/loom_check.py +84 -0
- package/payload/skills/loom-adopt/.loom-runtime/shared/scripts/loom_flow.py +259 -0
- package/payload/skills/loom-handoff/.loom-runtime/shared/scripts/loom_check.py +84 -0
- package/payload/skills/loom-handoff/.loom-runtime/shared/scripts/loom_flow.py +259 -0
- package/payload/skills/loom-init/.loom-runtime/shared/scripts/loom_check.py +84 -0
- package/payload/skills/loom-init/.loom-runtime/shared/scripts/loom_flow.py +259 -0
- package/payload/skills/loom-merge-ready/.loom-runtime/shared/scripts/loom_check.py +84 -0
- package/payload/skills/loom-merge-ready/.loom-runtime/shared/scripts/loom_flow.py +259 -0
- package/payload/skills/loom-pre-review/.loom-runtime/shared/scripts/loom_check.py +84 -0
- package/payload/skills/loom-pre-review/.loom-runtime/shared/scripts/loom_flow.py +259 -0
- package/payload/skills/loom-resume/.loom-runtime/shared/scripts/loom_check.py +84 -0
- package/payload/skills/loom-resume/.loom-runtime/shared/scripts/loom_flow.py +259 -0
- package/payload/skills/loom-retire/.loom-runtime/shared/scripts/loom_check.py +84 -0
- package/payload/skills/loom-retire/.loom-runtime/shared/scripts/loom_flow.py +259 -0
- package/payload/skills/loom-review/.loom-runtime/shared/scripts/loom_check.py +84 -0
- package/payload/skills/loom-review/.loom-runtime/shared/scripts/loom_flow.py +259 -0
- package/payload/skills/loom-spec-review/.loom-runtime/shared/scripts/loom_check.py +84 -0
- package/payload/skills/loom-spec-review/.loom-runtime/shared/scripts/loom_flow.py +259 -0
package/package.json
CHANGED
package/payload/manifest.json
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"schema_version": "loom-installer-payload/v1",
|
|
3
3
|
"loom_version": "0.4.0",
|
|
4
4
|
"source_repository": "https://github.com/MC-and-his-Agents/Loom",
|
|
5
|
-
"source_commit": "
|
|
5
|
+
"source_commit": "4f6a4074d02557304018e9f063425f974d6a08cf",
|
|
6
6
|
"source_ref": "main",
|
|
7
|
-
"built_at": "2026-04-
|
|
7
|
+
"built_at": "2026-04-25T11:49:46+08:00",
|
|
8
8
|
"runtime": {
|
|
9
9
|
"python_minimum": "3.10",
|
|
10
10
|
"python_recommended": "3.11+"
|
|
@@ -628,13 +628,13 @@
|
|
|
628
628
|
},
|
|
629
629
|
{
|
|
630
630
|
"path": "plugin/loom/skills/shared/scripts/loom_check.py",
|
|
631
|
-
"bytes":
|
|
632
|
-
"sha256": "
|
|
631
|
+
"bytes": 253737,
|
|
632
|
+
"sha256": "9ada27e8f88d01940e7f70112301f1c6c78ffa362f5159abba2a44ae445266ac"
|
|
633
633
|
},
|
|
634
634
|
{
|
|
635
635
|
"path": "plugin/loom/skills/shared/scripts/loom_flow.py",
|
|
636
|
-
"bytes":
|
|
637
|
-
"sha256": "
|
|
636
|
+
"bytes": 259768,
|
|
637
|
+
"sha256": "f11062993fe565160cdc2910e981e9a601d0fcafcbe16dd0072d63acf39d67b0"
|
|
638
638
|
},
|
|
639
639
|
{
|
|
640
640
|
"path": "plugin/loom/skills/shared/scripts/loom_init.py",
|
|
@@ -1213,13 +1213,13 @@
|
|
|
1213
1213
|
},
|
|
1214
1214
|
{
|
|
1215
1215
|
"path": "skills/loom-adopt/.loom-runtime/shared/scripts/loom_check.py",
|
|
1216
|
-
"bytes":
|
|
1217
|
-
"sha256": "
|
|
1216
|
+
"bytes": 253737,
|
|
1217
|
+
"sha256": "9ada27e8f88d01940e7f70112301f1c6c78ffa362f5159abba2a44ae445266ac"
|
|
1218
1218
|
},
|
|
1219
1219
|
{
|
|
1220
1220
|
"path": "skills/loom-adopt/.loom-runtime/shared/scripts/loom_flow.py",
|
|
1221
|
-
"bytes":
|
|
1222
|
-
"sha256": "
|
|
1221
|
+
"bytes": 259768,
|
|
1222
|
+
"sha256": "f11062993fe565160cdc2910e981e9a601d0fcafcbe16dd0072d63acf39d67b0"
|
|
1223
1223
|
},
|
|
1224
1224
|
{
|
|
1225
1225
|
"path": "skills/loom-adopt/.loom-runtime/shared/scripts/loom_init.py",
|
|
@@ -1828,13 +1828,13 @@
|
|
|
1828
1828
|
},
|
|
1829
1829
|
{
|
|
1830
1830
|
"path": "skills/loom-handoff/.loom-runtime/shared/scripts/loom_check.py",
|
|
1831
|
-
"bytes":
|
|
1832
|
-
"sha256": "
|
|
1831
|
+
"bytes": 253737,
|
|
1832
|
+
"sha256": "9ada27e8f88d01940e7f70112301f1c6c78ffa362f5159abba2a44ae445266ac"
|
|
1833
1833
|
},
|
|
1834
1834
|
{
|
|
1835
1835
|
"path": "skills/loom-handoff/.loom-runtime/shared/scripts/loom_flow.py",
|
|
1836
|
-
"bytes":
|
|
1837
|
-
"sha256": "
|
|
1836
|
+
"bytes": 259768,
|
|
1837
|
+
"sha256": "f11062993fe565160cdc2910e981e9a601d0fcafcbe16dd0072d63acf39d67b0"
|
|
1838
1838
|
},
|
|
1839
1839
|
{
|
|
1840
1840
|
"path": "skills/loom-handoff/.loom-runtime/shared/scripts/loom_init.py",
|
|
@@ -2443,13 +2443,13 @@
|
|
|
2443
2443
|
},
|
|
2444
2444
|
{
|
|
2445
2445
|
"path": "skills/loom-init/.loom-runtime/shared/scripts/loom_check.py",
|
|
2446
|
-
"bytes":
|
|
2447
|
-
"sha256": "
|
|
2446
|
+
"bytes": 253737,
|
|
2447
|
+
"sha256": "9ada27e8f88d01940e7f70112301f1c6c78ffa362f5159abba2a44ae445266ac"
|
|
2448
2448
|
},
|
|
2449
2449
|
{
|
|
2450
2450
|
"path": "skills/loom-init/.loom-runtime/shared/scripts/loom_flow.py",
|
|
2451
|
-
"bytes":
|
|
2452
|
-
"sha256": "
|
|
2451
|
+
"bytes": 259768,
|
|
2452
|
+
"sha256": "f11062993fe565160cdc2910e981e9a601d0fcafcbe16dd0072d63acf39d67b0"
|
|
2453
2453
|
},
|
|
2454
2454
|
{
|
|
2455
2455
|
"path": "skills/loom-init/.loom-runtime/shared/scripts/loom_init.py",
|
|
@@ -3063,13 +3063,13 @@
|
|
|
3063
3063
|
},
|
|
3064
3064
|
{
|
|
3065
3065
|
"path": "skills/loom-merge-ready/.loom-runtime/shared/scripts/loom_check.py",
|
|
3066
|
-
"bytes":
|
|
3067
|
-
"sha256": "
|
|
3066
|
+
"bytes": 253737,
|
|
3067
|
+
"sha256": "9ada27e8f88d01940e7f70112301f1c6c78ffa362f5159abba2a44ae445266ac"
|
|
3068
3068
|
},
|
|
3069
3069
|
{
|
|
3070
3070
|
"path": "skills/loom-merge-ready/.loom-runtime/shared/scripts/loom_flow.py",
|
|
3071
|
-
"bytes":
|
|
3072
|
-
"sha256": "
|
|
3071
|
+
"bytes": 259768,
|
|
3072
|
+
"sha256": "f11062993fe565160cdc2910e981e9a601d0fcafcbe16dd0072d63acf39d67b0"
|
|
3073
3073
|
},
|
|
3074
3074
|
{
|
|
3075
3075
|
"path": "skills/loom-merge-ready/.loom-runtime/shared/scripts/loom_init.py",
|
|
@@ -3678,13 +3678,13 @@
|
|
|
3678
3678
|
},
|
|
3679
3679
|
{
|
|
3680
3680
|
"path": "skills/loom-pre-review/.loom-runtime/shared/scripts/loom_check.py",
|
|
3681
|
-
"bytes":
|
|
3682
|
-
"sha256": "
|
|
3681
|
+
"bytes": 253737,
|
|
3682
|
+
"sha256": "9ada27e8f88d01940e7f70112301f1c6c78ffa362f5159abba2a44ae445266ac"
|
|
3683
3683
|
},
|
|
3684
3684
|
{
|
|
3685
3685
|
"path": "skills/loom-pre-review/.loom-runtime/shared/scripts/loom_flow.py",
|
|
3686
|
-
"bytes":
|
|
3687
|
-
"sha256": "
|
|
3686
|
+
"bytes": 259768,
|
|
3687
|
+
"sha256": "f11062993fe565160cdc2910e981e9a601d0fcafcbe16dd0072d63acf39d67b0"
|
|
3688
3688
|
},
|
|
3689
3689
|
{
|
|
3690
3690
|
"path": "skills/loom-pre-review/.loom-runtime/shared/scripts/loom_init.py",
|
|
@@ -4293,13 +4293,13 @@
|
|
|
4293
4293
|
},
|
|
4294
4294
|
{
|
|
4295
4295
|
"path": "skills/loom-resume/.loom-runtime/shared/scripts/loom_check.py",
|
|
4296
|
-
"bytes":
|
|
4297
|
-
"sha256": "
|
|
4296
|
+
"bytes": 253737,
|
|
4297
|
+
"sha256": "9ada27e8f88d01940e7f70112301f1c6c78ffa362f5159abba2a44ae445266ac"
|
|
4298
4298
|
},
|
|
4299
4299
|
{
|
|
4300
4300
|
"path": "skills/loom-resume/.loom-runtime/shared/scripts/loom_flow.py",
|
|
4301
|
-
"bytes":
|
|
4302
|
-
"sha256": "
|
|
4301
|
+
"bytes": 259768,
|
|
4302
|
+
"sha256": "f11062993fe565160cdc2910e981e9a601d0fcafcbe16dd0072d63acf39d67b0"
|
|
4303
4303
|
},
|
|
4304
4304
|
{
|
|
4305
4305
|
"path": "skills/loom-resume/.loom-runtime/shared/scripts/loom_init.py",
|
|
@@ -4908,13 +4908,13 @@
|
|
|
4908
4908
|
},
|
|
4909
4909
|
{
|
|
4910
4910
|
"path": "skills/loom-retire/.loom-runtime/shared/scripts/loom_check.py",
|
|
4911
|
-
"bytes":
|
|
4912
|
-
"sha256": "
|
|
4911
|
+
"bytes": 253737,
|
|
4912
|
+
"sha256": "9ada27e8f88d01940e7f70112301f1c6c78ffa362f5159abba2a44ae445266ac"
|
|
4913
4913
|
},
|
|
4914
4914
|
{
|
|
4915
4915
|
"path": "skills/loom-retire/.loom-runtime/shared/scripts/loom_flow.py",
|
|
4916
|
-
"bytes":
|
|
4917
|
-
"sha256": "
|
|
4916
|
+
"bytes": 259768,
|
|
4917
|
+
"sha256": "f11062993fe565160cdc2910e981e9a601d0fcafcbe16dd0072d63acf39d67b0"
|
|
4918
4918
|
},
|
|
4919
4919
|
{
|
|
4920
4920
|
"path": "skills/loom-retire/.loom-runtime/shared/scripts/loom_init.py",
|
|
@@ -5523,13 +5523,13 @@
|
|
|
5523
5523
|
},
|
|
5524
5524
|
{
|
|
5525
5525
|
"path": "skills/loom-review/.loom-runtime/shared/scripts/loom_check.py",
|
|
5526
|
-
"bytes":
|
|
5527
|
-
"sha256": "
|
|
5526
|
+
"bytes": 253737,
|
|
5527
|
+
"sha256": "9ada27e8f88d01940e7f70112301f1c6c78ffa362f5159abba2a44ae445266ac"
|
|
5528
5528
|
},
|
|
5529
5529
|
{
|
|
5530
5530
|
"path": "skills/loom-review/.loom-runtime/shared/scripts/loom_flow.py",
|
|
5531
|
-
"bytes":
|
|
5532
|
-
"sha256": "
|
|
5531
|
+
"bytes": 259768,
|
|
5532
|
+
"sha256": "f11062993fe565160cdc2910e981e9a601d0fcafcbe16dd0072d63acf39d67b0"
|
|
5533
5533
|
},
|
|
5534
5534
|
{
|
|
5535
5535
|
"path": "skills/loom-review/.loom-runtime/shared/scripts/loom_init.py",
|
|
@@ -6138,13 +6138,13 @@
|
|
|
6138
6138
|
},
|
|
6139
6139
|
{
|
|
6140
6140
|
"path": "skills/loom-spec-review/.loom-runtime/shared/scripts/loom_check.py",
|
|
6141
|
-
"bytes":
|
|
6142
|
-
"sha256": "
|
|
6141
|
+
"bytes": 253737,
|
|
6142
|
+
"sha256": "9ada27e8f88d01940e7f70112301f1c6c78ffa362f5159abba2a44ae445266ac"
|
|
6143
6143
|
},
|
|
6144
6144
|
{
|
|
6145
6145
|
"path": "skills/loom-spec-review/.loom-runtime/shared/scripts/loom_flow.py",
|
|
6146
|
-
"bytes":
|
|
6147
|
-
"sha256": "
|
|
6146
|
+
"bytes": 259768,
|
|
6147
|
+
"sha256": "f11062993fe565160cdc2910e981e9a601d0fcafcbe16dd0072d63acf39d67b0"
|
|
6148
6148
|
},
|
|
6149
6149
|
{
|
|
6150
6150
|
"path": "skills/loom-spec-review/.loom-runtime/shared/scripts/loom_init.py",
|
|
@@ -92,6 +92,7 @@ CORE_DOCS = (
|
|
|
92
92
|
"docs/methodology/templates/pull-request.md",
|
|
93
93
|
"docs/evidence/extraction-ledger.md",
|
|
94
94
|
"docs/evidence/landing-map.md",
|
|
95
|
+
"docs/evidence/validations/validation-loom-core-runtime-parity.md",
|
|
95
96
|
"docs/evidence/validations/validation-syvert-strong-governance-parity.md",
|
|
96
97
|
"docs/adoption/rationale.md",
|
|
97
98
|
"docs/adoption/routing-and-checkpoints.md",
|
|
@@ -1162,6 +1163,68 @@ def require_closeout_reconciliation_contract(
|
|
|
1162
1163
|
failures.append(Failure(category, f"{context} must point blocked reconciliation drift to `manual-reconciliation`"))
|
|
1163
1164
|
|
|
1164
1165
|
|
|
1166
|
+
def require_runtime_parity_payload(
|
|
1167
|
+
failures: list[Failure],
|
|
1168
|
+
*,
|
|
1169
|
+
category: str,
|
|
1170
|
+
context: str,
|
|
1171
|
+
payload: object,
|
|
1172
|
+
) -> None:
|
|
1173
|
+
if not isinstance(payload, dict):
|
|
1174
|
+
failures.append(Failure(category, f"{context} must be an object"))
|
|
1175
|
+
return
|
|
1176
|
+
if payload.get("command") != "runtime-parity":
|
|
1177
|
+
failures.append(Failure(category, f"{context} must report `command: runtime-parity`"))
|
|
1178
|
+
if payload.get("operation") != "validate":
|
|
1179
|
+
failures.append(Failure(category, f"{context} must report `operation: validate`"))
|
|
1180
|
+
if payload.get("schema_version") != "loom-runtime-parity/v1":
|
|
1181
|
+
failures.append(Failure(category, f"{context} schema_version must be `loom-runtime-parity/v1`"))
|
|
1182
|
+
if payload.get("result") not in {"pass", "block"}:
|
|
1183
|
+
failures.append(Failure(category, f"{context} result must be `pass` or `block`"))
|
|
1184
|
+
if not isinstance(payload.get("summary"), str) or not payload.get("summary"):
|
|
1185
|
+
failures.append(Failure(category, f"{context} must include a non-empty `summary`"))
|
|
1186
|
+
if not isinstance(payload.get("missing_inputs"), list):
|
|
1187
|
+
failures.append(Failure(category, f"{context} must include `missing_inputs`"))
|
|
1188
|
+
if payload.get("fallback_to") not in {None, "admission", "merge", "reconciliation-sync", "manual-runtime-reconciliation", "rebootstrap-runtime", "refresh-install", "loom-init"}:
|
|
1189
|
+
failures.append(Failure(category, f"{context} fallback_to must stay within the stable runtime parity contract"))
|
|
1190
|
+
require_runtime_state_payload(
|
|
1191
|
+
failures,
|
|
1192
|
+
category=category,
|
|
1193
|
+
context=context,
|
|
1194
|
+
payload=payload.get("runtime_state"),
|
|
1195
|
+
expected_scene="repo-local-demo",
|
|
1196
|
+
expected_carrier="repo-local-wrapper",
|
|
1197
|
+
allowed_results={"pass"},
|
|
1198
|
+
)
|
|
1199
|
+
checks = payload.get("checks")
|
|
1200
|
+
if not isinstance(checks, list):
|
|
1201
|
+
failures.append(Failure(category, f"{context} must include `checks` as a list"))
|
|
1202
|
+
return
|
|
1203
|
+
required_checks = {
|
|
1204
|
+
"work_item",
|
|
1205
|
+
"status_control_plane",
|
|
1206
|
+
"gate_chain",
|
|
1207
|
+
"controlled_merge_contract",
|
|
1208
|
+
"closeout_reconciliation",
|
|
1209
|
+
"shadow_parity_boundary",
|
|
1210
|
+
}
|
|
1211
|
+
check_names = {check.get("name") for check in checks if isinstance(check, dict)}
|
|
1212
|
+
if not required_checks.issubset(check_names):
|
|
1213
|
+
failures.append(Failure(category, f"{context} must cover the stable runtime parity check set"))
|
|
1214
|
+
for check in checks:
|
|
1215
|
+
if not isinstance(check, dict):
|
|
1216
|
+
failures.append(Failure(category, f"{context} checks must be JSON objects"))
|
|
1217
|
+
continue
|
|
1218
|
+
if check.get("result") not in {"pass", "block"}:
|
|
1219
|
+
failures.append(Failure(category, f"{context} check `{check.get('name')}` result must be `pass` or `block`"))
|
|
1220
|
+
if not isinstance(check.get("summary"), str) or not check.get("summary"):
|
|
1221
|
+
failures.append(Failure(category, f"{context} check `{check.get('name')}` must include non-empty `summary`"))
|
|
1222
|
+
if not isinstance(check.get("missing_inputs"), list):
|
|
1223
|
+
failures.append(Failure(category, f"{context} check `{check.get('name')}` must include `missing_inputs`"))
|
|
1224
|
+
if not isinstance(check.get("evidence"), dict):
|
|
1225
|
+
failures.append(Failure(category, f"{context} check `{check.get('name')}` must include `evidence`"))
|
|
1226
|
+
|
|
1227
|
+
|
|
1165
1228
|
def require_review_record_contract(
|
|
1166
1229
|
failures: list[Failure],
|
|
1167
1230
|
*,
|
|
@@ -2124,6 +2187,20 @@ def check_daily_execution_cli(root: Path) -> list[Failure]:
|
|
|
2124
2187
|
["python3", "tools/loom_status.py", "--target", "examples/new-project", "--item", "INIT-0001"],
|
|
2125
2188
|
{"pass", "block"},
|
|
2126
2189
|
),
|
|
2190
|
+
(
|
|
2191
|
+
"runtime-parity",
|
|
2192
|
+
[
|
|
2193
|
+
"python3",
|
|
2194
|
+
"tools/loom_flow.py",
|
|
2195
|
+
"runtime-parity",
|
|
2196
|
+
"validate",
|
|
2197
|
+
"--target",
|
|
2198
|
+
"examples/new-project",
|
|
2199
|
+
"--item",
|
|
2200
|
+
"INIT-0001",
|
|
2201
|
+
],
|
|
2202
|
+
{"pass"},
|
|
2203
|
+
),
|
|
2127
2204
|
(
|
|
2128
2205
|
"governance-profile-status",
|
|
2129
2206
|
["python3", "tools/loom_flow.py", "governance-profile", "status", "--target", "examples/new-project"],
|
|
@@ -2361,6 +2438,13 @@ def check_daily_execution_cli(root: Path) -> list[Failure]:
|
|
|
2361
2438
|
context="`loom_status`",
|
|
2362
2439
|
payload=payload,
|
|
2363
2440
|
)
|
|
2441
|
+
if label == "runtime-parity":
|
|
2442
|
+
require_runtime_parity_payload(
|
|
2443
|
+
failures,
|
|
2444
|
+
category="daily-execution-cli",
|
|
2445
|
+
context="`runtime-parity validate`",
|
|
2446
|
+
payload=payload,
|
|
2447
|
+
)
|
|
2364
2448
|
if label in {"governance-profile-status", "governance-profile-upgrade-plan"}:
|
|
2365
2449
|
if payload.get("command") != "governance-profile":
|
|
2366
2450
|
failures.append(Failure("daily-execution-cli", f"`{label}` must report `command: governance-profile`"))
|
|
@@ -277,6 +277,19 @@ def parse_args(argv: list[str]) -> argparse.Namespace:
|
|
|
277
277
|
help="Init-result path relative to the target root",
|
|
278
278
|
)
|
|
279
279
|
|
|
280
|
+
runtime_parity = subparsers.add_parser(
|
|
281
|
+
"runtime-parity",
|
|
282
|
+
help="Validate Loom core strong-governance runtime parity without host-specific orchestration",
|
|
283
|
+
)
|
|
284
|
+
runtime_parity.add_argument("operation", choices=("validate",))
|
|
285
|
+
runtime_parity.add_argument("--target", required=True, help="Target repository root")
|
|
286
|
+
runtime_parity.add_argument("--item", help="Expected current item id")
|
|
287
|
+
runtime_parity.add_argument(
|
|
288
|
+
"--output",
|
|
289
|
+
default=".loom/bootstrap/init-result.json",
|
|
290
|
+
help="Init-result path relative to the target root",
|
|
291
|
+
)
|
|
292
|
+
|
|
280
293
|
governance_profile = subparsers.add_parser(
|
|
281
294
|
"governance-profile",
|
|
282
295
|
help="Read Loom governance maturity and upgrade requirements",
|
|
@@ -4162,6 +4175,239 @@ def closeout_reconciliation_result(
|
|
|
4162
4175
|
return None, None
|
|
4163
4176
|
|
|
4164
4177
|
|
|
4178
|
+
def runtime_parity_check(
|
|
4179
|
+
name: str,
|
|
4180
|
+
*,
|
|
4181
|
+
result: str,
|
|
4182
|
+
summary: str,
|
|
4183
|
+
evidence: dict[str, Any] | None = None,
|
|
4184
|
+
missing_inputs: list[str] | None = None,
|
|
4185
|
+
fallback_to: str | None = None,
|
|
4186
|
+
) -> dict[str, Any]:
|
|
4187
|
+
return {
|
|
4188
|
+
"name": name,
|
|
4189
|
+
"result": result,
|
|
4190
|
+
"summary": summary,
|
|
4191
|
+
"evidence": evidence or {},
|
|
4192
|
+
"missing_inputs": missing_inputs or [],
|
|
4193
|
+
"fallback_to": fallback_to,
|
|
4194
|
+
}
|
|
4195
|
+
|
|
4196
|
+
|
|
4197
|
+
def runtime_parity_payload(
|
|
4198
|
+
*,
|
|
4199
|
+
target_root: Path,
|
|
4200
|
+
output_relative: str,
|
|
4201
|
+
expected_item: str | None,
|
|
4202
|
+
) -> dict[str, Any]:
|
|
4203
|
+
runtime_state = runtime_state_payload(target_root)
|
|
4204
|
+
checks: list[dict[str, Any]] = []
|
|
4205
|
+
if runtime_state["result"] != "pass":
|
|
4206
|
+
checks.append(
|
|
4207
|
+
runtime_parity_check(
|
|
4208
|
+
"runtime_state",
|
|
4209
|
+
result="block",
|
|
4210
|
+
summary="runtime carrier is not consistent enough to prove runtime parity.",
|
|
4211
|
+
missing_inputs=list(runtime_state.get("missing_inputs", [])),
|
|
4212
|
+
fallback_to=runtime_state.get("fallback_to"),
|
|
4213
|
+
evidence={"runtime_state": runtime_state},
|
|
4214
|
+
)
|
|
4215
|
+
)
|
|
4216
|
+
return {
|
|
4217
|
+
"command": "runtime-parity",
|
|
4218
|
+
"operation": "validate",
|
|
4219
|
+
"schema_version": "loom-runtime-parity/v1",
|
|
4220
|
+
"result": "block",
|
|
4221
|
+
"summary": "Loom core runtime parity validation is blocked by runtime-state drift.",
|
|
4222
|
+
"missing_inputs": list(runtime_state.get("missing_inputs", [])),
|
|
4223
|
+
"fallback_to": runtime_state.get("fallback_to"),
|
|
4224
|
+
"runtime_state": runtime_state,
|
|
4225
|
+
"checks": checks,
|
|
4226
|
+
}
|
|
4227
|
+
|
|
4228
|
+
context, context_errors = load_context(target_root, output_relative, expected_item)
|
|
4229
|
+
governance_surface = build_governance_surface(target_root)
|
|
4230
|
+
control_plane = governance_surface.get("governance_control_plane")
|
|
4231
|
+
carrier_summary = governance_surface.get("carrier_summary")
|
|
4232
|
+
|
|
4233
|
+
if context_errors:
|
|
4234
|
+
checks.append(
|
|
4235
|
+
runtime_parity_check(
|
|
4236
|
+
"work_item",
|
|
4237
|
+
result="block",
|
|
4238
|
+
summary="runtime parity could not read the Work Item fact chain.",
|
|
4239
|
+
missing_inputs=[f"fact-chain: {message}" for message in context_errors],
|
|
4240
|
+
fallback_to="admission",
|
|
4241
|
+
)
|
|
4242
|
+
)
|
|
4243
|
+
else:
|
|
4244
|
+
checks.append(
|
|
4245
|
+
runtime_parity_check(
|
|
4246
|
+
"work_item",
|
|
4247
|
+
result="pass",
|
|
4248
|
+
summary="Work Item is readable as the single execution entry.",
|
|
4249
|
+
evidence={
|
|
4250
|
+
"item_id": context["item_id"],
|
|
4251
|
+
"work_item": context["report"]["fact_chain"]["entry_points"]["work_item"],
|
|
4252
|
+
"recovery_entry": context["report"]["fact_chain"]["entry_points"]["recovery_entry"],
|
|
4253
|
+
"status_surface": context["report"]["fact_chain"]["entry_points"]["status_surface"],
|
|
4254
|
+
},
|
|
4255
|
+
)
|
|
4256
|
+
)
|
|
4257
|
+
|
|
4258
|
+
if isinstance(control_plane, dict) and control_plane.get("schema_version") == "loom-governance-control/v1":
|
|
4259
|
+
checks.append(
|
|
4260
|
+
runtime_parity_check(
|
|
4261
|
+
"status_control_plane",
|
|
4262
|
+
result="pass",
|
|
4263
|
+
summary="governance control plane is available as a machine-readable runtime surface.",
|
|
4264
|
+
evidence={
|
|
4265
|
+
"schema_version": control_plane.get("schema_version"),
|
|
4266
|
+
"taxonomy": sorted((control_plane.get("taxonomy") or {}).keys())
|
|
4267
|
+
if isinstance(control_plane.get("taxonomy"), dict)
|
|
4268
|
+
else [],
|
|
4269
|
+
"maturity": (control_plane.get("maturity") or {}).get("current")
|
|
4270
|
+
if isinstance(control_plane.get("maturity"), dict)
|
|
4271
|
+
else None,
|
|
4272
|
+
},
|
|
4273
|
+
)
|
|
4274
|
+
)
|
|
4275
|
+
else:
|
|
4276
|
+
checks.append(
|
|
4277
|
+
runtime_parity_check(
|
|
4278
|
+
"status_control_plane",
|
|
4279
|
+
result="block",
|
|
4280
|
+
summary="governance control plane is missing or unreadable.",
|
|
4281
|
+
missing_inputs=["governance_control_plane"],
|
|
4282
|
+
fallback_to="admission",
|
|
4283
|
+
)
|
|
4284
|
+
)
|
|
4285
|
+
|
|
4286
|
+
expected_gate_order = [
|
|
4287
|
+
"work_item_admission",
|
|
4288
|
+
"spec_gate",
|
|
4289
|
+
"build_gate",
|
|
4290
|
+
"review_gate",
|
|
4291
|
+
"merge_gate",
|
|
4292
|
+
"github_controlled_merge",
|
|
4293
|
+
"closeout",
|
|
4294
|
+
]
|
|
4295
|
+
gate_chain = control_plane.get("gate_chain") if isinstance(control_plane, dict) else None
|
|
4296
|
+
actual_gate_order = [entry.get("id") for entry in gate_chain if isinstance(entry, dict)] if isinstance(gate_chain, (list, tuple)) else []
|
|
4297
|
+
checks.append(
|
|
4298
|
+
runtime_parity_check(
|
|
4299
|
+
"gate_chain",
|
|
4300
|
+
result="pass" if actual_gate_order == expected_gate_order else "block",
|
|
4301
|
+
summary=(
|
|
4302
|
+
"strong governance gate chain is available in runtime order."
|
|
4303
|
+
if actual_gate_order == expected_gate_order
|
|
4304
|
+
else "strong governance gate chain does not match the runtime parity contract."
|
|
4305
|
+
),
|
|
4306
|
+
evidence={"gate_order": actual_gate_order, "expected_gate_order": expected_gate_order},
|
|
4307
|
+
missing_inputs=[] if actual_gate_order == expected_gate_order else ["governance_control_plane.gate_chain"],
|
|
4308
|
+
fallback_to=None if actual_gate_order == expected_gate_order else "admission",
|
|
4309
|
+
)
|
|
4310
|
+
)
|
|
4311
|
+
|
|
4312
|
+
host_binding = control_plane.get("host_binding") if isinstance(control_plane, dict) else None
|
|
4313
|
+
required_objects = host_binding.get("required_objects") if isinstance(host_binding, dict) else None
|
|
4314
|
+
controlled_merge_ready = (
|
|
4315
|
+
isinstance(host_binding, dict)
|
|
4316
|
+
and isinstance(required_objects, dict)
|
|
4317
|
+
and {"implementation_pr", "merge_commit", "closeout"}.issubset(required_objects.keys())
|
|
4318
|
+
)
|
|
4319
|
+
checks.append(
|
|
4320
|
+
runtime_parity_check(
|
|
4321
|
+
"controlled_merge_contract",
|
|
4322
|
+
result="pass" if controlled_merge_ready else "block",
|
|
4323
|
+
summary=(
|
|
4324
|
+
"controlled merge contract exposes PR, merge commit, and closeout host-owned bindings."
|
|
4325
|
+
if controlled_merge_ready
|
|
4326
|
+
else "controlled merge contract is missing required host-owned bindings."
|
|
4327
|
+
),
|
|
4328
|
+
evidence={
|
|
4329
|
+
"host_binding_result": host_binding.get("result") if isinstance(host_binding, dict) else None,
|
|
4330
|
+
"required_objects": sorted(required_objects.keys()) if isinstance(required_objects, dict) else [],
|
|
4331
|
+
},
|
|
4332
|
+
missing_inputs=[] if controlled_merge_ready else ["governance_control_plane.host_binding"],
|
|
4333
|
+
fallback_to=None if controlled_merge_ready else "merge",
|
|
4334
|
+
)
|
|
4335
|
+
)
|
|
4336
|
+
|
|
4337
|
+
closeout_gate = next((entry for entry in gate_chain or [] if isinstance(entry, dict) and entry.get("id") == "closeout"), {})
|
|
4338
|
+
closeout_requires = closeout_gate.get("requires") if isinstance(closeout_gate, dict) else None
|
|
4339
|
+
closeout_ready = isinstance(closeout_requires, (list, tuple)) and "reconciliation_audit" in closeout_requires
|
|
4340
|
+
checks.append(
|
|
4341
|
+
runtime_parity_check(
|
|
4342
|
+
"closeout_reconciliation",
|
|
4343
|
+
result="pass" if closeout_ready else "block",
|
|
4344
|
+
summary=(
|
|
4345
|
+
"closeout gate consumes reconciliation audit as a runtime prerequisite."
|
|
4346
|
+
if closeout_ready
|
|
4347
|
+
else "closeout gate does not expose reconciliation audit as a runtime prerequisite."
|
|
4348
|
+
),
|
|
4349
|
+
evidence={
|
|
4350
|
+
"closeout_requires": closeout_requires if isinstance(closeout_requires, (list, tuple)) else [],
|
|
4351
|
+
"repo_interop_availability": (governance_surface.get("repo_interop") or {}).get("availability")
|
|
4352
|
+
if isinstance(governance_surface.get("repo_interop"), dict)
|
|
4353
|
+
else None,
|
|
4354
|
+
},
|
|
4355
|
+
missing_inputs=[] if closeout_ready else ["governance_control_plane.gate_chain.closeout"],
|
|
4356
|
+
fallback_to=None if closeout_ready else "reconciliation-sync",
|
|
4357
|
+
)
|
|
4358
|
+
)
|
|
4359
|
+
|
|
4360
|
+
checks.append(
|
|
4361
|
+
runtime_parity_check(
|
|
4362
|
+
"shadow_parity_boundary",
|
|
4363
|
+
result="pass",
|
|
4364
|
+
summary="shadow parity remains validation-only in Loom core runtime parity.",
|
|
4365
|
+
evidence={
|
|
4366
|
+
"default_result_contract": ["pass", "warn"],
|
|
4367
|
+
"blocking_default": False,
|
|
4368
|
+
"surfaces": list(SHADOW_PARITY_SURFACES),
|
|
4369
|
+
},
|
|
4370
|
+
)
|
|
4371
|
+
)
|
|
4372
|
+
|
|
4373
|
+
if not isinstance(carrier_summary, dict):
|
|
4374
|
+
checks.append(
|
|
4375
|
+
runtime_parity_check(
|
|
4376
|
+
"carrier_summary",
|
|
4377
|
+
result="block",
|
|
4378
|
+
summary="carrier summary is missing from governance surface.",
|
|
4379
|
+
missing_inputs=["governance_surface.carrier_summary"],
|
|
4380
|
+
fallback_to="admission",
|
|
4381
|
+
)
|
|
4382
|
+
)
|
|
4383
|
+
|
|
4384
|
+
missing_inputs: list[str] = []
|
|
4385
|
+
fallback_to: str | None = None
|
|
4386
|
+
for check in checks:
|
|
4387
|
+
if check["result"] == "block":
|
|
4388
|
+
fallback_to = fallback_to or check.get("fallback_to")
|
|
4389
|
+
for message in check.get("missing_inputs", []):
|
|
4390
|
+
if message not in missing_inputs:
|
|
4391
|
+
missing_inputs.append(message)
|
|
4392
|
+
|
|
4393
|
+
result = "pass" if not missing_inputs else "block"
|
|
4394
|
+
return {
|
|
4395
|
+
"command": "runtime-parity",
|
|
4396
|
+
"operation": "validate",
|
|
4397
|
+
"schema_version": "loom-runtime-parity/v1",
|
|
4398
|
+
"result": result,
|
|
4399
|
+
"summary": (
|
|
4400
|
+
"Loom core runtime parity is machine-readable across Work Item, status, gates, controlled merge, closeout, and shadow boundary."
|
|
4401
|
+
if result == "pass"
|
|
4402
|
+
else "Loom core runtime parity validation found missing or unreadable runtime surfaces."
|
|
4403
|
+
),
|
|
4404
|
+
"missing_inputs": missing_inputs,
|
|
4405
|
+
"fallback_to": fallback_to,
|
|
4406
|
+
"runtime_state": runtime_state,
|
|
4407
|
+
"checks": checks,
|
|
4408
|
+
}
|
|
4409
|
+
|
|
4410
|
+
|
|
4165
4411
|
def closeout_payload(
|
|
4166
4412
|
*,
|
|
4167
4413
|
target_root: Path,
|
|
@@ -5898,6 +6144,17 @@ def handle_shadow_parity(args: argparse.Namespace) -> int:
|
|
|
5898
6144
|
)
|
|
5899
6145
|
|
|
5900
6146
|
|
|
6147
|
+
def handle_runtime_parity(args: argparse.Namespace) -> int:
|
|
6148
|
+
target_root = Path(args.target).expanduser().resolve()
|
|
6149
|
+
return emit(
|
|
6150
|
+
runtime_parity_payload(
|
|
6151
|
+
target_root=target_root,
|
|
6152
|
+
output_relative=args.output,
|
|
6153
|
+
expected_item=args.item,
|
|
6154
|
+
)
|
|
6155
|
+
)
|
|
6156
|
+
|
|
6157
|
+
|
|
5901
6158
|
def main(argv: list[str] | None = None) -> int:
|
|
5902
6159
|
args = parse_args(argv or sys.argv[1:])
|
|
5903
6160
|
if args.command == "fact-chain":
|
|
@@ -5922,6 +6179,8 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
5922
6179
|
return handle_reconciliation(args)
|
|
5923
6180
|
if args.command == "shadow-parity":
|
|
5924
6181
|
return handle_shadow_parity(args)
|
|
6182
|
+
if args.command == "runtime-parity":
|
|
6183
|
+
return handle_runtime_parity(args)
|
|
5925
6184
|
if args.command == "governance-profile":
|
|
5926
6185
|
return handle_governance_profile(args)
|
|
5927
6186
|
if args.command == "flow":
|