From 32371469b9a4dc7e02fa4cb8f13a0959a7762100 Mon Sep 17 00:00:00 2001 From: ci Date: Fri, 4 Sep 2026 15:19:29 -0400 Subject: [PATCH 1/8] Assemble inactive default profile --- README.md | 13 +++ RESTORE.md | 15 +++ ci/required-files.txt | 11 ++ .../v1/manifests/claude-code-producer.json | 1 + .../v1/manifests/codex-native-reviewer.json | 1 + .../v1/manifests/deterministic-verifier.json | 1 + .../v1/manifests/dormant-publisher.json | 1 + .../v1/manifests/github-actions-ci.json | 1 + .../default/v1/manifests/github-forge.json | 1 + .../v1/manifests/local-git-materializer.json | 1 + profiles/default/v1/profile.json | 1 + scripts/test/default-profile-assembly.test.sh | 105 ++++++++++++++++++ 12 files changed, 152 insertions(+) create mode 100644 profiles/default/v1/manifests/claude-code-producer.json create mode 100644 profiles/default/v1/manifests/codex-native-reviewer.json create mode 100644 profiles/default/v1/manifests/deterministic-verifier.json create mode 100644 profiles/default/v1/manifests/dormant-publisher.json create mode 100644 profiles/default/v1/manifests/github-actions-ci.json create mode 100644 profiles/default/v1/manifests/github-forge.json create mode 100644 profiles/default/v1/manifests/local-git-materializer.json create mode 100644 profiles/default/v1/profile.json create mode 100755 scripts/test/default-profile-assembly.test.sh diff --git a/README.md b/README.md index 5a7015f..b585467 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,19 @@ The private native snapshot helper is the exception recorded in `work/portable-profile-resolution/spec.md`. Remove it only when every supported runtime has an equivalent accepted descriptor-relative no-follow API. +## Inactive default profile assembly + +`profiles/default/v1/` binds the seven default adapter packages to exact Git +objects from one durable main commit. Protected roles keep distinct principals, +execution boundaries, and authority scopes; their decision records cite the exact +accepted `ROADMAP.md` content. The profile requests no adapter tools, and the CI, +identity, and dormant-publisher roles request no capability or permission. + +This is source data only. It is not selected, resolved, qualified, installed, or +activated, and it cannot invoke a model, use a credential, contact a provider, +publish, or touch a target. Run +`bash scripts/test/default-profile-assembly.test.sh` for the focused proof. + ## Inactive portable core v2 fake-forge contract `core/v2/` contains an inactive, repo-only contract for deterministic candidate diff --git a/RESTORE.md b/RESTORE.md index dce165d..6b04bbe 100644 --- a/RESTORE.md +++ b/RESTORE.md @@ -55,6 +55,21 @@ with the restored `scripts/core-contract.sh`. No compiled helper is installed or restored. A future activation must separately qualify and bind a production trusted parent; restoring these files does not select a live profile. +### Restore the inactive default profile assembly + +Restore the nine paths listed under “Inactive default profile assembly” in +[`ci/required-files.txt`](ci/required-files.txt) from one commit, then run: + +```sh +bash scripts/test/default-profile-assembly.test.sh +``` + +The proof validates the profile and seven manifests, their exact main package +objects, the accepted Roadmap decision record, role separation, and empty tool +grants. Restoring these records does not select, resolve, qualify, install, or +activate the profile and performs no model, credential, provider, publish, or +target operation. + --- ## 1. Recreate yshifu (the manager) diff --git a/ci/required-files.txt b/ci/required-files.txt index c7dac9b..fb86969 100644 --- a/ci/required-files.txt +++ b/ci/required-files.txt @@ -273,3 +273,14 @@ scripts/test/default-dormant-publisher-adapter.test.sh # Inactive deterministic verifier normalizer payload adapters/deterministic-verifier/v1/normalize.jq scripts/test/default-deterministic-verifier-adapter.test.sh + +# Inactive default profile assembly +profiles/default/v1/profile.json +profiles/default/v1/manifests/claude-code-producer.json +profiles/default/v1/manifests/codex-native-reviewer.json +profiles/default/v1/manifests/deterministic-verifier.json +profiles/default/v1/manifests/dormant-publisher.json +profiles/default/v1/manifests/github-actions-ci.json +profiles/default/v1/manifests/github-forge.json +profiles/default/v1/manifests/local-git-materializer.json +scripts/test/default-profile-assembly.test.sh diff --git a/profiles/default/v1/manifests/claude-code-producer.json b/profiles/default/v1/manifests/claude-code-producer.json new file mode 100644 index 0000000..e047f54 --- /dev/null +++ b/profiles/default/v1/manifests/claude-code-producer.json @@ -0,0 +1 @@ +{"body":{"adapter_version":"v1","offered_capabilities":["core.harness.produce.v1"],"offered_execution_kinds":["model"],"offered_permissions":["core.perm.evidence.write.v1","core.perm.model.invoke.v1","core.perm.scratch.write.v1","core.perm.target.read.v1"],"offered_roles":["producer"],"offered_tools":[],"package_ref":{"location":{"kind":"path","value":"adapters/claude-code-producer/v1/normalize.jq"},"mode":"100644","object_id":"8af4d80e04f6f3877861e55c216a5891830b03b6","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}}},"id":"adapter.claude-code-producer.v1","kind":"adapter_manifest","schema_version":2} diff --git a/profiles/default/v1/manifests/codex-native-reviewer.json b/profiles/default/v1/manifests/codex-native-reviewer.json new file mode 100644 index 0000000..dec7d8a --- /dev/null +++ b/profiles/default/v1/manifests/codex-native-reviewer.json @@ -0,0 +1 @@ +{"body":{"adapter_version":"v1","offered_capabilities":["core.review.change.v1"],"offered_execution_kinds":["model"],"offered_permissions":["core.perm.evidence.write.v1","core.perm.model.invoke.v1","core.perm.target.read.v1"],"offered_roles":["reviewer"],"offered_tools":[],"package_ref":{"location":{"kind":"path","value":"adapters/codex-native-reviewer/v1/normalize.jq"},"mode":"100644","object_id":"432f09f36f8c93076388e4a26dba56b6ee7a2bf9","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}}},"id":"adapter.codex-native-reviewer.v1","kind":"adapter_manifest","schema_version":2} diff --git a/profiles/default/v1/manifests/deterministic-verifier.json b/profiles/default/v1/manifests/deterministic-verifier.json new file mode 100644 index 0000000..f472c45 --- /dev/null +++ b/profiles/default/v1/manifests/deterministic-verifier.json @@ -0,0 +1 @@ +{"body":{"adapter_version":"v1","offered_capabilities":["core.verify.run.v1"],"offered_execution_kinds":["deterministic"],"offered_permissions":["core.perm.candidate.execute.v1","core.perm.evidence.write.v1","core.perm.target.read.v1"],"offered_roles":["verifier"],"offered_tools":[],"package_ref":{"location":{"kind":"path","value":"adapters/deterministic-verifier/v1/normalize.jq"},"mode":"100644","object_id":"15fbf4648ee33b8c2fe15ab04357376313f900f6","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}}},"id":"adapter.deterministic-verifier.v1","kind":"adapter_manifest","schema_version":2} diff --git a/profiles/default/v1/manifests/dormant-publisher.json b/profiles/default/v1/manifests/dormant-publisher.json new file mode 100644 index 0000000..2845d89 --- /dev/null +++ b/profiles/default/v1/manifests/dormant-publisher.json @@ -0,0 +1 @@ +{"body":{"adapter_version":"v1","offered_capabilities":[],"offered_execution_kinds":["deterministic"],"offered_permissions":[],"offered_roles":["publisher"],"offered_tools":[],"package_ref":{"location":{"kind":"path","value":"adapters/dormant-publisher/v1/normalize.jq"},"mode":"100644","object_id":"86ed0cd6b740a192b829044d7bcb7187e5f38422","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}}},"id":"adapter.dormant-publisher.v1","kind":"adapter_manifest","schema_version":2} diff --git a/profiles/default/v1/manifests/github-actions-ci.json b/profiles/default/v1/manifests/github-actions-ci.json new file mode 100644 index 0000000..b07ee0b --- /dev/null +++ b/profiles/default/v1/manifests/github-actions-ci.json @@ -0,0 +1 @@ +{"body":{"adapter_version":"v1","offered_capabilities":[],"offered_execution_kinds":["deterministic"],"offered_permissions":[],"offered_roles":["ci"],"offered_tools":[],"package_ref":{"location":{"kind":"path","value":"adapters/github-actions-ci/v1/normalize.jq"},"mode":"100644","object_id":"2fad7d2d217a5704fcd4e2d1f559309aa832d16d","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}}},"id":"adapter.github-actions-ci.v1","kind":"adapter_manifest","schema_version":2} diff --git a/profiles/default/v1/manifests/github-forge.json b/profiles/default/v1/manifests/github-forge.json new file mode 100644 index 0000000..74ce169 --- /dev/null +++ b/profiles/default/v1/manifests/github-forge.json @@ -0,0 +1 @@ +{"body":{"adapter_version":"v1","offered_capabilities":[],"offered_execution_kinds":["deterministic"],"offered_permissions":[],"offered_roles":["identity"],"offered_tools":[],"package_ref":{"location":{"kind":"path","value":"adapters/github-forge/v1/normalize.jq"},"mode":"100644","object_id":"feb4622bc4371dce337b1406062919ef2c2c5b49","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}}},"id":"adapter.github-forge.v1","kind":"adapter_manifest","schema_version":2} diff --git a/profiles/default/v1/manifests/local-git-materializer.json b/profiles/default/v1/manifests/local-git-materializer.json new file mode 100644 index 0000000..38c71b5 --- /dev/null +++ b/profiles/default/v1/manifests/local-git-materializer.json @@ -0,0 +1 @@ +{"body":{"adapter_version":"v1","offered_capabilities":["core.forge.materialize-candidate.v2"],"offered_execution_kinds":["deterministic"],"offered_permissions":["core.perm.candidate-repository.write.v2","core.perm.evidence.write.v1","core.perm.scratch.write.v1","core.perm.target.read.v1"],"offered_roles":["forge"],"offered_tools":[],"package_ref":{"location":{"kind":"path","value":"adapters/local-git-materializer/v1"},"mode":"040000","object_id":"277863b98b49e54e2cd826b3f32913fd49c51abf","object_type":"tree","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}}},"id":"adapter.local-git-materializer.v1","kind":"adapter_manifest","schema_version":2} diff --git a/profiles/default/v1/profile.json b/profiles/default/v1/profile.json new file mode 100644 index 0000000..36dc0e4 --- /dev/null +++ b/profiles/default/v1/profile.json @@ -0,0 +1 @@ +{"body":{"bindings":[{"adapter_instance_id":"instance.ci","binding_id":"binding.ci","execution_boundary_id":"boundary.ci","execution_kind":"deterministic","manifest_ref":{"id":"adapter.github-actions-ci.v1","kind":"adapter_manifest","schema_version":2,"sha256":"a5cf4b1b94e32d850e3d056024fa2d2c3977b977fb08323e99b89f8c159baff3"},"package_ref":{"location":{"kind":"path","value":"adapters/github-actions-ci/v1/normalize.jq"},"mode":"100644","object_id":"2fad7d2d217a5704fcd4e2d1f559309aa832d16d","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"principal_id":"principal.ci","requested_capabilities":[],"requested_permissions":[],"requested_tools":[],"role":"ci","skill_refs":[]},{"adapter_instance_id":"instance.forge","authority_ref":{"decision_record_ref":{"content_id":"roadmap","media_type":"text/markdown","sha256":"1466262c8994d637a02cc3503c35e3254ecce28479f9847589cb112e42b00107"},"purpose":"authority","scope_sha256":"e31dd669bf048817b503928e51191809cf3a3718d328dc5ab8875a4fe9be2911","subject_ref":{"type":"artifact","value":{"type":"content","value":{"content_id":"authority-forge","media_type":"application/json","sha256":"e31dd669bf048817b503928e51191809cf3a3718d328dc5ab8875a4fe9be2911"}}}},"binding_id":"binding.forge","execution_boundary_id":"boundary.forge","execution_kind":"deterministic","manifest_ref":{"id":"adapter.local-git-materializer.v1","kind":"adapter_manifest","schema_version":2,"sha256":"47c5884ca83597a09f1122467c9c0dfd3ea5b4e0256d2d52ae648167349bffe5"},"package_ref":{"location":{"kind":"path","value":"adapters/local-git-materializer/v1"},"mode":"040000","object_id":"277863b98b49e54e2cd826b3f32913fd49c51abf","object_type":"tree","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"principal_id":"principal.forge","requested_capabilities":["core.forge.materialize-candidate.v2"],"requested_permissions":["core.perm.candidate-repository.write.v2","core.perm.evidence.write.v1","core.perm.scratch.write.v1","core.perm.target.read.v1"],"requested_tools":[],"role":"forge","skill_refs":[]},{"adapter_instance_id":"instance.identity","binding_id":"binding.identity","execution_boundary_id":"boundary.identity","execution_kind":"deterministic","manifest_ref":{"id":"adapter.github-forge.v1","kind":"adapter_manifest","schema_version":2,"sha256":"a6290a480ab72b7deac2bc74bc63e35e4fa1dc952bab47de4b17ee9134476044"},"package_ref":{"location":{"kind":"path","value":"adapters/github-forge/v1/normalize.jq"},"mode":"100644","object_id":"feb4622bc4371dce337b1406062919ef2c2c5b49","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"principal_id":"principal.identity","requested_capabilities":[],"requested_permissions":[],"requested_tools":[],"role":"identity","skill_refs":[]},{"adapter_instance_id":"instance.producer","authority_ref":{"decision_record_ref":{"content_id":"roadmap","media_type":"text/markdown","sha256":"1466262c8994d637a02cc3503c35e3254ecce28479f9847589cb112e42b00107"},"purpose":"authority","scope_sha256":"b35cdd26196d8d93abe1c387cd4edcf9a130ddcc7a718b2431ddf94135eb19d5","subject_ref":{"type":"artifact","value":{"type":"content","value":{"content_id":"authority-producer","media_type":"application/json","sha256":"b35cdd26196d8d93abe1c387cd4edcf9a130ddcc7a718b2431ddf94135eb19d5"}}}},"binding_id":"binding.producer","execution_boundary_id":"boundary.producer","execution_kind":"model","manifest_ref":{"id":"adapter.claude-code-producer.v1","kind":"adapter_manifest","schema_version":2,"sha256":"d849818eb02c96972e1ac90540fd1b00749384f07bb56ed66f0800f78537479e"},"model_request":{"effort_id":"high","model_id":"claude.sonnet","provider_id":"anthropic"},"package_ref":{"location":{"kind":"path","value":"adapters/claude-code-producer/v1/normalize.jq"},"mode":"100644","object_id":"8af4d80e04f6f3877861e55c216a5891830b03b6","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"principal_id":"principal.producer","prompt_ref":{"location":{"kind":"path","value":"routines/coder.md"},"mode":"100644","object_id":"b307b85339fbfc060aec59c625918a3f20707438","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"requested_capabilities":["core.harness.produce.v1"],"requested_permissions":["core.perm.evidence.write.v1","core.perm.model.invoke.v1","core.perm.scratch.write.v1","core.perm.target.read.v1"],"requested_tools":[],"role":"producer","skill_refs":[]},{"adapter_instance_id":"instance.publisher","authority_ref":{"decision_record_ref":{"content_id":"roadmap","media_type":"text/markdown","sha256":"1466262c8994d637a02cc3503c35e3254ecce28479f9847589cb112e42b00107"},"purpose":"authority","scope_sha256":"9d00187a85fea0021fac962ee13791a14420fb71f4c9e5dcb23a392d5cf0436e","subject_ref":{"type":"artifact","value":{"type":"content","value":{"content_id":"authority-publisher","media_type":"application/json","sha256":"9d00187a85fea0021fac962ee13791a14420fb71f4c9e5dcb23a392d5cf0436e"}}}},"binding_id":"binding.publisher","execution_boundary_id":"boundary.publisher","execution_kind":"deterministic","manifest_ref":{"id":"adapter.dormant-publisher.v1","kind":"adapter_manifest","schema_version":2,"sha256":"e780e0ceb0a305928d6c1fec127cfc6db0140cf2e48b3921e23e59d942419029"},"package_ref":{"location":{"kind":"path","value":"adapters/dormant-publisher/v1/normalize.jq"},"mode":"100644","object_id":"86ed0cd6b740a192b829044d7bcb7187e5f38422","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"principal_id":"principal.publisher","requested_capabilities":[],"requested_permissions":[],"requested_tools":[],"role":"publisher","skill_refs":[]},{"adapter_instance_id":"instance.reviewer","authority_ref":{"decision_record_ref":{"content_id":"roadmap","media_type":"text/markdown","sha256":"1466262c8994d637a02cc3503c35e3254ecce28479f9847589cb112e42b00107"},"purpose":"authority","scope_sha256":"a74f15bc7a469e74924725ab9c319ed9162f44fa12b3cf850798f8274c446b6a","subject_ref":{"type":"artifact","value":{"type":"content","value":{"content_id":"authority-reviewer","media_type":"application/json","sha256":"a74f15bc7a469e74924725ab9c319ed9162f44fa12b3cf850798f8274c446b6a"}}}},"binding_id":"binding.reviewer","execution_boundary_id":"boundary.reviewer","execution_kind":"model","manifest_ref":{"id":"adapter.codex-native-reviewer.v1","kind":"adapter_manifest","schema_version":2,"sha256":"2f1ceaacd455e6cadc09f2762c6735eab48b91890240b6031af3db744a1175c4"},"model_request":{"effort_id":"high","model_id":"codex.review","provider_id":"openai"},"package_ref":{"location":{"kind":"path","value":"adapters/codex-native-reviewer/v1/normalize.jq"},"mode":"100644","object_id":"432f09f36f8c93076388e4a26dba56b6ee7a2bf9","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"principal_id":"principal.reviewer","prompt_ref":{"location":{"kind":"path","value":"reviewer/codex-review.md"},"mode":"100644","object_id":"b757f78b26f926a6688077a81f5b68a37c1c6690","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"requested_capabilities":["core.review.change.v1"],"requested_permissions":["core.perm.evidence.write.v1","core.perm.model.invoke.v1","core.perm.target.read.v1"],"requested_tools":[],"role":"reviewer","skill_refs":[]},{"adapter_instance_id":"instance.verifier","authority_ref":{"decision_record_ref":{"content_id":"roadmap","media_type":"text/markdown","sha256":"1466262c8994d637a02cc3503c35e3254ecce28479f9847589cb112e42b00107"},"purpose":"authority","scope_sha256":"aa7447ee06f5e2a74124f2d0a9d96a4e7552e626ccbd6e60a5ba694331effe04","subject_ref":{"type":"artifact","value":{"type":"content","value":{"content_id":"authority-verifier","media_type":"application/json","sha256":"aa7447ee06f5e2a74124f2d0a9d96a4e7552e626ccbd6e60a5ba694331effe04"}}}},"binding_id":"binding.verifier","execution_boundary_id":"boundary.verifier","execution_kind":"deterministic","manifest_ref":{"id":"adapter.deterministic-verifier.v1","kind":"adapter_manifest","schema_version":2,"sha256":"58f65eeac7dc8292e48adf6e1d0e8235d5a19c92521993c74b7b3368bb3f36fe"},"package_ref":{"location":{"kind":"path","value":"adapters/deterministic-verifier/v1/normalize.jq"},"mode":"100644","object_id":"15fbf4648ee33b8c2fe15ab04357376313f900f6","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"principal_id":"principal.verifier","requested_capabilities":["core.verify.run.v1"],"requested_permissions":["core.perm.candidate.execute.v1","core.perm.evidence.write.v1","core.perm.target.read.v1"],"requested_tools":[],"role":"verifier","skill_refs":[]}],"profile_version":"v1"},"id":"profile.default.v1","kind":"profile","schema_version":2} diff --git a/scripts/test/default-profile-assembly.test.sh b/scripts/test/default-profile-assembly.test.sh new file mode 100755 index 0000000..b8c3c85 --- /dev/null +++ b/scripts/test/default-profile-assembly.test.sh @@ -0,0 +1,105 @@ +#!/usr/bin/env bash +set -euo pipefail +export LC_ALL=C + +root=$(CDPATH='' cd -P -- "${BASH_SOURCE[0]%/*}/../.." && pwd -P) +profile="$root/profiles/default/v1/profile.json" +manifest_root="$root/profiles/default/v1/manifests" +manifests=("$manifest_root"/*.json) +roadmap="$root/ROADMAP.md" +roadmap_sha='1466262c8994d637a02cc3503c35e3254ecce28479f9847589cb112e42b00107' +package_commit='a637451d4b3fbef6b516a9c08f68c0dde46a7059' +fail() { printf 'FAIL: %s\n' "$1" >&2; exit 1; } +pass=0 +ok() { pass=$((pass + 1)); printf 'ok %s - %s\n' "$pass" "$1"; } +sha_file() { /usr/bin/shasum -a 256 "$1" | /usr/bin/awk '{print $1}'; } + +[ "$(jq --version)" = jq-1.6 ] || fail jq-version +[ "${#manifests[@]}" -eq 7 ] || fail manifest-count +scripts_core="$root/scripts/core-contract.sh" +"$scripts_core" validate-document "$profile" || fail profile-document +for manifest in "${manifests[@]}"; do + "$scripts_core" validate-document "$manifest" || fail "manifest-${manifest##*/}" +done +ok 'profile and seven manifests pass core v2 document validation' + +jq -e ' + .id == "profile.default.v1" and .body.profile_version == "v1" and + (.body.bindings | length) == 7 and + ([.body.bindings[].role] | sort) == + ["ci","forge","identity","producer","publisher","reviewer","verifier"] and + ([.body.bindings[].binding_id] | unique | length) == 7 and + ([.body.bindings[].adapter_instance_id] | unique | length) == 7 and + ([.body.bindings[].principal_id] | unique | length) == 7 and + ([.body.bindings[].execution_boundary_id] | unique | length) == 7 and + all(.body.bindings[] | select(.role|IN("forge","producer","publisher","reviewer","verifier")); + has("authority_ref")) and + ([.body.bindings[] | select(has("authority_ref"))] | length) == 5 and + all(.body.bindings[] | select(.role|IN("ci","identity")); + has("authority_ref") | not) and + all(.body.bindings[] | select(.role|IN("ci","identity","publisher")); + .requested_capabilities == [] and .requested_permissions == []) +' "$profile" >/dev/null || fail role-graph +ok 'roles and protected boundaries are complete and separated' + +[ "$(sha_file "$roadmap")" = "$roadmap_sha" ] || fail roadmap-digest +jq -e --arg digest "$roadmap_sha" ' + all(.body.bindings[] | select(has("authority_ref")); + .authority_ref.decision_record_ref == { + content_id:"roadmap", + media_type:"text/markdown", + sha256:$digest + }) +' "$profile" >/dev/null || fail authority-decision-record +ok 'protected authority scopes cite the accepted Roadmap decision record' + +for manifest in "${manifests[@]}"; do + digest=$(sha_file "$manifest") + id=$(jq -r .id "$manifest") + jq -e --arg id "$id" --arg digest "$digest" --slurpfile manifest "$manifest" ' + [.body.bindings[] | + select(.manifest_ref.id==$id and .manifest_ref.sha256==$digest)] as $matches | + ($matches | length) == 1 and + ($matches[0] as $binding | $manifest[0].body as $offered | + ($offered.offered_roles | index($binding.role)) != null and + ($offered.offered_execution_kinds | index($binding.execution_kind)) != null and + all($binding.requested_capabilities[]; . as $item | + ($offered.offered_capabilities | index($item)) != null) and + all($binding.requested_permissions[]; . as $item | + ($offered.offered_permissions | index($item)) != null) and + all($binding.requested_tools[]; . as $item | + ($offered.offered_tools | index($item)) != null) and + $binding.package_ref == $offered.package_ref) + ' "$profile" >/dev/null || fail "manifest-graph-$id" + commit=$(jq -r .body.package_ref.revision.commit_id "$manifest") + [ "$commit" = "$package_commit" ] || fail "package-commit-$id" + path=$(jq -r .body.package_ref.location.value "$manifest") + oid=$(jq -r .body.package_ref.object_id "$manifest") + mode=$(jq -r .body.package_ref.mode "$manifest") + type=$(jq -r .body.package_ref.object_type "$manifest") + record=$(git -C "$root" ls-tree "$commit" "$path") + [ "$record" = "$mode $type $oid"$'\t'"$path" ] || fail "package-object-$id" +done +while IFS= read -r ref; do + commit=$(jq -r .revision.commit_id <<<"$ref") + path=$(jq -r .location.value <<<"$ref") + [ "$commit" = "$package_commit" ] || fail "prompt-commit-$path" + oid=$(jq -r .object_id <<<"$ref") + mode=$(jq -r .mode <<<"$ref") + type=$(jq -r .object_type <<<"$ref") + record=$(git -C "$root" ls-tree "$commit" "$path") + [ "$record" = "$mode $type $oid"$'\t'"$path" ] || fail "prompt-object-$path" +done < <(jq -c '.body.bindings[] | .prompt_ref? // empty' "$profile") +ok 'every manifest graph and selected Git object is exact' + +jq -e ' + all(.body.bindings[]; + .requested_tools == [] and .skill_refs == []) and + (.body.bindings[] | select(.role=="producer") | + .model_request.provider_id=="anthropic" and .prompt_ref.location.value=="routines/coder.md") and + (.body.bindings[] | select(.role=="reviewer") | + .model_request.provider_id=="openai" and .prompt_ref.location.value=="reviewer/codex-review.md") +' "$profile" >/dev/null || fail default-selection +ok 'default model preferences are data and no tool is granted' + +printf 'default profile assembly: %s focused checks passed\n' "$pass" From 62e9887c2151315648a2b8c6844fe2742f9b7646 Mon Sep 17 00:00:00 2001 From: ci Date: Fri, 4 Sep 2026 15:55:13 -0400 Subject: [PATCH 2/8] Pin jq for default profile proof --- scripts/test/default-profile-assembly.test.sh | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/scripts/test/default-profile-assembly.test.sh b/scripts/test/default-profile-assembly.test.sh index b8c3c85..3f76e62 100755 --- a/scripts/test/default-profile-assembly.test.sh +++ b/scripts/test/default-profile-assembly.test.sh @@ -1,4 +1,5 @@ #!/usr/bin/env bash +# shellcheck disable=SC2016 set -euo pipefail export LC_ALL=C @@ -14,6 +15,58 @@ pass=0 ok() { pass=$((pass + 1)); printf 'ok %s - %s\n' "$pass" "$1"; } sha_file() { /usr/bin/shasum -a 256 "$1" | /usr/bin/awk '{print $1}'; } +tmp=$(/usr/bin/mktemp -d "${TMPDIR:-/tmp}/ystack-default-profile.XXXXXX") +download='' +cleanup() { + if [ -n "$download" ] && [ -f "$download" ]; then + /bin/rm -f -- "$download" + fi + /bin/rm -rf -- "$tmp" +} +trap cleanup EXIT + +platform=$(/usr/bin/uname -s):$(/usr/bin/uname -m) +case "$platform" in + Linux:x86_64) + asset='jq-linux64' + asset_sha='af986793a515d500ab2d35f8d2aecd656e764504b789b66d7e1a0b727a124c44' + ;; + Darwin:x86_64|Darwin:arm64) + asset='jq-osx-amd64' + asset_sha='5c0a0a3ea600f302ee458b30317425dd9632d1ad8882259fcaf4e9b868b2b1ef' + ;; + *) fail "unsupported jq 1.6 proof platform: $platform" ;; +esac + +cache="${TMPDIR:-/tmp}/ystack-portable-core-jq16" +/bin/mkdir -p "$cache" +jq_bin="$cache/$asset" +if [ ! -f "$jq_bin" ] || [ -L "$jq_bin" ] || + [ "$(sha_file "$jq_bin")" != "$asset_sha" ]; then + download=$(/usr/bin/mktemp "$cache/.jq-1.6.XXXXXX") + /usr/bin/curl --proto '=https' --tlsv1.2 -fsSL \ + "https://github.com/jqlang/jq/releases/download/jq-1.6/$asset" \ + -o "$download" + [ "$(sha_file "$download")" = "$asset_sha" ] || fail jq-download-digest + /bin/chmod 0555 "$download" + /bin/mv "$download" "$jq_bin" + download='' +fi + +jq_runtime="$tmp/bin" +/bin/mkdir "$jq_runtime" +if [ "$platform" = Darwin:arm64 ]; then + /bin/ln -s "$jq_bin" "$jq_runtime/jq-real" + /usr/bin/printf '%s\n' '#!/bin/sh' \ + 'exec /usr/bin/arch -x86_64 "${0%/*}/jq-real" "$@"' >"$jq_runtime/jq" + /bin/chmod 0555 "$jq_runtime/jq" +else + /bin/ln -s "$jq_bin" "$jq_runtime/jq" +fi +export PATH="$jq_runtime:$PATH" + +[ ! -L "$jq_bin" ] && [ "$(sha_file "$jq_bin")" = "$asset_sha" ] || + fail jq-cache-digest [ "$(jq --version)" = jq-1.6 ] || fail jq-version [ "${#manifests[@]}" -eq 7 ] || fail manifest-count scripts_core="$root/scripts/core-contract.sh" From 7fc2a040c24de1d184cba6b96d8b9d4922a89c4a Mon Sep 17 00:00:00 2001 From: ci Date: Fri, 4 Sep 2026 16:24:53 -0400 Subject: [PATCH 3/8] Support shallow default profile proof --- scripts/test/default-profile-assembly.test.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/test/default-profile-assembly.test.sh b/scripts/test/default-profile-assembly.test.sh index 3f76e62..90984fb 100755 --- a/scripts/test/default-profile-assembly.test.sh +++ b/scripts/test/default-profile-assembly.test.sh @@ -130,7 +130,7 @@ for manifest in "${manifests[@]}"; do oid=$(jq -r .body.package_ref.object_id "$manifest") mode=$(jq -r .body.package_ref.mode "$manifest") type=$(jq -r .body.package_ref.object_type "$manifest") - record=$(git -C "$root" ls-tree "$commit" "$path") + record=$(git -C "$root" ls-tree HEAD "$path") [ "$record" = "$mode $type $oid"$'\t'"$path" ] || fail "package-object-$id" done while IFS= read -r ref; do @@ -140,7 +140,7 @@ while IFS= read -r ref; do oid=$(jq -r .object_id <<<"$ref") mode=$(jq -r .mode <<<"$ref") type=$(jq -r .object_type <<<"$ref") - record=$(git -C "$root" ls-tree "$commit" "$path") + record=$(git -C "$root" ls-tree HEAD "$path") [ "$record" = "$mode $type $oid"$'\t'"$path" ] || fail "prompt-object-$path" done < <(jq -c '.body.bindings[] | .prompt_ref? // empty' "$profile") ok 'every manifest graph and selected Git object is exact' From aa285f3f9b6741077629e247b0b6b9f0817f726e Mon Sep 17 00:00:00 2001 From: ci Date: Fri, 4 Sep 2026 17:24:11 -0400 Subject: [PATCH 4/8] Anchor inactive producer config --- profiles/default/v1/producer-config.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 profiles/default/v1/producer-config.json diff --git a/profiles/default/v1/producer-config.json b/profiles/default/v1/producer-config.json new file mode 100644 index 0000000..369159a --- /dev/null +++ b/profiles/default/v1/producer-config.json @@ -0,0 +1 @@ +{"effort_id":"high","model_id":"claude.sonnet","provider_id":"anthropic","schema_version":1} From 43823f5b39dd6d351050256104582f44654332be Mon Sep 17 00:00:00 2001 From: ci Date: Sat, 5 Sep 2026 12:59:49 -0400 Subject: [PATCH 5/8] Pin the producer config and prove the assembled profile on the real normalizer Completes the in-progress fix for the two review findings on this PR. - P1: the producer manifest carries config_contract_ref and the producer binding carries config_ref, both bound to the immutable profiles/default/v1/producer-config.json blob. The test now builds a resolved profile for the assembled profile and runs the real Claude Code producer normalizer over changed and unchanged snapshots; a missing config is rejected. - P2: every pinned object is resolved at its recorded revision. The test fetches each recorded commit from origin by exact hash into a private history repository and runs ls-tree there, never against HEAD. - The profile now binds six adapters. The identity role, which had been bound to the GitHub forge observation payload, is dropped; that payload is not a forge materializer and remains a separate observation payload. The config reference currently names the pushed commit that introduced the config payload. Once that payload lands on main through its own PR, the reference is re-pinned to the main commit in a follow-up commit here. Co-Authored-By: Claude Fable 5.1 --- README.md | 16 +- RESTORE.md | 10 +- ci/required-files.txt | 2 +- .../v1/manifests/claude-code-producer.json | 2 +- .../default/v1/manifests/github-forge.json | 1 - profiles/default/v1/profile.json | 2 +- scripts/test/default-profile-assembly.test.sh | 245 +++++++++++++++++- 7 files changed, 251 insertions(+), 27 deletions(-) delete mode 100644 profiles/default/v1/manifests/github-forge.json diff --git a/README.md b/README.md index b585467..4dc1e32 100644 --- a/README.md +++ b/README.md @@ -37,15 +37,21 @@ runtime has an equivalent accepted descriptor-relative no-follow API. ## Inactive default profile assembly -`profiles/default/v1/` binds the seven default adapter packages to exact Git +`profiles/default/v1/` binds six default adapter packages to exact Git objects from one durable main commit. Protected roles keep distinct principals, execution boundaries, and authority scopes; their decision records cite the exact -accepted `ROADMAP.md` content. The profile requests no adapter tools, and the CI, -identity, and dormant-publisher roles request no capability or permission. +accepted `ROADMAP.md` content. The producer manifest and binding also pin the +profile's immutable producer config. Requested capabilities and permissions are +inactive contract data, not grants. The profile requests no adapter tools, and +the CI and dormant-publisher roles request no capability or permission. +The current normalizer payloads only validate supplied records and return +observations; they do not execute a model, verifier, forge, or other adapter. +The GitHub forge normalizer remains a separate observation payload. Transport and +runtime wiring are not part of this inactive assembly. This is source data only. It is not selected, resolved, qualified, installed, or -activated, and it cannot invoke a model, use a credential, contact a provider, -publish, or touch a target. Run +activated, has no authority or qualification, and cannot invoke a model, use a +credential, contact a provider, publish, or touch a target. Run `bash scripts/test/default-profile-assembly.test.sh` for the focused proof. ## Inactive portable core v2 fake-forge contract diff --git a/RESTORE.md b/RESTORE.md index 6b04bbe..3e997a7 100644 --- a/RESTORE.md +++ b/RESTORE.md @@ -64,11 +64,11 @@ Restore the nine paths listed under “Inactive default profile assembly” in bash scripts/test/default-profile-assembly.test.sh ``` -The proof validates the profile and seven manifests, their exact main package -objects, the accepted Roadmap decision record, role separation, and empty tool -grants. Restoring these records does not select, resolve, qualify, install, or -activate the profile and performs no model, credential, provider, publish, or -target operation. +The proof validates the profile and six manifests, their exact main package +objects, the producer config contract, the accepted Roadmap decision record, role +separation, and empty tool requests. Restoring these records does not select, +resolve, qualify, install, or activate the profile; it grants no authority and +performs no model, credential, provider, publish, or target operation. --- diff --git a/ci/required-files.txt b/ci/required-files.txt index fb86969..2724168 100644 --- a/ci/required-files.txt +++ b/ci/required-files.txt @@ -276,11 +276,11 @@ scripts/test/default-deterministic-verifier-adapter.test.sh # Inactive default profile assembly profiles/default/v1/profile.json +profiles/default/v1/producer-config.json profiles/default/v1/manifests/claude-code-producer.json profiles/default/v1/manifests/codex-native-reviewer.json profiles/default/v1/manifests/deterministic-verifier.json profiles/default/v1/manifests/dormant-publisher.json profiles/default/v1/manifests/github-actions-ci.json -profiles/default/v1/manifests/github-forge.json profiles/default/v1/manifests/local-git-materializer.json scripts/test/default-profile-assembly.test.sh diff --git a/profiles/default/v1/manifests/claude-code-producer.json b/profiles/default/v1/manifests/claude-code-producer.json index e047f54..ab86c81 100644 --- a/profiles/default/v1/manifests/claude-code-producer.json +++ b/profiles/default/v1/manifests/claude-code-producer.json @@ -1 +1 @@ -{"body":{"adapter_version":"v1","offered_capabilities":["core.harness.produce.v1"],"offered_execution_kinds":["model"],"offered_permissions":["core.perm.evidence.write.v1","core.perm.model.invoke.v1","core.perm.scratch.write.v1","core.perm.target.read.v1"],"offered_roles":["producer"],"offered_tools":[],"package_ref":{"location":{"kind":"path","value":"adapters/claude-code-producer/v1/normalize.jq"},"mode":"100644","object_id":"8af4d80e04f6f3877861e55c216a5891830b03b6","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}}},"id":"adapter.claude-code-producer.v1","kind":"adapter_manifest","schema_version":2} +{"body":{"adapter_version":"v1","config_contract_ref":{"decision_record_ref":{"content_id":"producer-config","media_type":"application/json","sha256":"ea076206d7f721aa4796c2a0830e95b3c7006703addc717240447c64ad589b61"},"purpose":"config-contract","scope_sha256":"ea076206d7f721aa4796c2a0830e95b3c7006703addc717240447c64ad589b61","subject_ref":{"type":"artifact","value":{"type":"content","value":{"content_id":"producer-config","media_type":"application/json","sha256":"ea076206d7f721aa4796c2a0830e95b3c7006703addc717240447c64ad589b61"}}}},"offered_capabilities":["core.harness.produce.v1"],"offered_execution_kinds":["model"],"offered_permissions":["core.perm.evidence.write.v1","core.perm.model.invoke.v1","core.perm.scratch.write.v1","core.perm.target.read.v1"],"offered_roles":["producer"],"offered_tools":[],"package_ref":{"location":{"kind":"path","value":"adapters/claude-code-producer/v1/normalize.jq"},"mode":"100644","object_id":"8af4d80e04f6f3877861e55c216a5891830b03b6","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}}},"id":"adapter.claude-code-producer.v1","kind":"adapter_manifest","schema_version":2} diff --git a/profiles/default/v1/manifests/github-forge.json b/profiles/default/v1/manifests/github-forge.json deleted file mode 100644 index 74ce169..0000000 --- a/profiles/default/v1/manifests/github-forge.json +++ /dev/null @@ -1 +0,0 @@ -{"body":{"adapter_version":"v1","offered_capabilities":[],"offered_execution_kinds":["deterministic"],"offered_permissions":[],"offered_roles":["identity"],"offered_tools":[],"package_ref":{"location":{"kind":"path","value":"adapters/github-forge/v1/normalize.jq"},"mode":"100644","object_id":"feb4622bc4371dce337b1406062919ef2c2c5b49","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}}},"id":"adapter.github-forge.v1","kind":"adapter_manifest","schema_version":2} diff --git a/profiles/default/v1/profile.json b/profiles/default/v1/profile.json index 36dc0e4..5ee18cf 100644 --- a/profiles/default/v1/profile.json +++ b/profiles/default/v1/profile.json @@ -1 +1 @@ -{"body":{"bindings":[{"adapter_instance_id":"instance.ci","binding_id":"binding.ci","execution_boundary_id":"boundary.ci","execution_kind":"deterministic","manifest_ref":{"id":"adapter.github-actions-ci.v1","kind":"adapter_manifest","schema_version":2,"sha256":"a5cf4b1b94e32d850e3d056024fa2d2c3977b977fb08323e99b89f8c159baff3"},"package_ref":{"location":{"kind":"path","value":"adapters/github-actions-ci/v1/normalize.jq"},"mode":"100644","object_id":"2fad7d2d217a5704fcd4e2d1f559309aa832d16d","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"principal_id":"principal.ci","requested_capabilities":[],"requested_permissions":[],"requested_tools":[],"role":"ci","skill_refs":[]},{"adapter_instance_id":"instance.forge","authority_ref":{"decision_record_ref":{"content_id":"roadmap","media_type":"text/markdown","sha256":"1466262c8994d637a02cc3503c35e3254ecce28479f9847589cb112e42b00107"},"purpose":"authority","scope_sha256":"e31dd669bf048817b503928e51191809cf3a3718d328dc5ab8875a4fe9be2911","subject_ref":{"type":"artifact","value":{"type":"content","value":{"content_id":"authority-forge","media_type":"application/json","sha256":"e31dd669bf048817b503928e51191809cf3a3718d328dc5ab8875a4fe9be2911"}}}},"binding_id":"binding.forge","execution_boundary_id":"boundary.forge","execution_kind":"deterministic","manifest_ref":{"id":"adapter.local-git-materializer.v1","kind":"adapter_manifest","schema_version":2,"sha256":"47c5884ca83597a09f1122467c9c0dfd3ea5b4e0256d2d52ae648167349bffe5"},"package_ref":{"location":{"kind":"path","value":"adapters/local-git-materializer/v1"},"mode":"040000","object_id":"277863b98b49e54e2cd826b3f32913fd49c51abf","object_type":"tree","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"principal_id":"principal.forge","requested_capabilities":["core.forge.materialize-candidate.v2"],"requested_permissions":["core.perm.candidate-repository.write.v2","core.perm.evidence.write.v1","core.perm.scratch.write.v1","core.perm.target.read.v1"],"requested_tools":[],"role":"forge","skill_refs":[]},{"adapter_instance_id":"instance.identity","binding_id":"binding.identity","execution_boundary_id":"boundary.identity","execution_kind":"deterministic","manifest_ref":{"id":"adapter.github-forge.v1","kind":"adapter_manifest","schema_version":2,"sha256":"a6290a480ab72b7deac2bc74bc63e35e4fa1dc952bab47de4b17ee9134476044"},"package_ref":{"location":{"kind":"path","value":"adapters/github-forge/v1/normalize.jq"},"mode":"100644","object_id":"feb4622bc4371dce337b1406062919ef2c2c5b49","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"principal_id":"principal.identity","requested_capabilities":[],"requested_permissions":[],"requested_tools":[],"role":"identity","skill_refs":[]},{"adapter_instance_id":"instance.producer","authority_ref":{"decision_record_ref":{"content_id":"roadmap","media_type":"text/markdown","sha256":"1466262c8994d637a02cc3503c35e3254ecce28479f9847589cb112e42b00107"},"purpose":"authority","scope_sha256":"b35cdd26196d8d93abe1c387cd4edcf9a130ddcc7a718b2431ddf94135eb19d5","subject_ref":{"type":"artifact","value":{"type":"content","value":{"content_id":"authority-producer","media_type":"application/json","sha256":"b35cdd26196d8d93abe1c387cd4edcf9a130ddcc7a718b2431ddf94135eb19d5"}}}},"binding_id":"binding.producer","execution_boundary_id":"boundary.producer","execution_kind":"model","manifest_ref":{"id":"adapter.claude-code-producer.v1","kind":"adapter_manifest","schema_version":2,"sha256":"d849818eb02c96972e1ac90540fd1b00749384f07bb56ed66f0800f78537479e"},"model_request":{"effort_id":"high","model_id":"claude.sonnet","provider_id":"anthropic"},"package_ref":{"location":{"kind":"path","value":"adapters/claude-code-producer/v1/normalize.jq"},"mode":"100644","object_id":"8af4d80e04f6f3877861e55c216a5891830b03b6","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"principal_id":"principal.producer","prompt_ref":{"location":{"kind":"path","value":"routines/coder.md"},"mode":"100644","object_id":"b307b85339fbfc060aec59c625918a3f20707438","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"requested_capabilities":["core.harness.produce.v1"],"requested_permissions":["core.perm.evidence.write.v1","core.perm.model.invoke.v1","core.perm.scratch.write.v1","core.perm.target.read.v1"],"requested_tools":[],"role":"producer","skill_refs":[]},{"adapter_instance_id":"instance.publisher","authority_ref":{"decision_record_ref":{"content_id":"roadmap","media_type":"text/markdown","sha256":"1466262c8994d637a02cc3503c35e3254ecce28479f9847589cb112e42b00107"},"purpose":"authority","scope_sha256":"9d00187a85fea0021fac962ee13791a14420fb71f4c9e5dcb23a392d5cf0436e","subject_ref":{"type":"artifact","value":{"type":"content","value":{"content_id":"authority-publisher","media_type":"application/json","sha256":"9d00187a85fea0021fac962ee13791a14420fb71f4c9e5dcb23a392d5cf0436e"}}}},"binding_id":"binding.publisher","execution_boundary_id":"boundary.publisher","execution_kind":"deterministic","manifest_ref":{"id":"adapter.dormant-publisher.v1","kind":"adapter_manifest","schema_version":2,"sha256":"e780e0ceb0a305928d6c1fec127cfc6db0140cf2e48b3921e23e59d942419029"},"package_ref":{"location":{"kind":"path","value":"adapters/dormant-publisher/v1/normalize.jq"},"mode":"100644","object_id":"86ed0cd6b740a192b829044d7bcb7187e5f38422","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"principal_id":"principal.publisher","requested_capabilities":[],"requested_permissions":[],"requested_tools":[],"role":"publisher","skill_refs":[]},{"adapter_instance_id":"instance.reviewer","authority_ref":{"decision_record_ref":{"content_id":"roadmap","media_type":"text/markdown","sha256":"1466262c8994d637a02cc3503c35e3254ecce28479f9847589cb112e42b00107"},"purpose":"authority","scope_sha256":"a74f15bc7a469e74924725ab9c319ed9162f44fa12b3cf850798f8274c446b6a","subject_ref":{"type":"artifact","value":{"type":"content","value":{"content_id":"authority-reviewer","media_type":"application/json","sha256":"a74f15bc7a469e74924725ab9c319ed9162f44fa12b3cf850798f8274c446b6a"}}}},"binding_id":"binding.reviewer","execution_boundary_id":"boundary.reviewer","execution_kind":"model","manifest_ref":{"id":"adapter.codex-native-reviewer.v1","kind":"adapter_manifest","schema_version":2,"sha256":"2f1ceaacd455e6cadc09f2762c6735eab48b91890240b6031af3db744a1175c4"},"model_request":{"effort_id":"high","model_id":"codex.review","provider_id":"openai"},"package_ref":{"location":{"kind":"path","value":"adapters/codex-native-reviewer/v1/normalize.jq"},"mode":"100644","object_id":"432f09f36f8c93076388e4a26dba56b6ee7a2bf9","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"principal_id":"principal.reviewer","prompt_ref":{"location":{"kind":"path","value":"reviewer/codex-review.md"},"mode":"100644","object_id":"b757f78b26f926a6688077a81f5b68a37c1c6690","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"requested_capabilities":["core.review.change.v1"],"requested_permissions":["core.perm.evidence.write.v1","core.perm.model.invoke.v1","core.perm.target.read.v1"],"requested_tools":[],"role":"reviewer","skill_refs":[]},{"adapter_instance_id":"instance.verifier","authority_ref":{"decision_record_ref":{"content_id":"roadmap","media_type":"text/markdown","sha256":"1466262c8994d637a02cc3503c35e3254ecce28479f9847589cb112e42b00107"},"purpose":"authority","scope_sha256":"aa7447ee06f5e2a74124f2d0a9d96a4e7552e626ccbd6e60a5ba694331effe04","subject_ref":{"type":"artifact","value":{"type":"content","value":{"content_id":"authority-verifier","media_type":"application/json","sha256":"aa7447ee06f5e2a74124f2d0a9d96a4e7552e626ccbd6e60a5ba694331effe04"}}}},"binding_id":"binding.verifier","execution_boundary_id":"boundary.verifier","execution_kind":"deterministic","manifest_ref":{"id":"adapter.deterministic-verifier.v1","kind":"adapter_manifest","schema_version":2,"sha256":"58f65eeac7dc8292e48adf6e1d0e8235d5a19c92521993c74b7b3368bb3f36fe"},"package_ref":{"location":{"kind":"path","value":"adapters/deterministic-verifier/v1/normalize.jq"},"mode":"100644","object_id":"15fbf4648ee33b8c2fe15ab04357376313f900f6","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"principal_id":"principal.verifier","requested_capabilities":["core.verify.run.v1"],"requested_permissions":["core.perm.candidate.execute.v1","core.perm.evidence.write.v1","core.perm.target.read.v1"],"requested_tools":[],"role":"verifier","skill_refs":[]}],"profile_version":"v1"},"id":"profile.default.v1","kind":"profile","schema_version":2} +{"body":{"bindings":[{"adapter_instance_id":"instance.ci","binding_id":"binding.ci","execution_boundary_id":"boundary.ci","execution_kind":"deterministic","manifest_ref":{"id":"adapter.github-actions-ci.v1","kind":"adapter_manifest","schema_version":2,"sha256":"a5cf4b1b94e32d850e3d056024fa2d2c3977b977fb08323e99b89f8c159baff3"},"package_ref":{"location":{"kind":"path","value":"adapters/github-actions-ci/v1/normalize.jq"},"mode":"100644","object_id":"2fad7d2d217a5704fcd4e2d1f559309aa832d16d","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"principal_id":"principal.ci","requested_capabilities":[],"requested_permissions":[],"requested_tools":[],"role":"ci","skill_refs":[]},{"adapter_instance_id":"instance.forge","authority_ref":{"decision_record_ref":{"content_id":"roadmap","media_type":"text/markdown","sha256":"1466262c8994d637a02cc3503c35e3254ecce28479f9847589cb112e42b00107"},"purpose":"authority","scope_sha256":"e31dd669bf048817b503928e51191809cf3a3718d328dc5ab8875a4fe9be2911","subject_ref":{"type":"artifact","value":{"type":"content","value":{"content_id":"authority-forge","media_type":"application/json","sha256":"e31dd669bf048817b503928e51191809cf3a3718d328dc5ab8875a4fe9be2911"}}}},"binding_id":"binding.forge","execution_boundary_id":"boundary.forge","execution_kind":"deterministic","manifest_ref":{"id":"adapter.local-git-materializer.v1","kind":"adapter_manifest","schema_version":2,"sha256":"47c5884ca83597a09f1122467c9c0dfd3ea5b4e0256d2d52ae648167349bffe5"},"package_ref":{"location":{"kind":"path","value":"adapters/local-git-materializer/v1"},"mode":"040000","object_id":"277863b98b49e54e2cd826b3f32913fd49c51abf","object_type":"tree","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"principal_id":"principal.forge","requested_capabilities":["core.forge.materialize-candidate.v2"],"requested_permissions":["core.perm.candidate-repository.write.v2","core.perm.evidence.write.v1","core.perm.scratch.write.v1","core.perm.target.read.v1"],"requested_tools":[],"role":"forge","skill_refs":[]},{"adapter_instance_id":"instance.producer","authority_ref":{"decision_record_ref":{"content_id":"roadmap","media_type":"text/markdown","sha256":"1466262c8994d637a02cc3503c35e3254ecce28479f9847589cb112e42b00107"},"purpose":"authority","scope_sha256":"b35cdd26196d8d93abe1c387cd4edcf9a130ddcc7a718b2431ddf94135eb19d5","subject_ref":{"type":"artifact","value":{"type":"content","value":{"content_id":"authority-producer","media_type":"application/json","sha256":"b35cdd26196d8d93abe1c387cd4edcf9a130ddcc7a718b2431ddf94135eb19d5"}}}},"binding_id":"binding.producer","config_ref":{"location":{"kind":"path","value":"profiles/default/v1/producer-config.json"},"mode":"100644","object_id":"369159a30c8a0026644c3716e7fc1132206e826c","object_type":"blob","revision":{"commit_id":"d97b8e36a2c305fa3888fafba0acda6b85fc93de","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"execution_boundary_id":"boundary.producer","execution_kind":"model","manifest_ref":{"id":"adapter.claude-code-producer.v1","kind":"adapter_manifest","schema_version":2,"sha256":"ada221fd7186544a53ceb2f10e0bbe863eb0ef6ef54b407c65f58d7f21881bb3"},"model_request":{"effort_id":"high","model_id":"claude.sonnet","provider_id":"anthropic"},"package_ref":{"location":{"kind":"path","value":"adapters/claude-code-producer/v1/normalize.jq"},"mode":"100644","object_id":"8af4d80e04f6f3877861e55c216a5891830b03b6","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"principal_id":"principal.producer","prompt_ref":{"location":{"kind":"path","value":"routines/coder.md"},"mode":"100644","object_id":"b307b85339fbfc060aec59c625918a3f20707438","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"requested_capabilities":["core.harness.produce.v1"],"requested_permissions":["core.perm.evidence.write.v1","core.perm.model.invoke.v1","core.perm.scratch.write.v1","core.perm.target.read.v1"],"requested_tools":[],"role":"producer","skill_refs":[]},{"adapter_instance_id":"instance.publisher","authority_ref":{"decision_record_ref":{"content_id":"roadmap","media_type":"text/markdown","sha256":"1466262c8994d637a02cc3503c35e3254ecce28479f9847589cb112e42b00107"},"purpose":"authority","scope_sha256":"9d00187a85fea0021fac962ee13791a14420fb71f4c9e5dcb23a392d5cf0436e","subject_ref":{"type":"artifact","value":{"type":"content","value":{"content_id":"authority-publisher","media_type":"application/json","sha256":"9d00187a85fea0021fac962ee13791a14420fb71f4c9e5dcb23a392d5cf0436e"}}}},"binding_id":"binding.publisher","execution_boundary_id":"boundary.publisher","execution_kind":"deterministic","manifest_ref":{"id":"adapter.dormant-publisher.v1","kind":"adapter_manifest","schema_version":2,"sha256":"e780e0ceb0a305928d6c1fec127cfc6db0140cf2e48b3921e23e59d942419029"},"package_ref":{"location":{"kind":"path","value":"adapters/dormant-publisher/v1/normalize.jq"},"mode":"100644","object_id":"86ed0cd6b740a192b829044d7bcb7187e5f38422","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"principal_id":"principal.publisher","requested_capabilities":[],"requested_permissions":[],"requested_tools":[],"role":"publisher","skill_refs":[]},{"adapter_instance_id":"instance.reviewer","authority_ref":{"decision_record_ref":{"content_id":"roadmap","media_type":"text/markdown","sha256":"1466262c8994d637a02cc3503c35e3254ecce28479f9847589cb112e42b00107"},"purpose":"authority","scope_sha256":"a74f15bc7a469e74924725ab9c319ed9162f44fa12b3cf850798f8274c446b6a","subject_ref":{"type":"artifact","value":{"type":"content","value":{"content_id":"authority-reviewer","media_type":"application/json","sha256":"a74f15bc7a469e74924725ab9c319ed9162f44fa12b3cf850798f8274c446b6a"}}}},"binding_id":"binding.reviewer","execution_boundary_id":"boundary.reviewer","execution_kind":"model","manifest_ref":{"id":"adapter.codex-native-reviewer.v1","kind":"adapter_manifest","schema_version":2,"sha256":"2f1ceaacd455e6cadc09f2762c6735eab48b91890240b6031af3db744a1175c4"},"model_request":{"effort_id":"high","model_id":"codex.review","provider_id":"openai"},"package_ref":{"location":{"kind":"path","value":"adapters/codex-native-reviewer/v1/normalize.jq"},"mode":"100644","object_id":"432f09f36f8c93076388e4a26dba56b6ee7a2bf9","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"principal_id":"principal.reviewer","prompt_ref":{"location":{"kind":"path","value":"reviewer/codex-review.md"},"mode":"100644","object_id":"b757f78b26f926a6688077a81f5b68a37c1c6690","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"requested_capabilities":["core.review.change.v1"],"requested_permissions":["core.perm.evidence.write.v1","core.perm.model.invoke.v1","core.perm.target.read.v1"],"requested_tools":[],"role":"reviewer","skill_refs":[]},{"adapter_instance_id":"instance.verifier","authority_ref":{"decision_record_ref":{"content_id":"roadmap","media_type":"text/markdown","sha256":"1466262c8994d637a02cc3503c35e3254ecce28479f9847589cb112e42b00107"},"purpose":"authority","scope_sha256":"aa7447ee06f5e2a74124f2d0a9d96a4e7552e626ccbd6e60a5ba694331effe04","subject_ref":{"type":"artifact","value":{"type":"content","value":{"content_id":"authority-verifier","media_type":"application/json","sha256":"aa7447ee06f5e2a74124f2d0a9d96a4e7552e626ccbd6e60a5ba694331effe04"}}}},"binding_id":"binding.verifier","execution_boundary_id":"boundary.verifier","execution_kind":"deterministic","manifest_ref":{"id":"adapter.deterministic-verifier.v1","kind":"adapter_manifest","schema_version":2,"sha256":"58f65eeac7dc8292e48adf6e1d0e8235d5a19c92521993c74b7b3368bb3f36fe"},"package_ref":{"location":{"kind":"path","value":"adapters/deterministic-verifier/v1/normalize.jq"},"mode":"100644","object_id":"15fbf4648ee33b8c2fe15ab04357376313f900f6","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"principal_id":"principal.verifier","requested_capabilities":["core.verify.run.v1"],"requested_permissions":["core.perm.candidate.execute.v1","core.perm.evidence.write.v1","core.perm.target.read.v1"],"requested_tools":[],"role":"verifier","skill_refs":[]}],"profile_version":"v1"},"id":"profile.default.v1","kind":"profile","schema_version":2} diff --git a/scripts/test/default-profile-assembly.test.sh b/scripts/test/default-profile-assembly.test.sh index 90984fb..708ddec 100755 --- a/scripts/test/default-profile-assembly.test.sh +++ b/scripts/test/default-profile-assembly.test.sh @@ -2,11 +2,14 @@ # shellcheck disable=SC2016 set -euo pipefail export LC_ALL=C +umask 077 root=$(CDPATH='' cd -P -- "${BASH_SOURCE[0]%/*}/../.." && pwd -P) profile="$root/profiles/default/v1/profile.json" manifest_root="$root/profiles/default/v1/manifests" manifests=("$manifest_root"/*.json) +producer_manifest="$manifest_root/claude-code-producer.json" +producer_config="$root/profiles/default/v1/producer-config.json" roadmap="$root/ROADMAP.md" roadmap_sha='1466262c8994d637a02cc3503c35e3254ecce28479f9847589cb112e42b00107' package_commit='a637451d4b3fbef6b516a9c08f68c0dde46a7059' @@ -68,29 +71,94 @@ export PATH="$jq_runtime:$PATH" [ ! -L "$jq_bin" ] && [ "$(sha_file "$jq_bin")" = "$asset_sha" ] || fail jq-cache-digest [ "$(jq --version)" = jq-1.6 ] || fail jq-version -[ "${#manifests[@]}" -eq 7 ] || fail manifest-count + +history_repo="$tmp/history.git" +history_home="$tmp/home" +/bin/mkdir "$history_home" +/usr/bin/env -i HOME="$history_home" PATH=/usr/bin:/bin LC_ALL=C \ + GIT_CONFIG_NOSYSTEM=1 GIT_TERMINAL_PROMPT=0 \ + /usr/bin/git init --bare -q "$history_repo" +history_git() { + /usr/bin/env -i HOME="$history_home" PATH=/usr/bin:/bin LC_ALL=C \ + GIT_CONFIG_NOSYSTEM=1 GIT_TERMINAL_PROMPT=0 \ + /usr/bin/git -C "$history_repo" "$@" +} +origin_url=$(/usr/bin/git -C "$root" remote get-url origin) +[[ "$origin_url" =~ ^https://[^/@[:space:]]+/[^?#[:space:]]+$ ]] || + fail origin-url +history_git -c credential.helper= -c core.askPass= fetch -q --no-tags --depth=1 \ + "$origin_url" "+$package_commit:refs/ystack/package" +[ "$(history_git rev-parse 'refs/ystack/package^{commit}')" = "$package_commit" ] || + fail package-fetch +[ "$(history_git rev-list --count refs/ystack/package)" -eq 1 ] || + fail package-fetch-depth +[ -z "$(history_git for-each-ref --format='%(refname)' refs/tags)" ] || + fail package-fetch-tags + +[ "${#manifests[@]}" -eq 6 ] || fail manifest-count scripts_core="$root/scripts/core-contract.sh" +generation=$(/usr/bin/sed -n \ + "s/^PORTABLE_CORE_GENERATION='\(g-[0-9a-f]\{64\}\)'$/\1/p" "$scripts_core") +[[ "$generation" =~ ^g-[0-9a-f]{64}$ ]] || fail core-generation +modules="$root/core/v2/generations/$generation/modules" +[ -d "$modules" ] && [ ! -L "$modules" ] || fail core-modules "$scripts_core" validate-document "$profile" || fail profile-document for manifest in "${manifests[@]}"; do "$scripts_core" validate-document "$manifest" || fail "manifest-${manifest##*/}" done -ok 'profile and seven manifests pass core v2 document validation' +ok 'profile and six manifests pass core v2 document validation' + +producer_config_ref=$(jq -c '.body.bindings[] | select(.role=="producer") | .config_ref' "$profile") +[ "$(jq -r 'type' <<<"$producer_config_ref")" = object ] || fail producer-config-ref +config_commit=$(jq -r '.revision.commit_id' <<<"$producer_config_ref") +config_path=$(jq -r '.location.value' <<<"$producer_config_ref") +config_oid=$(jq -r '.object_id' <<<"$producer_config_ref") +config_mode=$(jq -r '.mode' <<<"$producer_config_ref") +config_type=$(jq -r '.object_type' <<<"$producer_config_ref") +[ "$config_path" = 'profiles/default/v1/producer-config.json' ] || fail producer-config-path +[ "$config_oid" = "$(git -C "$root" hash-object "$producer_config")" ] || + fail producer-config-blob +history_git -c credential.helper= -c core.askPass= fetch -q --no-tags --depth=1 \ + "$origin_url" "+$config_commit:refs/ystack/producer-config" +[ "$(history_git rev-parse 'refs/ystack/producer-config^{commit}')" = "$config_commit" ] || + fail producer-config-fetch +[ "$(history_git rev-list --count refs/ystack/producer-config)" -eq 1 ] || + fail producer-config-fetch-depth +config_record=$(history_git ls-tree "$config_commit" "$config_path") +[ "$config_record" = "$config_mode $config_type $config_oid"$'\t'"$config_path" ] || + fail producer-config-object +config_sha=$(sha_file "$producer_config") +jq -e --arg config_sha "$config_sha" ' + .body.config_contract_ref as $contract | + $contract.purpose == "config-contract" and + $contract.scope_sha256 == $config_sha and + $contract.decision_record_ref == { + content_id:"producer-config",media_type:"application/json",sha256:$config_sha + } and + $contract.subject_ref == { + type:"artifact", + value:{type:"content",value:{ + content_id:"producer-config",media_type:"application/json",sha256:$config_sha + }} + } +' "$producer_manifest" >/dev/null || fail producer-config-contract +ok 'the producer config contract and Git object are exact at their recorded revision' jq -e ' .id == "profile.default.v1" and .body.profile_version == "v1" and - (.body.bindings | length) == 7 and + (.body.bindings | length) == 6 and ([.body.bindings[].role] | sort) == - ["ci","forge","identity","producer","publisher","reviewer","verifier"] and - ([.body.bindings[].binding_id] | unique | length) == 7 and - ([.body.bindings[].adapter_instance_id] | unique | length) == 7 and - ([.body.bindings[].principal_id] | unique | length) == 7 and - ([.body.bindings[].execution_boundary_id] | unique | length) == 7 and + ["ci","forge","producer","publisher","reviewer","verifier"] and + ([.body.bindings[].binding_id] | unique | length) == 6 and + ([.body.bindings[].adapter_instance_id] | unique | length) == 6 and + ([.body.bindings[].principal_id] | unique | length) == 6 and + ([.body.bindings[].execution_boundary_id] | unique | length) == 6 and all(.body.bindings[] | select(.role|IN("forge","producer","publisher","reviewer","verifier")); has("authority_ref")) and ([.body.bindings[] | select(has("authority_ref"))] | length) == 5 and - all(.body.bindings[] | select(.role|IN("ci","identity")); - has("authority_ref") | not) and - all(.body.bindings[] | select(.role|IN("ci","identity","publisher")); + all(.body.bindings[] | select(.role=="ci"); + has("authority_ref") | not) and + all(.body.bindings[] | select(.role|IN("ci","publisher")); .requested_capabilities == [] and .requested_permissions == []) ' "$profile" >/dev/null || fail role-graph ok 'roles and protected boundaries are complete and separated' @@ -130,7 +198,7 @@ for manifest in "${manifests[@]}"; do oid=$(jq -r .body.package_ref.object_id "$manifest") mode=$(jq -r .body.package_ref.mode "$manifest") type=$(jq -r .body.package_ref.object_type "$manifest") - record=$(git -C "$root" ls-tree HEAD "$path") + record=$(history_git ls-tree "$commit" "$path") [ "$record" = "$mode $type $oid"$'\t'"$path" ] || fail "package-object-$id" done while IFS= read -r ref; do @@ -140,7 +208,7 @@ while IFS= read -r ref; do oid=$(jq -r .object_id <<<"$ref") mode=$(jq -r .mode <<<"$ref") type=$(jq -r .object_type <<<"$ref") - record=$(git -C "$root" ls-tree HEAD "$path") + record=$(history_git ls-tree "$commit" "$path") [ "$record" = "$mode $type $oid"$'\t'"$path" ] || fail "prompt-object-$path" done < <(jq -c '.body.bindings[] | .prompt_ref? // empty' "$profile") ok 'every manifest graph and selected Git object is exact' @@ -155,4 +223,155 @@ jq -e ' ' "$profile" >/dev/null || fail default-selection ok 'default model preferences are data and no tool is granted' +producer_source_repo="$tmp/producer-source" +/usr/bin/git init -q "$producer_source_repo" +/bin/mkdir "$producer_source_repo/manifests" +/bin/cp "$profile" "$producer_source_repo/profile.json" +/bin/cp "$manifest_root"/*.json "$producer_source_repo/manifests/" +/usr/bin/git -C "$producer_source_repo" add profile.json manifests +/usr/bin/git -C "$producer_source_repo" -c user.name=ystack-test \ + -c user.email=ystack-test@example.invalid commit -q -m producer-source +producer_source_commit=$(/usr/bin/git -C "$producer_source_repo" rev-parse HEAD) +producer_manifest_pairs="$tmp/producer-manifest-pairs.json" +producer_manifest_sources="$tmp/producer-manifest-sources.json" +for manifest in "${manifests[@]}"; do + name=${manifest##*/} + manifest_id=$(jq -r .id "$manifest") + manifest_sha=$(sha_file "$manifest") + IFS=$' \t' read -r manifest_mode manifest_type manifest_oid _ < <( + /usr/bin/git -C "$producer_source_repo" ls-tree "$producer_source_commit" "manifests/$name") + jq -S -c -n --arg id "$manifest_id" --arg commit "$producer_source_commit" \ + --arg path "manifests/$name" --arg mode "$manifest_mode" --arg type "$manifest_type" \ + --arg oid "$manifest_oid" --arg sha "$manifest_sha" ' + {id:$id,source:{source:{revision:{repository_id:"repo.default-profile-test", + hash_algorithm:"sha1",commit_id:$commit},location:{kind:"path",value:$path}, + object_type:$type,object_id:$oid,mode:$mode},value_format:"canonical-json",value_sha256:$sha}}' +done >"$tmp/producer-manifest-records.jsonl" +jq -S -s '.' "$tmp/producer-manifest-records.jsonl" >"$producer_manifest_sources" +for manifest in "${manifests[@]}"; do + manifest_sha=$(sha_file "$manifest") + jq -S -c --arg sha "$manifest_sha" '{content:.,sha256:$sha}' "$manifest" +done | jq -S -s '.' >"$producer_manifest_pairs" +IFS=$' \t' read -r producer_profile_mode producer_profile_type producer_profile_oid _ < <( + /usr/bin/git -C "$producer_source_repo" ls-tree "$producer_source_commit" profile.json) +producer_profile_source="$tmp/producer-profile-source.json" +jq -S -c -n --arg commit "$producer_source_commit" --arg mode "$producer_profile_mode" \ + --arg type "$producer_profile_type" --arg oid "$producer_profile_oid" ' + {source:{revision:{repository_id:"repo.default-profile-test",hash_algorithm:"sha1", + commit_id:$commit},location:{kind:"path",value:"profile.json"},object_type:$type, + object_id:$oid,mode:$mode},value_format:"canonical-json",value_sha256:""}' \ + >"$producer_profile_source" + +build_producer_input() { + local case_profile=$1 case_state=$2 case_input=$3 + local case_resolved="$case_input.resolved" case_request="$case_input.request" + local case_snapshot="$case_input.snapshot" case_profile_sha case_resolved_sha + local case_request_sha case_snapshot_sha + case_profile_sha=$(sha_file "$case_profile") + jq -L "$modules" -L "$root/scripts/test" -S -c -n \ + --slurpfile profile_doc "$case_profile" --slurpfile profile_source "$producer_profile_source" \ + --slurpfile manifests "$producer_manifest_pairs" --slurpfile sources "$producer_manifest_sources" \ + --arg profile_sha "$case_profile_sha" ' + import "portable-core-stage-request-fixtures" as fixture; + def present($value): {state:"present",value:$value}; + def absent: {state:"absent"}; + def source_value($source;$format;$sha): + {source:$source,value_format:$format,value_sha256:$sha}; + def pair_for($id): first($manifests[0][] | select(.content.id==$id)); + def source_for($id): first($sources[0][] | select(.id==$id) | .source); + ($profile_source[0] | .value_sha256=$profile_sha) as $profile_source | + {schema_version:2,kind:"resolved_profile",id:"resolved.example",body:{ + profile_ref:{schema_version:2,kind:"profile",id:$profile_doc[0].id,sha256:$profile_sha}, + profile_source:$profile_source,selection_ref:fixture::selection_scope, + repository_context_ref:fixture::repository_context_scope, + bindings:[$profile_doc[0].body.bindings[] as $binding | + pair_for($binding.manifest_ref.id) as $manifest | + {binding:$binding,adapter_implementation:{id:$manifest.content.id, + version:$manifest.content.body.adapter_version}, + manifest_source:source_for($binding.manifest_ref.id), + package_source:source_value($binding.package_ref;"raw-bytes";$profile_sha), + config_source:(if $binding | has("config_ref") then + present(source_value($binding.config_ref;"raw-bytes";$profile_sha)) else absent end), + prompt_source:(if $binding | has("prompt_ref") then + present(source_value($binding.prompt_ref;"raw-bytes";$profile_sha)) else absent end), + skill_sources:($binding.skill_refs | map(source_value(.;"raw-bytes";$profile_sha))), + tool_sources:($binding.requested_tools | map({tool_id:.tool_id, + package_source:source_value(.package_ref;"raw-bytes";$profile_sha), + config_source:.config_ref})) + }]}} + ' >"$case_resolved" + case_resolved_sha=$(sha_file "$case_resolved") + jq -L "$root/scripts/test" -S -c -n --arg resolved_sha "$case_resolved_sha" ' + import "portable-core-stage-request-fixtures" as fixture; + def v2: walk(if type=="object" and has("schema_version") then .schema_version=2 else . end); + fixture::request_doc("producer";$resolved_sha) | v2 + ' >"$case_request" + case_request_sha=$(sha_file "$case_request") + jq -L "$modules" -L "$root/scripts/test" -S -c -n \ + --slurpfile request_doc "$case_request" --slurpfile resolved_doc "$case_resolved" \ + --arg state "$case_state" --arg request_sha "$case_request_sha" \ + --arg resolved_sha "$case_resolved_sha" ' + import "stage_request" as request; + def present($value): {state:"present",value:$value}; + def absent: {state:"absent"}; + def fact($id;$value;$n): {state:"recorded",value:$value, + source_ref:{content_id:$id,media_type:"application/json",sha256:($n*64)}}; + request::expected_execution_projection($request_doc[0].body;$resolved_doc[0].body) as $projection | + ($resolved_doc[0].body.bindings[] | select(.binding.role=="producer") | .binding) as $binding | + {schema_version:1,kind:"claude_code_producer_snapshot",id:"snapshot.assembly",body:{ + attempt:{attempt_id:"attempt.assembly",attempt_number:1, + started_at:"2026-08-30T00:01:00Z",finished_at:"2026-08-30T00:02:00Z", + recorded_at:"2026-08-30T00:03:00Z"}, + execution:{performer:$projection.performer,actual_binding:$projection.actual_binding, + environment:$projection.environment,used_capability:$projection.used_capability, + metadata:{kind:"model",provider:fact("fact.provider";$binding.model_request.provider_id;"1"), + model:fact("fact.model";$binding.model_request.model_id;"2"), + snapshot:fact("fact.snapshot";"claude-code.v1";"3"), + effort:fact("fact.effort";$binding.model_request.effort_id;"4"), + prompt:fact("fact.prompt";$binding.prompt_ref;"5"),skills:fact("fact.skills";$binding.skill_refs;"6"), + tools:fact("fact.tools";$binding.requested_tools;"7")}}, + observed_at:"2026-08-30T00:04:00Z", + output:(if $state=="changed" then present({content_id:"producer.patch", + media_type:"text/x-diff",sha256:("a"*64)}) else absent end), + provider_metadata:{message:{state:"absent"}}, + request_ref:{schema_version:2,kind:"stage_request",id:$request_doc[0].id,sha256:$request_sha}, + resolved_profile_ref:{schema_version:2,kind:"resolved_profile",id:$resolved_doc[0].id,sha256:$resolved_sha}, + state:$state,target_revision:$request_doc[0].body.target_revision.value}} + ' >"$case_snapshot" + case_snapshot_sha=$(sha_file "$case_snapshot") + jq -S -c -n --slurpfile snapshot "$case_snapshot" --slurpfile request_doc "$case_request" \ + --slurpfile resolved_doc "$case_resolved" --slurpfile manifest_doc "$producer_manifest" \ + --arg snapshot_sha "$case_snapshot_sha" --arg request_sha "$case_request_sha" \ + --arg resolved_sha "$case_resolved_sha" --arg manifest_sha "$(sha_file "$producer_manifest")" ' + {snapshot:$snapshot[0],trust_context:{schema_version:1,kind:"adapter_trust_context", + id:"trust.assembly",body:{binding_id:"binding.producer",expected_attempt_id:"attempt.assembly", + expected_attempt_number:1,manifest:{content:$manifest_doc[0],sha256:$manifest_sha}, + request:{content:$request_doc[0],sha256:$request_sha}, + resolved_profile:{content:$resolved_doc[0],sha256:$resolved_sha}, + target_revision:$request_doc[0].body.target_revision.value, + verified_snapshot:{content:$snapshot[0],sha256:$snapshot_sha}}}} + ' >"$case_input" +} + +producer_normalizer="$root/adapters/claude-code-producer/v1/normalize.jq" +build_producer_input "$profile" changed "$tmp/producer-changed.input" +jq -L "$modules" -S -c -f "$producer_normalizer" "$tmp/producer-changed.input" \ + >"$tmp/producer-changed.output" || fail producer-normalizer-changed +jq -e '.state=="changed" and .observation.binding.config_ref.state=="present"' \ + "$tmp/producer-changed.output" >/dev/null || fail producer-normalizer-changed-output +build_producer_input "$profile" no-change "$tmp/producer-no-change.input" +jq -L "$modules" -S -c -f "$producer_normalizer" "$tmp/producer-no-change.input" \ + >"$tmp/producer-no-change.output" || fail producer-normalizer-no-change +jq -e '.state=="no-change" and .observation.result.output_ref.state=="absent"' \ + "$tmp/producer-no-change.output" >/dev/null || fail producer-normalizer-no-change-output +jq -S -c 'del(.body.bindings[] | select(.role=="producer").config_ref)' "$profile" \ + >"$tmp/producer-missing-config.profile" +build_producer_input "$tmp/producer-missing-config.profile" changed "$tmp/producer-missing-config.input" +if jq -L "$modules" -S -c -f "$producer_normalizer" "$tmp/producer-missing-config.input" \ + >"$tmp/producer-missing-config.output" 2>"$tmp/producer-missing-config.error"; then + fail producer-normalizer-missing-config +fi +grep -Fq E_TRUST "$tmp/producer-missing-config.error" || fail producer-normalizer-missing-config-error +ok 'the assembled producer binding normalizes changed and unchanged snapshots and rejects a missing config' + printf 'default profile assembly: %s focused checks passed\n' "$pass" From 040e873518a2eb96469bf450d5cc0ba6bbc62597 Mon Sep 17 00:00:00 2001 From: ci Date: Sun, 6 Sep 2026 00:33:38 -0400 Subject: [PATCH 6/8] Pin the producer config to its durable main commit The producer binding's config_ref pointed at the config PR's branch head while that PR was open. It now points at the squash commit on main that carries profiles/default/v1/producer-config.json, so the reference stays resolvable after the branch is deleted. Co-Authored-By: Claude Fable 5.1 --- profiles/default/v1/profile.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/profiles/default/v1/profile.json b/profiles/default/v1/profile.json index 5ee18cf..b3adeb4 100644 --- a/profiles/default/v1/profile.json +++ b/profiles/default/v1/profile.json @@ -1 +1 @@ -{"body":{"bindings":[{"adapter_instance_id":"instance.ci","binding_id":"binding.ci","execution_boundary_id":"boundary.ci","execution_kind":"deterministic","manifest_ref":{"id":"adapter.github-actions-ci.v1","kind":"adapter_manifest","schema_version":2,"sha256":"a5cf4b1b94e32d850e3d056024fa2d2c3977b977fb08323e99b89f8c159baff3"},"package_ref":{"location":{"kind":"path","value":"adapters/github-actions-ci/v1/normalize.jq"},"mode":"100644","object_id":"2fad7d2d217a5704fcd4e2d1f559309aa832d16d","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"principal_id":"principal.ci","requested_capabilities":[],"requested_permissions":[],"requested_tools":[],"role":"ci","skill_refs":[]},{"adapter_instance_id":"instance.forge","authority_ref":{"decision_record_ref":{"content_id":"roadmap","media_type":"text/markdown","sha256":"1466262c8994d637a02cc3503c35e3254ecce28479f9847589cb112e42b00107"},"purpose":"authority","scope_sha256":"e31dd669bf048817b503928e51191809cf3a3718d328dc5ab8875a4fe9be2911","subject_ref":{"type":"artifact","value":{"type":"content","value":{"content_id":"authority-forge","media_type":"application/json","sha256":"e31dd669bf048817b503928e51191809cf3a3718d328dc5ab8875a4fe9be2911"}}}},"binding_id":"binding.forge","execution_boundary_id":"boundary.forge","execution_kind":"deterministic","manifest_ref":{"id":"adapter.local-git-materializer.v1","kind":"adapter_manifest","schema_version":2,"sha256":"47c5884ca83597a09f1122467c9c0dfd3ea5b4e0256d2d52ae648167349bffe5"},"package_ref":{"location":{"kind":"path","value":"adapters/local-git-materializer/v1"},"mode":"040000","object_id":"277863b98b49e54e2cd826b3f32913fd49c51abf","object_type":"tree","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"principal_id":"principal.forge","requested_capabilities":["core.forge.materialize-candidate.v2"],"requested_permissions":["core.perm.candidate-repository.write.v2","core.perm.evidence.write.v1","core.perm.scratch.write.v1","core.perm.target.read.v1"],"requested_tools":[],"role":"forge","skill_refs":[]},{"adapter_instance_id":"instance.producer","authority_ref":{"decision_record_ref":{"content_id":"roadmap","media_type":"text/markdown","sha256":"1466262c8994d637a02cc3503c35e3254ecce28479f9847589cb112e42b00107"},"purpose":"authority","scope_sha256":"b35cdd26196d8d93abe1c387cd4edcf9a130ddcc7a718b2431ddf94135eb19d5","subject_ref":{"type":"artifact","value":{"type":"content","value":{"content_id":"authority-producer","media_type":"application/json","sha256":"b35cdd26196d8d93abe1c387cd4edcf9a130ddcc7a718b2431ddf94135eb19d5"}}}},"binding_id":"binding.producer","config_ref":{"location":{"kind":"path","value":"profiles/default/v1/producer-config.json"},"mode":"100644","object_id":"369159a30c8a0026644c3716e7fc1132206e826c","object_type":"blob","revision":{"commit_id":"d97b8e36a2c305fa3888fafba0acda6b85fc93de","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"execution_boundary_id":"boundary.producer","execution_kind":"model","manifest_ref":{"id":"adapter.claude-code-producer.v1","kind":"adapter_manifest","schema_version":2,"sha256":"ada221fd7186544a53ceb2f10e0bbe863eb0ef6ef54b407c65f58d7f21881bb3"},"model_request":{"effort_id":"high","model_id":"claude.sonnet","provider_id":"anthropic"},"package_ref":{"location":{"kind":"path","value":"adapters/claude-code-producer/v1/normalize.jq"},"mode":"100644","object_id":"8af4d80e04f6f3877861e55c216a5891830b03b6","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"principal_id":"principal.producer","prompt_ref":{"location":{"kind":"path","value":"routines/coder.md"},"mode":"100644","object_id":"b307b85339fbfc060aec59c625918a3f20707438","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"requested_capabilities":["core.harness.produce.v1"],"requested_permissions":["core.perm.evidence.write.v1","core.perm.model.invoke.v1","core.perm.scratch.write.v1","core.perm.target.read.v1"],"requested_tools":[],"role":"producer","skill_refs":[]},{"adapter_instance_id":"instance.publisher","authority_ref":{"decision_record_ref":{"content_id":"roadmap","media_type":"text/markdown","sha256":"1466262c8994d637a02cc3503c35e3254ecce28479f9847589cb112e42b00107"},"purpose":"authority","scope_sha256":"9d00187a85fea0021fac962ee13791a14420fb71f4c9e5dcb23a392d5cf0436e","subject_ref":{"type":"artifact","value":{"type":"content","value":{"content_id":"authority-publisher","media_type":"application/json","sha256":"9d00187a85fea0021fac962ee13791a14420fb71f4c9e5dcb23a392d5cf0436e"}}}},"binding_id":"binding.publisher","execution_boundary_id":"boundary.publisher","execution_kind":"deterministic","manifest_ref":{"id":"adapter.dormant-publisher.v1","kind":"adapter_manifest","schema_version":2,"sha256":"e780e0ceb0a305928d6c1fec127cfc6db0140cf2e48b3921e23e59d942419029"},"package_ref":{"location":{"kind":"path","value":"adapters/dormant-publisher/v1/normalize.jq"},"mode":"100644","object_id":"86ed0cd6b740a192b829044d7bcb7187e5f38422","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"principal_id":"principal.publisher","requested_capabilities":[],"requested_permissions":[],"requested_tools":[],"role":"publisher","skill_refs":[]},{"adapter_instance_id":"instance.reviewer","authority_ref":{"decision_record_ref":{"content_id":"roadmap","media_type":"text/markdown","sha256":"1466262c8994d637a02cc3503c35e3254ecce28479f9847589cb112e42b00107"},"purpose":"authority","scope_sha256":"a74f15bc7a469e74924725ab9c319ed9162f44fa12b3cf850798f8274c446b6a","subject_ref":{"type":"artifact","value":{"type":"content","value":{"content_id":"authority-reviewer","media_type":"application/json","sha256":"a74f15bc7a469e74924725ab9c319ed9162f44fa12b3cf850798f8274c446b6a"}}}},"binding_id":"binding.reviewer","execution_boundary_id":"boundary.reviewer","execution_kind":"model","manifest_ref":{"id":"adapter.codex-native-reviewer.v1","kind":"adapter_manifest","schema_version":2,"sha256":"2f1ceaacd455e6cadc09f2762c6735eab48b91890240b6031af3db744a1175c4"},"model_request":{"effort_id":"high","model_id":"codex.review","provider_id":"openai"},"package_ref":{"location":{"kind":"path","value":"adapters/codex-native-reviewer/v1/normalize.jq"},"mode":"100644","object_id":"432f09f36f8c93076388e4a26dba56b6ee7a2bf9","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"principal_id":"principal.reviewer","prompt_ref":{"location":{"kind":"path","value":"reviewer/codex-review.md"},"mode":"100644","object_id":"b757f78b26f926a6688077a81f5b68a37c1c6690","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"requested_capabilities":["core.review.change.v1"],"requested_permissions":["core.perm.evidence.write.v1","core.perm.model.invoke.v1","core.perm.target.read.v1"],"requested_tools":[],"role":"reviewer","skill_refs":[]},{"adapter_instance_id":"instance.verifier","authority_ref":{"decision_record_ref":{"content_id":"roadmap","media_type":"text/markdown","sha256":"1466262c8994d637a02cc3503c35e3254ecce28479f9847589cb112e42b00107"},"purpose":"authority","scope_sha256":"aa7447ee06f5e2a74124f2d0a9d96a4e7552e626ccbd6e60a5ba694331effe04","subject_ref":{"type":"artifact","value":{"type":"content","value":{"content_id":"authority-verifier","media_type":"application/json","sha256":"aa7447ee06f5e2a74124f2d0a9d96a4e7552e626ccbd6e60a5ba694331effe04"}}}},"binding_id":"binding.verifier","execution_boundary_id":"boundary.verifier","execution_kind":"deterministic","manifest_ref":{"id":"adapter.deterministic-verifier.v1","kind":"adapter_manifest","schema_version":2,"sha256":"58f65eeac7dc8292e48adf6e1d0e8235d5a19c92521993c74b7b3368bb3f36fe"},"package_ref":{"location":{"kind":"path","value":"adapters/deterministic-verifier/v1/normalize.jq"},"mode":"100644","object_id":"15fbf4648ee33b8c2fe15ab04357376313f900f6","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"principal_id":"principal.verifier","requested_capabilities":["core.verify.run.v1"],"requested_permissions":["core.perm.candidate.execute.v1","core.perm.evidence.write.v1","core.perm.target.read.v1"],"requested_tools":[],"role":"verifier","skill_refs":[]}],"profile_version":"v1"},"id":"profile.default.v1","kind":"profile","schema_version":2} +{"body":{"bindings":[{"adapter_instance_id":"instance.ci","binding_id":"binding.ci","execution_boundary_id":"boundary.ci","execution_kind":"deterministic","manifest_ref":{"id":"adapter.github-actions-ci.v1","kind":"adapter_manifest","schema_version":2,"sha256":"a5cf4b1b94e32d850e3d056024fa2d2c3977b977fb08323e99b89f8c159baff3"},"package_ref":{"location":{"kind":"path","value":"adapters/github-actions-ci/v1/normalize.jq"},"mode":"100644","object_id":"2fad7d2d217a5704fcd4e2d1f559309aa832d16d","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"principal_id":"principal.ci","requested_capabilities":[],"requested_permissions":[],"requested_tools":[],"role":"ci","skill_refs":[]},{"adapter_instance_id":"instance.forge","authority_ref":{"decision_record_ref":{"content_id":"roadmap","media_type":"text/markdown","sha256":"1466262c8994d637a02cc3503c35e3254ecce28479f9847589cb112e42b00107"},"purpose":"authority","scope_sha256":"e31dd669bf048817b503928e51191809cf3a3718d328dc5ab8875a4fe9be2911","subject_ref":{"type":"artifact","value":{"type":"content","value":{"content_id":"authority-forge","media_type":"application/json","sha256":"e31dd669bf048817b503928e51191809cf3a3718d328dc5ab8875a4fe9be2911"}}}},"binding_id":"binding.forge","execution_boundary_id":"boundary.forge","execution_kind":"deterministic","manifest_ref":{"id":"adapter.local-git-materializer.v1","kind":"adapter_manifest","schema_version":2,"sha256":"47c5884ca83597a09f1122467c9c0dfd3ea5b4e0256d2d52ae648167349bffe5"},"package_ref":{"location":{"kind":"path","value":"adapters/local-git-materializer/v1"},"mode":"040000","object_id":"277863b98b49e54e2cd826b3f32913fd49c51abf","object_type":"tree","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"principal_id":"principal.forge","requested_capabilities":["core.forge.materialize-candidate.v2"],"requested_permissions":["core.perm.candidate-repository.write.v2","core.perm.evidence.write.v1","core.perm.scratch.write.v1","core.perm.target.read.v1"],"requested_tools":[],"role":"forge","skill_refs":[]},{"adapter_instance_id":"instance.producer","authority_ref":{"decision_record_ref":{"content_id":"roadmap","media_type":"text/markdown","sha256":"1466262c8994d637a02cc3503c35e3254ecce28479f9847589cb112e42b00107"},"purpose":"authority","scope_sha256":"b35cdd26196d8d93abe1c387cd4edcf9a130ddcc7a718b2431ddf94135eb19d5","subject_ref":{"type":"artifact","value":{"type":"content","value":{"content_id":"authority-producer","media_type":"application/json","sha256":"b35cdd26196d8d93abe1c387cd4edcf9a130ddcc7a718b2431ddf94135eb19d5"}}}},"binding_id":"binding.producer","config_ref":{"location":{"kind":"path","value":"profiles/default/v1/producer-config.json"},"mode":"100644","object_id":"369159a30c8a0026644c3716e7fc1132206e826c","object_type":"blob","revision":{"commit_id":"74c6662346dfec0f0e83d54105236e317539f461","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"execution_boundary_id":"boundary.producer","execution_kind":"model","manifest_ref":{"id":"adapter.claude-code-producer.v1","kind":"adapter_manifest","schema_version":2,"sha256":"ada221fd7186544a53ceb2f10e0bbe863eb0ef6ef54b407c65f58d7f21881bb3"},"model_request":{"effort_id":"high","model_id":"claude.sonnet","provider_id":"anthropic"},"package_ref":{"location":{"kind":"path","value":"adapters/claude-code-producer/v1/normalize.jq"},"mode":"100644","object_id":"8af4d80e04f6f3877861e55c216a5891830b03b6","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"principal_id":"principal.producer","prompt_ref":{"location":{"kind":"path","value":"routines/coder.md"},"mode":"100644","object_id":"b307b85339fbfc060aec59c625918a3f20707438","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"requested_capabilities":["core.harness.produce.v1"],"requested_permissions":["core.perm.evidence.write.v1","core.perm.model.invoke.v1","core.perm.scratch.write.v1","core.perm.target.read.v1"],"requested_tools":[],"role":"producer","skill_refs":[]},{"adapter_instance_id":"instance.publisher","authority_ref":{"decision_record_ref":{"content_id":"roadmap","media_type":"text/markdown","sha256":"1466262c8994d637a02cc3503c35e3254ecce28479f9847589cb112e42b00107"},"purpose":"authority","scope_sha256":"9d00187a85fea0021fac962ee13791a14420fb71f4c9e5dcb23a392d5cf0436e","subject_ref":{"type":"artifact","value":{"type":"content","value":{"content_id":"authority-publisher","media_type":"application/json","sha256":"9d00187a85fea0021fac962ee13791a14420fb71f4c9e5dcb23a392d5cf0436e"}}}},"binding_id":"binding.publisher","execution_boundary_id":"boundary.publisher","execution_kind":"deterministic","manifest_ref":{"id":"adapter.dormant-publisher.v1","kind":"adapter_manifest","schema_version":2,"sha256":"e780e0ceb0a305928d6c1fec127cfc6db0140cf2e48b3921e23e59d942419029"},"package_ref":{"location":{"kind":"path","value":"adapters/dormant-publisher/v1/normalize.jq"},"mode":"100644","object_id":"86ed0cd6b740a192b829044d7bcb7187e5f38422","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"principal_id":"principal.publisher","requested_capabilities":[],"requested_permissions":[],"requested_tools":[],"role":"publisher","skill_refs":[]},{"adapter_instance_id":"instance.reviewer","authority_ref":{"decision_record_ref":{"content_id":"roadmap","media_type":"text/markdown","sha256":"1466262c8994d637a02cc3503c35e3254ecce28479f9847589cb112e42b00107"},"purpose":"authority","scope_sha256":"a74f15bc7a469e74924725ab9c319ed9162f44fa12b3cf850798f8274c446b6a","subject_ref":{"type":"artifact","value":{"type":"content","value":{"content_id":"authority-reviewer","media_type":"application/json","sha256":"a74f15bc7a469e74924725ab9c319ed9162f44fa12b3cf850798f8274c446b6a"}}}},"binding_id":"binding.reviewer","execution_boundary_id":"boundary.reviewer","execution_kind":"model","manifest_ref":{"id":"adapter.codex-native-reviewer.v1","kind":"adapter_manifest","schema_version":2,"sha256":"2f1ceaacd455e6cadc09f2762c6735eab48b91890240b6031af3db744a1175c4"},"model_request":{"effort_id":"high","model_id":"codex.review","provider_id":"openai"},"package_ref":{"location":{"kind":"path","value":"adapters/codex-native-reviewer/v1/normalize.jq"},"mode":"100644","object_id":"432f09f36f8c93076388e4a26dba56b6ee7a2bf9","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"principal_id":"principal.reviewer","prompt_ref":{"location":{"kind":"path","value":"reviewer/codex-review.md"},"mode":"100644","object_id":"b757f78b26f926a6688077a81f5b68a37c1c6690","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"requested_capabilities":["core.review.change.v1"],"requested_permissions":["core.perm.evidence.write.v1","core.perm.model.invoke.v1","core.perm.target.read.v1"],"requested_tools":[],"role":"reviewer","skill_refs":[]},{"adapter_instance_id":"instance.verifier","authority_ref":{"decision_record_ref":{"content_id":"roadmap","media_type":"text/markdown","sha256":"1466262c8994d637a02cc3503c35e3254ecce28479f9847589cb112e42b00107"},"purpose":"authority","scope_sha256":"aa7447ee06f5e2a74124f2d0a9d96a4e7552e626ccbd6e60a5ba694331effe04","subject_ref":{"type":"artifact","value":{"type":"content","value":{"content_id":"authority-verifier","media_type":"application/json","sha256":"aa7447ee06f5e2a74124f2d0a9d96a4e7552e626ccbd6e60a5ba694331effe04"}}}},"binding_id":"binding.verifier","execution_boundary_id":"boundary.verifier","execution_kind":"deterministic","manifest_ref":{"id":"adapter.deterministic-verifier.v1","kind":"adapter_manifest","schema_version":2,"sha256":"58f65eeac7dc8292e48adf6e1d0e8235d5a19c92521993c74b7b3368bb3f36fe"},"package_ref":{"location":{"kind":"path","value":"adapters/deterministic-verifier/v1/normalize.jq"},"mode":"100644","object_id":"15fbf4648ee33b8c2fe15ab04357376313f900f6","object_type":"blob","revision":{"commit_id":"a637451d4b3fbef6b516a9c08f68c0dde46a7059","hash_algorithm":"sha1","repository_id":"repo.ystack"}},"principal_id":"principal.verifier","requested_capabilities":["core.verify.run.v1"],"requested_permissions":["core.perm.candidate.execute.v1","core.perm.evidence.write.v1","core.perm.target.read.v1"],"requested_tools":[],"role":"verifier","skill_refs":[]}],"profile_version":"v1"},"id":"profile.default.v1","kind":"profile","schema_version":2} From bc705d94caf985e44bd733bf4dada48cf6d3ed0f Mon Sep 17 00:00:00 2001 From: ci Date: Sun, 6 Sep 2026 01:00:55 -0400 Subject: [PATCH 7/8] List the producer config once in the restore manifest Merging main doubled the producer config entry in ci/required-files.txt, which the construction publisher gate refuses as a duplicate active entry. The config stays under its own block; the assembly block no longer repeats it. Proof: construction-publisher-gate 134 passed, 0 failures; default-profile-assembly 7/7. Co-Authored-By: Claude Fable 5.1 --- ci/required-files.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/ci/required-files.txt b/ci/required-files.txt index 5684c78..8cec8f8 100644 --- a/ci/required-files.txt +++ b/ci/required-files.txt @@ -288,7 +288,6 @@ scripts/test/default-deterministic-verifier-adapter.test.sh # Inactive default profile assembly profiles/default/v1/profile.json -profiles/default/v1/producer-config.json profiles/default/v1/manifests/claude-code-producer.json profiles/default/v1/manifests/codex-native-reviewer.json profiles/default/v1/manifests/deterministic-verifier.json From 3862a613cf2069186bb79f0c5cf7ae332bfe6bce Mon Sep 17 00:00:00 2001 From: ci Date: Sun, 6 Sep 2026 01:10:26 -0400 Subject: [PATCH 8/8] Let the history fetch use the checkout's own auth header The assembly test proves each pinned commit exists on origin by fetching it into a fresh bare repo with an empty HOME. On a private repo in CI that fetch had no credentials, because the checkout keeps its token as an http extraheader in its local Git config. The test now passes exactly those extraheader entries through the environment to the fresh repo's fetch and nothing else; the checkout itself is never written to. The restore note also counts the eight assembly paths and points at the producer config's own section. Proof: default-profile-assembly 7/7 plain, 7/7 with a probe extraheader set in the checkout config, and a bogus AUTHORIZATION extraheader makes the fetch fail, showing the header reaches it. shellcheck clean. Co-Authored-By: Claude Fable 5.1 --- RESTORE.md | 5 ++-- scripts/test/default-profile-assembly.test.sh | 25 ++++++++++++++++--- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/RESTORE.md b/RESTORE.md index a324731..82d8a2b 100644 --- a/RESTORE.md +++ b/RESTORE.md @@ -57,8 +57,9 @@ parent; restoring these files does not select a live profile. ### Restore the inactive default profile assembly -Restore the nine paths listed under “Inactive default profile assembly” in -[`ci/required-files.txt`](ci/required-files.txt) from one commit, then run: +Restore the eight paths listed under “Inactive default profile assembly” in +[`ci/required-files.txt`](ci/required-files.txt) from one commit, together with +the producer config restored under “Inactive default producer config”, then run: ```sh bash scripts/test/default-profile-assembly.test.sh diff --git a/scripts/test/default-profile-assembly.test.sh b/scripts/test/default-profile-assembly.test.sh index 708ddec..2b95e24 100755 --- a/scripts/test/default-profile-assembly.test.sh +++ b/scripts/test/default-profile-assembly.test.sh @@ -83,11 +83,29 @@ history_git() { GIT_CONFIG_NOSYSTEM=1 GIT_TERMINAL_PROMPT=0 \ /usr/bin/git -C "$history_repo" "$@" } +# A CI checkout keeps its token as an http extraheader in the checkout's local +# Git config. Pass exactly those entries through the environment so the fresh +# history repo can fetch a private origin; nothing is written to the checkout +# and no other config leaks into the fetch. +fetch_config=() +fetch_config_count=0 +while IFS= read -r -d '' entry; do + fetch_config+=("GIT_CONFIG_KEY_$fetch_config_count=${entry%%$'\n'*}" + "GIT_CONFIG_VALUE_$fetch_config_count=${entry#*$'\n'}") + fetch_config_count=$((fetch_config_count + 1)) +done < <(/usr/bin/git -C "$root" config --local --null --get-regexp \ + '^http\..*\.extraheader$' || true) +history_fetch() { + /usr/bin/env -i HOME="$history_home" PATH=/usr/bin:/bin LC_ALL=C \ + GIT_CONFIG_NOSYSTEM=1 GIT_TERMINAL_PROMPT=0 \ + GIT_CONFIG_COUNT="$fetch_config_count" ${fetch_config[@]+"${fetch_config[@]}"} \ + /usr/bin/git -C "$history_repo" -c credential.helper= -c core.askPass= \ + fetch -q --no-tags --depth=1 "$origin_url" "$@" +} origin_url=$(/usr/bin/git -C "$root" remote get-url origin) [[ "$origin_url" =~ ^https://[^/@[:space:]]+/[^?#[:space:]]+$ ]] || fail origin-url -history_git -c credential.helper= -c core.askPass= fetch -q --no-tags --depth=1 \ - "$origin_url" "+$package_commit:refs/ystack/package" +history_fetch "+$package_commit:refs/ystack/package" [ "$(history_git rev-parse 'refs/ystack/package^{commit}')" = "$package_commit" ] || fail package-fetch [ "$(history_git rev-list --count refs/ystack/package)" -eq 1 ] || @@ -118,8 +136,7 @@ config_type=$(jq -r '.object_type' <<<"$producer_config_ref") [ "$config_path" = 'profiles/default/v1/producer-config.json' ] || fail producer-config-path [ "$config_oid" = "$(git -C "$root" hash-object "$producer_config")" ] || fail producer-config-blob -history_git -c credential.helper= -c core.askPass= fetch -q --no-tags --depth=1 \ - "$origin_url" "+$config_commit:refs/ystack/producer-config" +history_fetch "+$config_commit:refs/ystack/producer-config" [ "$(history_git rev-parse 'refs/ystack/producer-config^{commit}')" = "$config_commit" ] || fail producer-config-fetch [ "$(history_git rev-list --count refs/ystack/producer-config)" -eq 1 ] ||