diff --git a/BACKLOG.md b/BACKLOG.md index 88132ec6..5163bddb 100644 --- a/BACKLOG.md +++ b/BACKLOG.md @@ -56,11 +56,11 @@ records, generated release manifests, or the owning docs named above. | BLOCKED | RELOCATION-01 | Add provenance-bounded witness relocation candidates without introducing a second binding path or trusting a caller-authored prior digest; detailed candidate contract is retained in [issue #66](https://github.com/research-engineering/agentic-proofkit/issues/66). | An owner-admitted content-addressed baseline binds witness id, prior path and digest, source revision, evidence class, authentication non-claims, and freshness non-claims; the scanner then proves the zero/one/many match partition while remaining non-current until fresh execution evidence exists. | | BLOCKED | RELEASE-01 | Prove signed protected-tag release policy as provider-side release governance, not source-only intent. | Repository tag protection/ruleset and release workflow variables require signed annotated release tags; the next public release records provider-side evidence or the row is explicitly retired as an accepted non-claim. | | DEFERRED | WEB-PUBLISH-DESIGN-01 | Investigate optional publication of the specification browser at a configurable domain with authentication. Preserve local loopback serving and local browser opening as the default workflow; remote publication must be explicit and opt-in. | After the current program, compare static export with external hosting, a bounded deployment adapter, and an authenticated hosted server. Decide whether any capability belongs in Proofkit or should remain external, using a concrete consumer need and maintenance/security costs. The decision must define URL and authentication configuration, hosting/TLS/access-control ownership, source-disclosure and secret boundaries, content freshness, and preservation of derived-view authority. Require a feasibility witness and negative cases for unauthorized access and unintended publication before accepting an implementation plan; otherwise retain local-only behavior and retire the candidate with rationale. This row authorizes investigation, not exposure of the current server or deployment. | -| DEFERRED | TRACEABILITY-DESIGN-01 | Design and validate the complete specification, scenario, native-test and execution-evidence workflow, including source intake, change impact and explanatory diagrams; see the bounded questions below. Start after the already scheduled global phases and existing backlog tasks are completed or explicitly dispositioned. | An owner-reviewed design and implementation decision resolves every question below against current Proofkit, StrictDoc and OpenSpec capabilities; an executable example and adversarial controls justify the selected ownership, storage and invalidation model. Existing mechanisms are reused when sufficient; unsupported additions are explicitly rejected rather than assumed necessary. | +| NEXT | TRACEABILITY-DESIGN-01 | Complete the specification, scenario, native-test and execution-evidence workflow, including source intake, change impact and explanatory diagrams; see the bounded questions below. Reuse current public contracts and retained evidence; lazy input guidance alone does not close the complete workflow. | An owner-reviewed design and implementation decision resolves every question below against current Proofkit, StrictDoc and OpenSpec capabilities; an executable example and adversarial controls justify the selected ownership, storage and invalidation model. Existing mechanisms are reused when sufficient; unsupported additions are explicitly rejected rather than assumed necessary. | ## TRACEABILITY-DESIGN-01 -This is deferred design work, not a claim that the following capabilities are +This is active design and validation work, not a claim that the following capabilities are implemented or absent. First establish the current behavior and reuse existing owners before proposing a new command, record, parser or workflow engine. diff --git a/internal/app/authoring_sources_test.go b/internal/app/authoring_sources_test.go new file mode 100644 index 00000000..463c968c --- /dev/null +++ b/internal/app/authoring_sources_test.go @@ -0,0 +1,115 @@ +package app + +import ( + "bytes" + "fmt" + "reflect" + "strings" + "testing" +) + +func TestAuthoringInputGuideIsLazy(t *testing.T) { + for _, args := range [][]string{{"help"}, {"help", "families"}, {"changed-path-set", "--help"}, {"native-evidence-guidance", "--help"}, {"change", "plan", "--help"}} { + code, output, diagnostic := executeAgentWorkflowCLI(t, args, panicReader{}, PresentationCapabilities{}) + if code != 0 || diagnostic != "" || strings.Contains(output, "Requirement authoring input guide:") { + t.Fatalf("authoring guide is not demand-loaded for %v", args) + } + } + _, output := receiptHelpTemplate(t, "requirement-authoring-plan") + if strings.Count(output, "Requirement authoring input guide:") != 1 { + t.Fatal("targeted authoring help lost its unique guide") + } +} + +func TestAuthoringSourceClassesPreserveProvenanceAndReviewCLI(t *testing.T) { + input, help := receiptHelpTemplate(t, "requirement-authoring-plan") + for _, text := range []string{ + "Admitted reference roles:", "external specifications", "test-coverage observations", + "product intent", "coverage percentage", "not an approval", + } { + if !strings.Contains(help, text) { + t.Fatalf("authoring help omits intake boundary %q", text) + } + } + cases := []struct{ name, kind, path, summary string }{ + {"code", "code_summary", "src/request.go", "Observed code rejects empty input; the owner must decide whether this is required."}, + {"external-spec", "design_doc", "imports/request-spec.md", "An external specification proposes accepting empty input; it is not this repository's authority."}, + {"intent", "clarification_answer", "decisions/intent.md", "The product owner proposes rejection of empty input for review."}, + {"design", "design_doc", "design/request.md", "The design proposes rejection of empty input."}, + {"plan", "implementation_plan", "plans/request.md", "The implementation plan proposes preserving empty-input rejection."}, + {"tests", "test_summary", "tests/request_test.go", "A test asserts empty-input rejection; no execution is asserted."}, + {"coverage", "test_summary", "reports/coverage.json", "Coverage-only observation: the empty-input branch is not exercised; no product requirement is inferred."}, + {"pr-facts", "pr_facts", "reviews/change.md", "A pull request proposes changing empty-input behavior; approval is unresolved."}, + } + for _, mode := range []string{"code-baseline", "audit-from-code"} { + for _, item := range cases { + t.Run(mode+"/"+item.name, func(t *testing.T) { + root := t.TempDir() + materialization := adoptionHelpPacket(t, root, mode) + source := materialization["requirementSources"].([]any)[0].(map[string]any) + empty := cloneMap(t, source) + empty["requirements"] = []any{} + packet := cloneMap(t, input) + packet["currentRequirementSource"] = empty + update := packet["candidateUpdates"].([]any)[0].(map[string]any) + update["candidateRequirement"] = source["requirements"].([]any)[0] + questions := []any{"Does the owner accept the proposed behavior?", "Which conflicting observation should be retained or rejected?"} + update["ownerQuestions"] = questions + ref := packet["authoringRefs"].([]any)[0].(map[string]any) + ref["kind"], ref["path"], ref["summary"] = item.kind, item.path, item.summary + ref["digest"] = "sha256:" + strings.Repeat("a", 64) + ref["nonClaims"] = []any{"Caller-provided observation; no authenticity, execution or approval is established."} + for _, authoringMode := range []string{"retrospective_baseline", "pull_request_design"} { + packet["mode"] = authoringMode + report := runAdoptionHelpCLI(t, adoptionHelpJSON(t, packet), "requirement-authoring-plan", "--input", "-") + if report["state"] != "passed" || !reflect.DeepEqual(report["authoringRefs"], packet["authoringRefs"]) { + t.Fatal("authoring lost an entire admitted reference") + } + changes := report["candidateChangeSet"].([]any) + if len(changes) != 1 || !reflect.DeepEqual(changes[0].(map[string]any)["sourceRefIds"], update["sourceRefIds"]) { + t.Fatal("candidate lost its provenance relation") + } + var ownerAction map[string]any + for _, raw := range report["ownerReviewPlan"].([]any) { + action := raw.(map[string]any) + if action["candidateId"] == update["candidateId"] { + ownerAction = action + } + } + if ownerAction == nil || !reflect.DeepEqual(ownerAction["ownerQuestions"], questions) || !reflect.DeepEqual(ownerAction["evidenceRefs"], update["sourceRefIds"]) { + t.Fatal("unresolved owner questions or evidence links disappeared") + } + preview := report["nonAuthoritativeAdmissionPreview"].(map[string]any) + if preview["authority"] != "candidate_only" || preview["candidateOnly"] != true || preview["ownerReviewRequired"] != true { + t.Fatal("observations or coverage became owner approval") + } + for _, field := range []string{"writtenFileCountNonClaim", "executedWitnessCountNonClaim"} { + if fmt.Sprint(report["summary"].(map[string]any)[field]) != "0" { + t.Fatal("authoring claimed an unperformed effect") + } + } + if !equalCLIJSON(t, preview["requirementSourcePreview"], source) { + t.Fatal("reference role changed canonical requirement meaning") + } + materialization["requirementSources"] = []any{preview["requirementSourcePreview"]} + plan := runAdoptionHelpCLI(t, adoptionHelpJSON(t, materialization), "adopt", "materialize", "plan", "--input", "-", "--repo-root", root) + if plan["state"] != "ready" || plan["sourceIntent"] != mode { + t.Fatal("actual candidate output cannot enter its declared adoption mode") + } + } + for _, field := range []string{"kind", "sourceRefIds"} { + invalid := cloneMap(t, packet) + if field == "kind" { + invalid["authoringRefs"].([]any)[0].(map[string]any)[field] = "unadmitted_kind" + } else { + invalid["candidateUpdates"].([]any)[0].(map[string]any)[field] = []any{"missing.ref"} + } + code, output, diagnostic := executeAgentWorkflowCLI(t, []string{"requirement-authoring-plan", "--input", "-"}, bytes.NewReader(adoptionHelpJSON(t, invalid)), PresentationCapabilities{}) + if code != 1 || output != "" || !strings.Contains(diagnostic, field) { + t.Fatalf("invalid %s did not fail at the intended boundary: %d %q %q", field, code, output, diagnostic) + } + } + }) + } + } +} diff --git a/internal/app/change_input_guide_test.go b/internal/app/change_input_guide_test.go new file mode 100644 index 00000000..38e3b7c5 --- /dev/null +++ b/internal/app/change_input_guide_test.go @@ -0,0 +1,176 @@ +package app + +import ( + "bytes" + "crypto/sha256" + "fmt" + "os" + "path/filepath" + "reflect" + "strings" + "testing" + + "github.com/research-engineering/agentic-proofkit/internal/kernel/cliexec" +) + +func TestChangeInputGuideIsLazyAndExecutable(t *testing.T) { + packet, help := receiptHelpTemplate(t, "change", "plan") + if len(help) > 10<<10 { + t.Fatal("current-subject help exceeds its bounded context") + } + for _, boundary := range []string{ + "does not read", "Do not hash only IDs", "source-qualified pairs", + "required consumer check", "not authenticated approval", "empty prefix reviews architecture", + } { + if !strings.Contains(help, boundary) { + t.Fatalf("guide lost boundary %q", boundary) + } + } + code, output, diagnostic := executeAgentWorkflowCLI(t, []string{"change", "plan", "--input", "-"}, bytes.NewReader(adoptionHelpJSON(t, packet)), PresentationCapabilities{}) + if code != 1 || output != "" || diagnostic == "" { + t.Fatal("unfilled template fabricated an admissible assessment") + } + for _, carrier := range []struct{ profile, python string }{ + {cliexec.ProfilePath, ""}, {cliexec.ProfileNPMOffline, ""}, {cliexec.ProfilePythonModule, "/example/python 3"}, + } { + renderer, err := cliexec.AdmitLauncherProfile(carrier.profile, carrier.python) + if err != nil { + t.Fatal(err) + } + descriptor, _ := commandDescriptorFor("change-workflow-plan") + got := guideCommands(t, commandUsageWithRenderer(descriptor, renderer), "Current-subject review input guide:", renderer) + if !reflect.DeepEqual(got, [][]string{{"change", "plan", "--input", ""}}) { + t.Fatalf("guide command is not carrier-bound: %v", got) + } + } + for _, args := range [][]string{{"help"}, {"help", "families"}, {"native-evidence-guidance"}, {"changed-path-set", "--help"}} { + code, output, diagnostic := executeAgentWorkflowCLI(t, args, panicReader{}, PresentationCapabilities{}) + if code != 0 || diagnostic != "" || strings.Contains(output, "Current-subject review input guide:") { + t.Fatal("current-subject template must remain demand-loaded") + } + } +} + +func TestChangeGuideActualFilesInvalidateOldAssessment(t *testing.T) { + template, _ := receiptHelpTemplate(t, "change", "plan") + // This finite consumer owns these inputs. It is not a universal dependency scanner. + files := map[string]string{ + "meaning.json": `{"namespace":"alpha","requirementId":"REQ-ONE","invariant":"Reject empty input","scenarioId":"empty","scenarioContext":"empty string"}`, + "bindings.json": `{"witnessId":"native.one","path":"request.test.ts","selector":"test_empty"}`, + "test.ts": `assert.equal(normalize(""), null);`, + "helper.ts": `export const normalize = value => value || null;`, + "command.json": `["node","--test","request.test.ts"]`, + "runtime.json": `{"environment":"local-node","toolchain":"node-fixture-1"}`, + "policy.json": `{"receiptKind":"fixture.native","requireCurrent":true}`, + } + root := t.TempDir() + write := func(name, value string) { + t.Helper() + if err := os.WriteFile(filepath.Join(root, name), []byte(value), 0600); err != nil { + t.Fatal(err) + } + } + for name, value := range files { + write(name, value) + } + // Structured fixtures have JSON value semantics; native code is byte-sensitive. + current := func() string { + t.Helper() + values := map[string]any{} + for name := range files { + data, err := os.ReadFile(filepath.Join(root, name)) + if err != nil { + t.Fatal(err) + } + if strings.HasSuffix(name, ".json") { + values[name] = decodeCLIJSON(t, string(data)) + } else { + values[name] = string(data) + } + } + return fmt.Sprintf("sha256:%x", sha256.Sum256(adoptionHelpJSON(t, values))) + } + baseline := current() + checkpoint := func(subject, assessment string) map[string]any { + packet := cloneMap(t, template) + value := packet["checkpoint"].(map[string]any) + value["subjectDigest"], value["assessmentSubjectDigest"] = subject, assessment + refs := packet["contextRefs"].([]any) + refs[0].(map[string]any)["subjectDigest"] = fmt.Sprintf("sha256:%x", sha256.Sum256([]byte("fixture owner policy"))) + refs[1].(map[string]any)["subjectDigest"] = subject + return packet + } + invoke := func(packet map[string]any, wantCode int, wantError string) map[string]any { + t.Helper() + code, output, diagnostic := executeAgentWorkflowCLI(t, []string{"change", "plan", "--input", "-"}, bytes.NewReader(adoptionHelpJSON(t, packet)), PresentationCapabilities{}) + if code != wantCode || (wantError != "" && !strings.Contains(diagnostic, wantError)) || (wantError == "" && diagnostic != "") { + t.Fatalf("unexpected checkpoint result: %d %q %q", code, output, diagnostic) + } + if wantCode != 0 { + if output != "" { + t.Fatal("rejected checkpoint emitted a success packet") + } + return nil + } + return decodeCLIJSON(t, output).(map[string]any) + } + prior := checkpoint(baseline, baseline) + action := invoke(prior, 0, "") + if action["action"] != "accept_stage" { + t.Fatalf("unchanged reviewed subject not accepted: %v", action) + } + // A public consumer applies the actual returned delta, without internal Go APIs. + merged := cloneMap(t, prior) + for key, value := range action["successorStateDelta"].(map[string]any) { + merged[key] = value + } + if next := invoke(merged, 0, ""); next["activeStageId"] != "design" { + t.Fatalf("merged successor did not reach design: %v", next) + } + mutations := []struct{ name, file, before, after string }{ + {"namespace", "meaning.json", "alpha", "beta"}, + {"requirement", "meaning.json", "REQ-ONE", "REQ-TWO"}, + {"invariant", "meaning.json", "Reject empty input", "Accept empty input"}, + {"scenario", "meaning.json", `"scenarioId":"empty"`, `"scenarioId":"blank"`}, + {"scenario-context", "meaning.json", "empty string", "whitespace"}, + {"witness", "bindings.json", "native.one", "native.two"}, + {"path", "bindings.json", "request.test.ts", "other.test.ts"}, + {"selector", "bindings.json", "test_empty", "test_preserve"}, + {"assertion", "test.ts", "null", "true"}, + {"helper", "helper.ts", "null", "true"}, + {"argv", "command.json", "request.test.ts", "other.test.ts"}, + {"environment", "runtime.json", "local-node", "remote-node"}, + {"toolchain", "runtime.json", "node-fixture-1", "node-fixture-2"}, + {"receipt-policy", "policy.json", "true", "false"}, + } + for _, mutation := range mutations { + t.Run(mutation.name, func(t *testing.T) { + before := files[mutation.file] + after := strings.Replace(before, mutation.before, mutation.after, 1) + if before == after { + t.Fatal("mutation failed to change the intended operand") + } + write(mutation.file, after) + defer write(mutation.file, before) + digest := current() + if digest == baseline { + t.Fatal("actual semantic change did not invalidate the current subject") + } + invoke(checkpoint(digest, baseline), 1, "proofkit.workflow.assessment_digest_mismatch") + if got := invoke(checkpoint(digest, digest), 0, ""); got["action"] != "accept_stage" { + t.Fatal("matching retained assessment is not accepted") + } + // CLI admits declared equality, not files. The consumer must recompute. + invoke(prior, 0, "") + if prior["checkpoint"].(map[string]any)["subjectDigest"] == digest { + t.Fatal("consumer failed to detect all-old caller hashes") + } + }) + } + write("unrelated.ts", "independent scope changed") + write("meaning.json", "\n "+files["meaning.json"]+"\n") + if current() != baseline { + t.Fatal("unaffected scope or JSON layout invalidated semantic subject") + } + invoke(checkpoint(current(), baseline), 0, "") +} diff --git a/internal/app/cli_contract_test.go b/internal/app/cli_contract_test.go index b913826e..c729db07 100644 --- a/internal/app/cli_contract_test.go +++ b/internal/app/cli_contract_test.go @@ -24,7 +24,7 @@ import ( ) const ( - cliContractPublicABISHA256 = "2867ea2c8caf03e5b88fa46cabee0697e781452af2a8049e70660796730d0b66" + cliContractPublicABISHA256 = "31d82294be58a80cdef00a33a554cfeeb17a03903083ebf56a38a994d7f2def9" maxAggregateFileReadBytesForContractTest = 64 << 20 maxPackageManifestBytesForContractTest = 256 << 10 maxSourceFileBytesForContractTest = 8 << 20 diff --git a/internal/app/command_contract_generated.go b/internal/app/command_contract_generated.go index cf3f8318..7c154214 100644 --- a/internal/app/command_contract_generated.go +++ b/internal/app/command_contract_generated.go @@ -1,7 +1,7 @@ // Code generated by internal/tools/commandcontractgen; DO NOT EDIT. package app -const commandContractSourceSHA256 = "40e21bb074eea37dba970d08cf06e1c5ee0ec1c1d7404fad1e7e28490a3924c4" +const commandContractSourceSHA256 = "7bb0e36255f4b08eca5f067f133b16b5a35111789ce1a46eccf63adccf2cf72c" type generatedCommandContractMetadata struct { InputContractSHA256 string @@ -12,19 +12,19 @@ type generatedCommandContractMetadata struct { } var generatedCommandContractMetadataByName = map[string]generatedCommandContractMetadata{ - "adopt-materialize-apply": {InputContractSHA256: "sha256:ff3aee6b2420c04d19afdf3a72ef2a73b731f25cc1abcb0f3fe1ffd0fc9ed06b", InputSchemaSummary: []string{"schemaVersion=1", "owner-admitted adoption plan, requirement sources, proof bindings, and direct test inventory", "root-shape-only definition proofkit.adoption-materialization.apply-input.v1.root-shape; nested fields, types, cardinalities, and cross-record closure remain native-owner claims"}, OutputContractSHA256: "sha256:0b6422c73221f2d45ab30c523bd467f8ca7e5871ad299ef4a4a65d2bb2d3f2b6", FlagChoices: map[string][]string{"--color": []string{"auto", "never"}, "--format": []string{"json", "text"}}, RouteTokens: []string{"adopt", "materialize", "apply"}}, - "adopt-materialize-plan": {InputContractSHA256: "sha256:484d8d867ff1080d14f14c9b82c9e02ce0bb10ded7713b8098b5a2f5128fefc2", InputSchemaSummary: []string{"schemaVersion=1", "owner-admitted adoption plan, requirement sources, proof bindings, and direct test inventory", "root-shape-only definition proofkit.adoption-materialization.plan-input.v1.root-shape; nested fields, types, cardinalities, and cross-record closure remain native-owner claims"}, OutputContractSHA256: "sha256:96f5947637a274bd4995989da657b7091ca3c6a3dea4b4839da61ed727537cd5", FlagChoices: map[string][]string{"--color": []string{"auto", "never"}, "--format": []string{"json", "text"}}, RouteTokens: []string{"adopt", "materialize", "plan"}}, - "adopt-materialize-recover": {InputContractSHA256: "", InputSchemaSummary: []string(nil), OutputContractSHA256: "sha256:7f4260b4997bcefefee18a1a43b02f9955e064026e034c20fde641f163d07a9e", FlagChoices: map[string][]string{"--action": []string{"resume", "rollback"}, "--color": []string{"auto", "never"}, "--format": []string{"json", "text"}}, RouteTokens: []string{"adopt", "materialize", "recover"}}, + "adopt-materialize-apply": {InputContractSHA256: "sha256:ff3aee6b2420c04d19afdf3a72ef2a73b731f25cc1abcb0f3fe1ffd0fc9ed06b", InputSchemaSummary: []string{"schemaVersion=1", "owner-admitted adoption plan, requirement sources, proof bindings, and direct test inventory", "root-shape-only definition proofkit.adoption-materialization.apply-input.v1.root-shape; nested fields, types, cardinalities, and cross-record closure remain native-owner claims"}, OutputContractSHA256: "sha256:d9462227e1539ed48afe3ca3df16df427e989ccf060ec46b3a78e76bec4ade48", FlagChoices: map[string][]string{"--color": []string{"auto", "never"}, "--format": []string{"json", "text"}}, RouteTokens: []string{"adopt", "materialize", "apply"}}, + "adopt-materialize-plan": {InputContractSHA256: "sha256:484d8d867ff1080d14f14c9b82c9e02ce0bb10ded7713b8098b5a2f5128fefc2", InputSchemaSummary: []string{"schemaVersion=1", "owner-admitted adoption plan, requirement sources, proof bindings, and direct test inventory", "root-shape-only definition proofkit.adoption-materialization.plan-input.v1.root-shape; nested fields, types, cardinalities, and cross-record closure remain native-owner claims"}, OutputContractSHA256: "sha256:465534bc2676a61afae85278b27571879dfc8e18920935f2fc23f8e622061af9", FlagChoices: map[string][]string{"--color": []string{"auto", "never"}, "--format": []string{"json", "text"}}, RouteTokens: []string{"adopt", "materialize", "plan"}}, + "adopt-materialize-recover": {InputContractSHA256: "", InputSchemaSummary: []string(nil), OutputContractSHA256: "sha256:2bbc8a16190cc567296ba1260a7e468465b55e19a7f825044d7ab5b43a884afd", FlagChoices: map[string][]string{"--action": []string{"resume", "rollback"}, "--color": []string{"auto", "never"}, "--format": []string{"json", "text"}}, RouteTokens: []string{"adopt", "materialize", "recover"}}, "adopt-plan": {InputContractSHA256: "", InputSchemaSummary: []string(nil), OutputContractSHA256: "sha256:ba2bb3ce147ac37bde035334e0058820339b36de2a0ae270a9e5dbe00e6a3e6d", FlagChoices: map[string][]string{"--color": []string{"auto", "never"}, "--format": []string{"json", "text"}, "--mode": []string{"audit-from-code", "code-baseline", "fresh"}, "--stack": []string{"agentic_runtime_repo", "generated_docs_contract_repo", "python_service", "python_typescript_service", "typescript_monorepo", "typescript_workspace"}}, RouteTokens: []string{"adopt", "plan"}}, "adoption-checklist": {InputContractSHA256: "sha256:4e6c4c9b369279837a5894c0b3f842a411dce529b91c91cb2d4ec63eb5ee4c2c", InputSchemaSummary: []string{"schemaVersion=1", "root-shape-only definition proofkit.adoption-checklist.input.v1.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:9d0d0e60f0935407fd31007d8502459663eb4c7228dc5e3c7727ae2c9907bdc9", FlagChoices: map[string][]string{}, RouteTokens: []string{"adoption-checklist"}}, "adoption-contract-envelope": {InputContractSHA256: "sha256:c310214676ff4b6f536a5bc9d687f681a7e71f73d7a03ac932707d8cd3905cdf", InputSchemaSummary: []string{"schemaVersion=2", "root-shape-only definition proofkit.adoption-contract-envelope.input.v2.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:3efb2c5161fee16fd8ac6a40dcb6d9c41fbc23e468f60621436ae9e8076e0950", FlagChoices: map[string][]string{}, RouteTokens: []string{"adoption-contract-envelope"}}, "adoption-doctor": {InputContractSHA256: "sha256:efa9acfe32bff07f56d9dc9902530df2979794289bc2f7f547f7a108a7dd0f35", InputSchemaSummary: []string{"schemaVersion=1", "root-shape-only definition proofkit.adoption-doctor.input.v1.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:8fdfc6608f197e633f042f20031ae1014872a90aa3daa66885ffcaddca994766", FlagChoices: map[string][]string{}, RouteTokens: []string{"adoption-doctor"}}, "adoption-workflow-plan": {InputContractSHA256: "sha256:b32ae67179d7b6dcf1ea66cb6b2b2691c8367ce2e2be367619b65973166da55c", InputSchemaSummary: []string{"schemaVersion=1", "root-shape-only definition proofkit.adoption-workflow-plan.input.v1.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:8d64cb53ebd0307e3cebc3435286a3d2a1ee8a0ad6f7514fc0fb3285db0f565b", FlagChoices: map[string][]string{}, RouteTokens: []string{"adoption-workflow-plan"}}, - "agent-route": {InputContractSHA256: "sha256:c00e832b4e9eac6b858eec46e810431c0a5c9f56c5c50f055f39ee024f50014c", InputSchemaSummary: []string{"availableInputs", "browserMode", "goal", "knownChangedPaths", "mode", "nonClaims", "observedReports", "openBrowser", "routeId", "schemaVersion", "root-shape-only definition proofkit.agent-route.input.v2.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:92f47b1f6d2a90d67a98242df788cb857a07c74267bdff2d99638ecd319e3122", FlagChoices: map[string][]string{}, RouteTokens: []string{"agent-route"}}, + "agent-route": {InputContractSHA256: "sha256:c00e832b4e9eac6b858eec46e810431c0a5c9f56c5c50f055f39ee024f50014c", InputSchemaSummary: []string{"availableInputs", "browserMode", "goal", "knownChangedPaths", "mode", "nonClaims", "observedReports", "openBrowser", "routeId", "schemaVersion", "root-shape-only definition proofkit.agent-route.input.v2.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:e59dada1926e3385793cdcb0a8b9cf8110b8f995b785c27ac397b60ba972b571", FlagChoices: map[string][]string{}, RouteTokens: []string{"agent-route"}}, "binding-partition": {InputContractSHA256: "sha256:366ad082045af52b2ac6604f18626d0f285b2db73b45d9a82687b8d3b0d2b3fd", InputSchemaSummary: []string{"schemaVersion=1", "root-shape-only definition proofkit.binding-partition.input.v1.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:52840879e13a00ef9a4abaad6cdb33000511674d5f9003fb56f387fdf58fadc8", FlagChoices: map[string][]string{}, RouteTokens: []string{"binding-partition"}}, "branch-authority": {InputContractSHA256: "sha256:8a3ed74978898593fbdbf1f7fa684dae450fbd9019edcd60d07f818d63363ed4", InputSchemaSummary: []string{"schemaVersion=1", "root-shape-only definition proofkit.branch-authority.input.v1.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:3c7dc74842299b92cd5baf57cc8666e9415963091359e5faf654e28da89561f1", FlagChoices: map[string][]string{}, RouteTokens: []string{"branch-authority"}}, "capability-map-admission": {InputContractSHA256: "sha256:36025145e1be04f8da9baccd2161b4ccf04f5426e95084d9cccc01802970e29d", InputSchemaSummary: []string{"schemaVersion=1", "root-shape-only definition proofkit.capability-map-admission.input.v1.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:5100e56075f50435605264c6a835a60f24f6790479e2b4c623d359f1e7e78690", FlagChoices: map[string][]string{}, RouteTokens: []string{"capability-map-admission"}}, - "change-workflow-plan": {InputContractSHA256: "sha256:e3124fc636b7f66b24daf8e1435cea11da15a741abeabe0cc3d3890b13c71625", InputSchemaSummary: []string{"schemaVersion=1", "root-shape-only definition proofkit.change-workflow-plan.input.v1.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:cd035e9b71d83c341b1a937a18699fd727cb4b0d694983d715b064292ae4d8bd", FlagChoices: map[string][]string{"--color": []string{"auto", "never"}, "--format": []string{"json", "text"}}, RouteTokens: []string{"change", "plan"}}, + "change-workflow-plan": {InputContractSHA256: "sha256:fe64cfbd2f8f9c74ce822aaf7acaabb53b6dcef9f193ac3c25ad79936c4f5afd", InputSchemaSummary: []string{"schemaVersion=1", "root-shape-only definition proofkit.change-workflow-plan.input.v1.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:c81afa10bb91cd08c36d87ece85113e7acc87a038183ed609c47845ceeafabfd", FlagChoices: map[string][]string{"--color": []string{"auto", "never"}, "--format": []string{"json", "text"}}, RouteTokens: []string{"change", "plan"}}, "changed-path-set": {InputContractSHA256: "sha256:8fe97426a58969e3e8dcbd52ed44540666b4de6be0487e8a3bc5088ae9c0f933", InputSchemaSummary: []string{"schemaVersion=1", "root-shape-only definition proofkit.changed-path-set.input.v1.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:abccdbf78e67f633ce49c34e8849c03f08ce42fa934a4c68969720c5045bf593", FlagChoices: map[string][]string{}, RouteTokens: []string{"changed-path-set"}}, "completion-criteria": {InputContractSHA256: "sha256:99c49c44b001e40383787e4c55f66621b8a8315f09635f1baf2326dc09bec4e6", InputSchemaSummary: []string{"schemaVersion=1", "root-shape-only definition proofkit.completion-criteria.input.v1.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:c90bb9605c7a22914104701a068dded510534bdeb60f4d601555d46c2d3d8a6d", FlagChoices: map[string][]string{}, RouteTokens: []string{"completion-criteria"}}, "conformance-profile": {InputContractSHA256: "sha256:10857de4cea06702bb4d35580046275d4b1f88821d287a4c57dabc187bda954e", InputSchemaSummary: []string{"schemaVersion=2", "root-shape-only definition proofkit.conformance-profile.input.v2.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:4654015b8b9055080c1d5528773462fab3fe81d40c7f3b9870e5dbec4dc98caf", FlagChoices: map[string][]string{}, RouteTokens: []string{"conformance-profile"}}, @@ -38,19 +38,19 @@ var generatedCommandContractMetadataByName = map[string]generatedCommandContract "gradual-adoption-guidance": {InputContractSHA256: "sha256:4752cbac81c864cb3e18a39facfd666a9707314233d54798c7f71e67d7f2800c", InputSchemaSummary: []string{"schemaVersion=1", "root-shape-only definition proofkit.gradual-adoption-guidance.input.v1.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:171fed4bb8d32a47fc5ec49796f5b0b55ed666feaccc2fbbfeb12da31d80ecc9", FlagChoices: map[string][]string{}, RouteTokens: []string{"gradual-adoption-guidance"}}, "help": {InputContractSHA256: "", InputSchemaSummary: []string(nil), OutputContractSHA256: "", FlagChoices: map[string][]string{}, RouteTokens: []string{"help"}}, "impact": {InputContractSHA256: "sha256:41d3107414837955ee408d5ce94949a4c1a6b76f6949e6c1dc224bd06f6b09bc", InputSchemaSummary: []string{"schemaVersion=2", "root-shape-only definition proofkit.impact.input.v2.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:73066e9a5ca48f21936111ffb7223900fb629875997f4e7b16d7fef9c4177972", FlagChoices: map[string][]string{}, RouteTokens: []string{"impact"}}, - "integration-apply": {InputContractSHA256: "", InputSchemaSummary: []string(nil), OutputContractSHA256: "sha256:65af409248c6413f9ce22e436cde242b3875451dcd8d761ea9d464f61c740a1a", FlagChoices: map[string][]string{"--color": []string{"auto", "never"}, "--format": []string{"json", "text"}, "--operation": []string{"install", "remove", "update"}, "--tool": []string{"claude", "codex"}}, RouteTokens: []string{"integration", "apply"}}, - "integration-check": {InputContractSHA256: "", InputSchemaSummary: []string(nil), OutputContractSHA256: "sha256:447db19dd53276746654d272f300fd819e54ce037382d6bf983b0c07b524b66b", FlagChoices: map[string][]string{"--format": []string{"json", "text"}, "--tool": []string{"claude", "codex"}}, RouteTokens: []string{"integration", "check"}}, - "integration-plan": {InputContractSHA256: "", InputSchemaSummary: []string(nil), OutputContractSHA256: "sha256:76359c885ae29c964c96f59fd626d7c576d1d75fb851f3993de841b9cdc2cee9", FlagChoices: map[string][]string{"--color": []string{"auto", "never"}, "--format": []string{"json", "text"}, "--operation": []string{"install", "remove", "update"}, "--tool": []string{"claude", "codex"}}, RouteTokens: []string{"integration", "plan"}}, - "integration-recover": {InputContractSHA256: "", InputSchemaSummary: []string(nil), OutputContractSHA256: "sha256:880c85b05aa164985d4eee01352414d6a938b50bf46cdd1e31483ed609571d2b", FlagChoices: map[string][]string{"--action": []string{"resume", "rollback"}, "--color": []string{"auto", "never"}, "--format": []string{"json", "text"}}, RouteTokens: []string{"integration", "recover"}}, - "integration-source": {InputContractSHA256: "", InputSchemaSummary: []string(nil), OutputContractSHA256: "sha256:128d4a199f97dee063766b42156493eb19d267455df83f07613e3b052daf3f4c", FlagChoices: map[string][]string{"--format": []string{"json", "text"}, "--tool": []string{"claude", "codex"}}, RouteTokens: []string{"integration", "source"}}, + "integration-apply": {InputContractSHA256: "", InputSchemaSummary: []string(nil), OutputContractSHA256: "sha256:29d38f47080100f3b2c0d93ab76173dc6ba9599d13130c8b3bee960898cc33d3", FlagChoices: map[string][]string{"--color": []string{"auto", "never"}, "--format": []string{"json", "text"}, "--operation": []string{"install", "remove", "update"}, "--tool": []string{"claude", "codex"}}, RouteTokens: []string{"integration", "apply"}}, + "integration-check": {InputContractSHA256: "", InputSchemaSummary: []string(nil), OutputContractSHA256: "sha256:5438119b425a58e777dfad3f028945ec8be1d3ff21d1fab49534d1b666767c2d", FlagChoices: map[string][]string{"--format": []string{"json", "text"}, "--tool": []string{"claude", "codex"}}, RouteTokens: []string{"integration", "check"}}, + "integration-plan": {InputContractSHA256: "", InputSchemaSummary: []string(nil), OutputContractSHA256: "sha256:c5d95c7fd90d8560312f2c3dea032cbdafaa74cedfe1e845012c9dcd68d96b16", FlagChoices: map[string][]string{"--color": []string{"auto", "never"}, "--format": []string{"json", "text"}, "--operation": []string{"install", "remove", "update"}, "--tool": []string{"claude", "codex"}}, RouteTokens: []string{"integration", "plan"}}, + "integration-recover": {InputContractSHA256: "", InputSchemaSummary: []string(nil), OutputContractSHA256: "sha256:0d368195d7989c2342b9b5c20a2ef2ac2a0c7be847d7352fe81ac7c4d7bfeeff", FlagChoices: map[string][]string{"--action": []string{"resume", "rollback"}, "--color": []string{"auto", "never"}, "--format": []string{"json", "text"}}, RouteTokens: []string{"integration", "recover"}}, + "integration-source": {InputContractSHA256: "", InputSchemaSummary: []string(nil), OutputContractSHA256: "sha256:bc2990004831538f6da693dabeebc08e3cad8acd3ff927325443265d2dec4dec", FlagChoices: map[string][]string{"--format": []string{"json", "text"}, "--tool": []string{"claude", "codex"}}, RouteTokens: []string{"integration", "source"}}, "json-report-cli-adapter-source": {InputContractSHA256: "", InputSchemaSummary: []string(nil), OutputContractSHA256: "sha256:6c3dd1c8507a90e055cf2c886089446d8560ff3e0d3ca9cc6360a3377d2d85da", FlagChoices: map[string][]string{}, RouteTokens: []string{"json-report-cli-adapter-source"}}, "migration-parity-admission": {InputContractSHA256: "sha256:0b36c0e68da3b857dac4b13e7b3bd523052459106133aa8c908a4352682e6c05", InputSchemaSummary: []string{"schemaVersion=1", "paritySetId", "sourceProofOwners[]", "targetProofkitRefs[]", "parityRecords[]", "nonClaims[]", "root-shape-only definition proofkit.migration-parity-admission.input.v1.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:8e0f8af2b205817f018b0fe133fe789661caa29007695e036bfcab63c1830f47", FlagChoices: map[string][]string{}, RouteTokens: []string{"migration-parity-admission"}}, "migration-plan": {InputContractSHA256: "sha256:58a62759a634101ce2ca9218184175134bbe5633328e1b23797b94c19fc9b11a", InputSchemaSummary: []string{"schemaVersion=1", "migrationId", "sourceProofOwners[]", "targetProofkitRefs[]", "parityEvidenceRefs[]", "retainedOwners[]", "retirementCandidates[]", "followUpCommands[]", "nonClaims[]", "root-shape-only definition proofkit.migration-plan.input.v1.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:f14f0381e9dc241357c346315b95b03ef5b23f1d1bbc3b00f111fbe1515ed3ff", FlagChoices: map[string][]string{}, RouteTokens: []string{"migration-plan"}}, - "native-evidence-guidance": {InputContractSHA256: "", InputSchemaSummary: []string(nil), OutputContractSHA256: "sha256:fe02404bbd97a6fc56911441688e74db4a45f3acacfbcbcfe22b5f1073758640", FlagChoices: map[string][]string{"--color": []string{"auto", "never"}, "--format": []string{"json", "text"}}, RouteTokens: []string{"native-evidence-guidance"}}, + "native-evidence-guidance": {InputContractSHA256: "", InputSchemaSummary: []string(nil), OutputContractSHA256: "sha256:4cfb35b6a3361c5d9ab12c20e6289688471363b987ab3842dbc4439e2fd1dc8a", FlagChoices: map[string][]string{"--color": []string{"auto", "never"}, "--format": []string{"json", "text"}}, RouteTokens: []string{"native-evidence-guidance"}}, "next": {InputContractSHA256: "", InputSchemaSummary: []string(nil), OutputContractSHA256: "sha256:7394789ca6a1a275662109980d82d58f3586e6afb2689d0b3e54acb14d067c21", FlagChoices: map[string][]string{"--color": []string{"auto", "never"}, "--format": []string{"json", "text"}}, RouteTokens: []string{"next"}}, "obligation-decision": {InputContractSHA256: "sha256:1dea2ed5c5066451d6d49b815cea99df2cdae2ef05d42fed16c8aeb45eb7f445", InputSchemaSummary: []string{"schemaVersion=1", "root-shape-only definition proofkit.obligation-decision.input.v1.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:96dc074f611bcc12e511bc803c548e4df623e2de869d3add29a3ea6386e04330", FlagChoices: map[string][]string{}, RouteTokens: []string{"obligation-decision"}}, "package-runtime-dependency-admission": {InputContractSHA256: "sha256:fc85887af9b8fcd899d245f0db30b2f2f68609822fc268126bf999082bb4115f", InputSchemaSummary: []string{"schemaVersion=1", "reportId", "expectedDependencySpec", "expectedLockfileIntegrity", "expectedPackageName", "expectedPackageVersion", "admissibleLocations{}", "packageResolution{}", "nonClaims[]", "root-shape-only definition proofkit.package-runtime-dependency-admission.input.v1.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:c012032e8c8212fd50bc2e85669cc610609ca2124ebc992c9e88f44a1ad2d5fc", FlagChoices: map[string][]string{}, RouteTokens: []string{"package-runtime-dependency-admission"}}, - "pilot-admission": {InputContractSHA256: "sha256:a1d9116ce619f7d705349ff4ae44c0f4399a281ebaa9e7d62ea304ac57af59ba", InputSchemaSummary: []string{"schemaVersion=2", "root-shape-only definition proofkit.pilot-admission.input.v2.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:66c6995438128545e05d535484e399c5bf11fb0b257e156cf389505fdcc73025", FlagChoices: map[string][]string{}, RouteTokens: []string{"pilot-admission"}}, + "pilot-admission": {InputContractSHA256: "sha256:a1d9116ce619f7d705349ff4ae44c0f4399a281ebaa9e7d62ea304ac57af59ba", InputSchemaSummary: []string{"schemaVersion=2", "root-shape-only definition proofkit.pilot-admission.input.v2.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:5aa8fe82acbe498c8fb240196d2a0b135ecfa61b0b873e6173cf0947d8631f58", FlagChoices: map[string][]string{}, RouteTokens: []string{"pilot-admission"}}, "producer-policy-self-proof": {InputContractSHA256: "sha256:d48e18826000c8d415f3c44b6c686e1da6ed962ef7ca36c9f705de8c68d034f9", InputSchemaSummary: []string{"schemaVersion=1", "root-shape-only definition proofkit.producer-policy-self-proof.input.v1.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:e82a3989a743f8babc6069f7af82b1dd1ea62bad8dbb18d95e105b36f74e4276", FlagChoices: map[string][]string{}, RouteTokens: []string{"producer-policy-self-proof"}}, "proof-obligation-algebra": {InputContractSHA256: "sha256:4f176b6bc9bdbd0d96d65c071d66447d246665bda7a23269e7927f1d0b80b043", InputSchemaSummary: []string{"schemaVersion=1", "root-shape-only definition proofkit.proof-obligation-algebra.input.v1.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:f9ee9e56b349756c55856a2dab198e1ad85db70a468c38e3aeca73cfe2ed66f6", FlagChoices: map[string][]string{}, RouteTokens: []string{"proof-obligation-algebra"}}, "proof-receipt-admission": {InputContractSHA256: "sha256:8ba257066e276a48de661e52cabd3be194cba31a8a45e082f3b013a5c9a9120c", InputSchemaSummary: []string{"schemaVersion=1", "root-shape-only definition proofkit.proof-receipt-admission.input.v1.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:40fd1426468aae342029e10dcc950e6a24142f9a09f0b3d4513622c7a2bff75c", FlagChoices: map[string][]string{}, RouteTokens: []string{"proof-receipt-admission"}}, @@ -65,7 +65,7 @@ var generatedCommandContractMetadataByName = map[string]generatedCommandContract "rendered-artifact-freshness": {InputContractSHA256: "sha256:be4f53ef1307b4c16bb15a945f8021473b5a215961f3d38f6f591a0240da91f3", InputSchemaSummary: []string{"schemaVersion=1", "root-shape-only definition proofkit.rendered-artifact-freshness.input.v1.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:c9a763142d11daca913672b0bab517767d35e275cd7c8ccb2bb360e6fc8f7425", FlagChoices: map[string][]string{}, RouteTokens: []string{"rendered-artifact-freshness"}}, "repo-profile-admission": {InputContractSHA256: "sha256:3a7331d66195dbdc9f672d380efe8fdb9d1d2e36a764b8bc912dccdd81b0e965", InputSchemaSummary: []string{"schemaVersion=1", "root-shape-only definition proofkit.repo-profile-admission.input.v1.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:36d2116fa144aa86d7b9d0ac59b89ad04fb97c85a11f3f65efb7311506761fbd", FlagChoices: map[string][]string{}, RouteTokens: []string{"repo-profile-admission"}}, "repository-inventory": {InputContractSHA256: "", InputSchemaSummary: []string(nil), OutputContractSHA256: "sha256:4a6fc5b5ef55090854e70927494d220afdee0ae234de4f61a720a6018865f02f", FlagChoices: map[string][]string{}, RouteTokens: []string{"repository-inventory"}}, - "requirement-authoring-plan": {InputContractSHA256: "sha256:dd1269ff4b5dcd70ac38c34e7df27b1ca9d31f0f880d84eaf328cbae71c23906", InputSchemaSummary: []string{"schemaVersion=1", "root-shape-only definition proofkit.requirement-authoring-plan.input.v1.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:02377126b5d982362fdf845a9cd12bea4a320965493feb9cd92bc0d4a784b74e", FlagChoices: map[string][]string{}, RouteTokens: []string{"requirement-authoring-plan"}}, + "requirement-authoring-plan": {InputContractSHA256: "sha256:e43149e9aa24f9dfec832bbc5f92b6d419d3903bfde6f4b09198001e291883ee", InputSchemaSummary: []string{"schemaVersion=1", "root-shape-only definition proofkit.requirement-authoring-plan.input.v1.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:0f4fb44df20eae47d4a67ee638c0692069a30fcbc85e1034d49561f2025a08dd", FlagChoices: map[string][]string{}, RouteTokens: []string{"requirement-authoring-plan"}}, "requirement-bindings": {InputContractSHA256: "sha256:f4e9458a2cb69274c0c7a566eb3624c508faff8f140d1b783575c78e17a7c4d8", InputSchemaSummary: []string{"schemaVersion=1", "root-shape-only definition proofkit.requirement-bindings.input.v1.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:7821c7b23ff2c0ca83c64039c22400d90660cad73a60b9afb46829c539c61168", FlagChoices: map[string][]string{}, RouteTokens: []string{"requirement-bindings"}}, "requirement-browser-server": {InputContractSHA256: "sha256:557d9f1e6919a6f40b831fb910340f85cdc0a0619d0c4895098308939a262e6e", InputSchemaSummary: []string{"workspace mode: schemaVersion=2", "workspace mode: workspaceId", "workspace mode: context=proofkit.requirement-context schemaVersion=2 with strict v1 adapter", "workspace mode: diffInput=proofkit.requirement-semantic-diff-input schemaVersion=2 (optional)", "workspace mode: graphInput=proofkit.requirement-traceability-graph-input schemaVersion=2 (optional)", "--session-mode values: browse|one-shot-question", "one-shot-question requires --view workspace --serve --open", "--session-timeout-seconds is 1..7200 and requires one-shot-question", "source|proof|coverage|spec-tree modes retain their owner input contracts", "root-shape-only definition proofkit.requirement-browser-server.input.v3.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:40a4ac0312d4fb921d572817331a73c629ed807caed789296f992f1482e0d932", FlagChoices: map[string][]string{}, RouteTokens: []string{"requirement-browser-server"}}, "requirement-context-compose": {InputContractSHA256: "sha256:0b8d5eace6247fd8fa01ad7372f0395ea6fa10e7f0aa9fe5bab2ff4ed8a69384", InputSchemaSummary: []string{"schemaVersion=1", "catalogId", "specTree.path", "requirementSources[] (non-empty)", "requirementSources[].nodeId", "requirementSources[].path", "expectedSourceDigest (optional sha256 ref)", "proofBinding.path (optional)", "coverage.path (optional)", "exact catalog paths only; no discovery", "root-shape-only definition proofkit.requirement-context-compose.input.v1.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:dd08c6e3e66349019a349049345e64fca3d31459e42fe634e98e9a9ade8101f4", FlagChoices: map[string][]string{}, RouteTokens: []string{"requirement-context-compose"}}, @@ -89,7 +89,7 @@ var generatedCommandContractMetadataByName = map[string]generatedCommandContract "selective-gate-evidence": {InputContractSHA256: "sha256:8aa178ab7ca7c475c23707bc4e15fd3f9f8d57acf6f6dcf279677e7769a45586", InputSchemaSummary: []string{"schemaVersion=1", "root-shape-only definition proofkit.selective-gate-evidence.input.v1.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:723569262bb85d9674b2a78d3bcb6e9f4cab229b71e8c784ff1b804a7fcade71", FlagChoices: map[string][]string{}, RouteTokens: []string{"selective-gate-evidence"}}, "selective-gate-obligation-decision-input": {InputContractSHA256: "sha256:85761fcbc0ea94239d55bf379d0592a6ca814e6612a2d609a651f6cdaf8ca10a", InputSchemaSummary: []string{"schemaVersion=1", "root-shape-only definition proofkit.selective-gate-obligation-decision-input.input.v1.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:ab9dddabe975238d7019266c43350afa2df1a61d4c2eb7bc23afd520b588a2da", FlagChoices: map[string][]string{}, RouteTokens: []string{"selective-gate-obligation-decision-input"}}, "selective-gate-plan": {InputContractSHA256: "sha256:5293a5a4c7d8426cf637e6f8d252095ca0eb1714365bb89bec83307b778c678a", InputSchemaSummary: []string{"schemaVersion=1", "root-shape-only definition proofkit.selective-gate-plan.input.v1.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:d7bffed853af5595af08b03859be01c283a3bdff1b3502d94ddc190889977647", FlagChoices: map[string][]string{}, RouteTokens: []string{"selective-gate-plan"}}, - "self-check": {InputContractSHA256: "sha256:092ea3fb5c79214b1ed8e8573b59f90bd736fa62797a19f55da92fdaaa519eb6", InputSchemaSummary: []string{"schemaVersion=1", "root-shape-only definition proofkit.self-check.input.v1.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:455db6d1517cd174d84534473375c2f45e8b4ce4dcd78db89da46a5bd215cea8", FlagChoices: map[string][]string{}, RouteTokens: []string{"self-check"}}, + "self-check": {InputContractSHA256: "sha256:ec19af40f151f3b316784910c08dfa415672e080f270d07979938794de25dd19", InputSchemaSummary: []string{"schemaVersion=1", "root-shape-only definition proofkit.self-check.input.v1.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:c7dc1f2eacb8077895c8d29c5f496ef053b89ae26e145acbc80b1388fb1c7020", FlagChoices: map[string][]string{}, RouteTokens: []string{"self-check"}}, "spec-overview-claims": {InputContractSHA256: "sha256:2490dcd34ba7485e13f8f33e8a288a0463c4c52cc6b0d82c57777466927e49a4", InputSchemaSummary: []string{"schemaVersion=1", "root-shape-only definition proofkit.spec-overview-claims.input.v1.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:554f3a7020e9820ccb90672629fd769c52b2f298f356040aa3b0a817666cbfbf", FlagChoices: map[string][]string{}, RouteTokens: []string{"spec-overview-claims"}}, "spec-proof-bundle-admission": {InputContractSHA256: "sha256:2dd04eb5ad2bd26758b434c2f427347efd491dab5a50b1197c8a9f98113be1b5", InputSchemaSummary: []string{"schemaVersion=1", "root-shape-only definition proofkit.spec-proof-bundle-admission.input.v1.root-shape; nested fields, types, and cardinalities are non-claims"}, OutputContractSHA256: "sha256:a6ac0c69d19caf97e9a8c95808b83cdb3f908720923739aa59ef646d27c90870", FlagChoices: map[string][]string{}, RouteTokens: []string{"spec-proof-bundle-admission"}}, "stack-preset": {InputContractSHA256: "", InputSchemaSummary: []string(nil), OutputContractSHA256: "sha256:ef5920f363a4a96dcac308ea8412260a06e64ba4876460a369aefb8983130a9d", FlagChoices: map[string][]string{"--preset": []string{"agentic_runtime_repo", "generated_docs_contract_repo", "python_service", "python_typescript_service", "typescript_monorepo", "typescript_workspace"}}, RouteTokens: []string{"stack-preset"}}, diff --git a/internal/app/command_help.go b/internal/app/command_help.go index 72265230..ecaab6ba 100644 --- a/internal/app/command_help.go +++ b/internal/app/command_help.go @@ -7,6 +7,7 @@ import ( "github.com/research-engineering/agentic-proofkit/internal/command/adoptionmaterialization" "github.com/research-engineering/agentic-proofkit/internal/command/capabilitymapadmission" + "github.com/research-engineering/agentic-proofkit/internal/command/changeworkflowplan" "github.com/research-engineering/agentic-proofkit/internal/command/nativeevidenceguidance" "github.com/research-engineering/agentic-proofkit/internal/command/proofreceiptadmission" "github.com/research-engineering/agentic-proofkit/internal/command/receiptcurrentnessscope" @@ -123,6 +124,9 @@ func commandUsageWithRenderer(descriptor commandDescriptor, renderer cliexec.Ren if descriptor.name == "requirement-authoring-plan" { lines = append(lines, "", strings.TrimSuffix(requirementauthoringplan.InputGuide(renderer), "\n")) } + if descriptor.name == "change-workflow-plan" { + lines = append(lines, "", strings.TrimSuffix(changeworkflowplan.InputGuide(renderer), "\n")) + } if descriptor.name == "proof-receipt-admission" { lines = append(lines, "", strings.TrimSuffix(proofreceiptadmission.InputGuide(renderer), "\n")) } diff --git a/internal/app/receipt_input_guide_test.go b/internal/app/receipt_input_guide_test.go index 9de4feb8..909e8714 100644 --- a/internal/app/receipt_input_guide_test.go +++ b/internal/app/receipt_input_guide_test.go @@ -17,10 +17,10 @@ import ( "github.com/research-engineering/agentic-proofkit/internal/kernel/cliexec" ) -func receiptHelpTemplate(t *testing.T, command string) (map[string]any, string) { +func receiptHelpTemplate(t *testing.T, command ...string) (map[string]any, string) { t.Helper() var canonical string - for _, args := range [][]string{{command, "--help"}, {command, "-h"}, {"help", command}} { + for _, args := range [][]string{append(append([]string{}, command...), "--help"), append(append([]string{}, command...), "-h"), append([]string{"help"}, command...)} { code, output, diagnostic := executeAgentWorkflowCLI(t, args, panicReader{}, PresentationCapabilities{}) if code != 0 || diagnostic != "" || len(output) > 12<<10 || strings.Contains(output, "\x1b[") { t.Fatalf("help is not bounded, input-free plain text: %v, %d, %q", args, code, diagnostic) @@ -325,7 +325,7 @@ func TestNativeTraceabilityGuideIsLazyAndCarrierBound(t *testing.T) { actualLazy = append(actualLazy, line) } } - for _, command := range [][]string{{"adopt", "materialize", "plan", "--help"}, {"requirement-authoring-plan", "--help"}, {"requirement-coverage-input-compose", "--help"}, {"proof-receipt-admission", "--help"}, {"spec-proof-bundle-admission", "--help"}, {"receipt-currentness-scope", "--help"}, {"requirement-impact-input-compose", "--help"}} { + for _, command := range [][]string{{"adopt", "materialize", "plan", "--help"}, {"requirement-authoring-plan", "--help"}, {"requirement-coverage-input-compose", "--help"}, {"proof-receipt-admission", "--help"}, {"spec-proof-bundle-admission", "--help"}, {"receipt-currentness-scope", "--help"}, {"requirement-impact-input-compose", "--help"}, {"change", "plan", "--help"}} { expectedLazy = append(expectedLazy, " "+renderer.DisplayCommand(command...)) code, output, diagnostic := executeAgentWorkflowCLI(t, command, panicReader{}, PresentationCapabilities{}) if code != 0 || output == "" || diagnostic != "" { diff --git a/internal/command/changeworkflowplan/dependency_test.go b/internal/command/changeworkflowplan/dependency_test.go index f5d85fbe..a8c8da18 100644 --- a/internal/command/changeworkflowplan/dependency_test.go +++ b/internal/command/changeworkflowplan/dependency_test.go @@ -5,6 +5,7 @@ import ( "go/token" "os" "path/filepath" + "strconv" "strings" "testing" ) @@ -31,8 +32,9 @@ func TestWorkflowAmbientAuthorityPredicates(t *testing.T) { assertNoSourceTokens(t, production, "git.Command", "go-git") }) t.Run("no_process_environment", func(t *testing.T) { + // Parsed imports cover every exec alias; Command( also matched DisplayCommand(. assertNoImports(t, production, "os/exec") - assertNoSourceTokens(t, production, "Getenv(", "LookupEnv(", "Environ(", "Command(") + assertNoSourceTokens(t, production, "Getenv(", "LookupEnv(", "Environ(") }) t.Run("no_setup_or_route", func(t *testing.T) { assertNoSourceTokens(t, production, "agentroute", "setup facade", "repository scan", "consumer-specific") @@ -60,19 +62,49 @@ func productionSource(t *testing.T) []sourceUnit { if err != nil { t.Fatal(err) } - parsed, err := parser.ParseFile(token.NewFileSet(), entry.Name(), content, parser.ImportsOnly) + imports, err := sourceImports(entry.Name(), content) if err != nil { t.Fatal(err) } - imports := map[string]struct{}{} - for _, imported := range parsed.Imports { - imports[strings.Trim(imported.Path.Value, "\"")] = struct{}{} - } result = append(result, sourceUnit{name: filepath.Base(entry.Name()), imports: imports, text: string(content)}) } return result } +func sourceImports(name string, content []byte) (map[string]struct{}, error) { + parsed, err := parser.ParseFile(token.NewFileSet(), name, content, parser.ImportsOnly) + if err != nil { + return nil, err + } + imports := map[string]struct{}{} + for _, imported := range parsed.Imports { + path, err := strconv.Unquote(imported.Path.Value) + if err != nil { + return nil, err + } + imports[path] = struct{}{} + } + return imports, nil +} + +func TestWorkflowProcessImportGuard(t *testing.T) { + for _, alias := range []string{"", "process ", ". ", "_ "} { + for _, literal := range []string{"\"os/exec\"", "`os/exec`"} { + imports, err := sourceImports("fixture.go", []byte("package fixture\nimport "+alias+literal+"\n")) + if err != nil { + t.Fatal(err) + } + if _, forbidden := imports["os/exec"]; !forbidden { + t.Fatalf("direct process authority escaped parsed-import policy: %s%s", alias, literal) + } + } + } + imports, err := sourceImports("fixture.go", []byte("package fixture\nfunc render(renderer Renderer) string { return renderer.DisplayCommand() }\n")) + if err != nil || len(imports) != 0 { + t.Fatal("pure rendering acquired process authority") + } +} + func assertNoImports(t *testing.T, units []sourceUnit, forbidden ...string) { t.Helper() for _, unit := range units { diff --git a/internal/command/changeworkflowplan/input_guide.go b/internal/command/changeworkflowplan/input_guide.go new file mode 100644 index 00000000..7803801f --- /dev/null +++ b/internal/command/changeworkflowplan/input_guide.go @@ -0,0 +1,92 @@ +package changeworkflowplan + +import ( + "strings" + + "github.com/research-engineering/agentic-proofkit/internal/kernel/cliexec" +) + +// InputGuide describes the consumer boundary; it grants no approval or IO authority. +func InputGuide(renderer cliexec.Renderer) string { + return strings.ReplaceAll(inputGuide, "{{cli}}", renderer.DisplayCommand()) +} + +const inputGuide = `Current-subject review input guide: + This command checks declared workflow state and identities. It does not read + artifactPath, discover dependencies, authenticate a reviewer or approve a change. + A supplied digest is not proof that current files still have that content. + +Consumer adapter steps (implement in the repository's change/check workflow): + 1. Read exact base/current inputs from an explicit bounded scope. Bind source + namespace, requirement/scenario meaning, matched native witness/path/selector, + assertion and helper inputs, command argv, environment/toolchain and receipt + policy. Enumerate transitive semantic dependencies; omitted inputs cannot + be repaired by hashing the declared subset again. Do not hash only IDs. + 2. Build one deterministic review subject per independently reviewable scope. + Use canonical admitted semantics for structured records and exact bytes for + native code unless a reviewed semantic normalization is available. Keep + source provenance separately; only an owner-approved normalization can + disregard a presentation change. Unknown equivalence requires review. + 3. Recompute the current subject before every checkpoint submission. Derive + affected relations from the exact base/current records, including additions, + removals, renames and shared many-to-many dependencies. Retain tombstone/base + identities for removals; compare source-qualified pairs, not bare local IDs. + Preserve unaffected confirmations. A test change requests upstream review, + never an automatic specification rewrite. Unknown/missing dependencies block. + 4. Obtain the assessment digest from the actual retained owner review. Do not + replace it with the new subject digest just to make admission pass. After a + semantic change, request new review or update the affected owners. Register + this adapter in a required consumer check; running it manually once does + not establish automatic invalidation for future changes. + +Review checkpoint template (null digests must be supplied): +` + "```json\n" + `{ + "schemaVersion": 1, + "completedStageIds": [], + "checkpoint": { + "state": "review_passed", + "subjectRefId": "example.subject", + "subjectDigest": null, + "assessmentSubjectDigest": null + }, + "contextRefs": [{ + "refId": "example.authority", + "refKind": "authority", + "artifactPath": "review/authority.json", + "subjectDigest": null, + "dependencyRefIds": [] + }, { + "refId": "example.subject", + "refKind": "artifact", + "artifactPath": "review/subject.json", + "subjectDigest": null, + "dependencyRefIds": [] + }], + "governingAuthorityRefId": "example.authority", + "requiredContextRefIds": [] +} +` + "```\n" + ` + Replace example references and paths with admitted consumer facts; keep refs + sorted and dependencies explicit. Digests use sha256:<64 lowercase hex digits>. + Both subjectDigest slots must name the same current artifact; the independent + assessmentSubjectDigest must match it. Bind authority to its own actual record. + completedStageIds is the exact completed prefix, not permission to skip stages. + This empty prefix reviews architecture; do not call it native verification. + Use review_passed only for an actual review without unresolved findings. + For a new subject awaiting review, use state ready_for_review and omit + assessmentSubjectDigest; retain subjectRefId and its current subjectDigest. + + {{cli}} change plan --input + A stale assessment rejects admission. Matching stale caller-supplied digests + can still agree: the consumer's actual-byte check must detect that substitution. + An admitted accept_stage action and successorStateDelta remain a derived plan, + not authenticated approval, execution or merge authority. Apply only that + delta to the exact prior snapshot, preserve its other fields, and re-admit the + merged snapshot. Never pass the output report itself as a workflow input. + + Qualify the adapter with an unchanged positive, each independently changed + semantic operand, a stale assessment, a changed file with old supplied hashes, + a cross-source substitution, an unaffected neighbor and a presentation-only + admitted-record control. Include add/remove/rename and changed environment. + No fixture count proves an arbitrary repository's dependency completeness. +` diff --git a/internal/command/nativeevidenceguidance/guidance.go b/internal/command/nativeevidenceguidance/guidance.go index 279fb22e..d2c8e588 100644 --- a/internal/command/nativeevidenceguidance/guidance.go +++ b/internal/command/nativeevidenceguidance/guidance.go @@ -98,6 +98,8 @@ Repository-specific adapter template (implement under consumer authority): Confirm continued adequacy or update affected owners; never automatically rewrite specification meaning from a test change. Bind any confirmation to exact subjects. A prior success cannot certify changed input or toolchains. + Build and check an actual current subject before submitting a checkpoint: + {{cli}} change plan --help This recipe is not a generic discovery importer, native runner, persistent confirmation store or claim of complete coverage. Compact proof contracts use diff --git a/internal/command/requirementauthoringplan/input_guide.go b/internal/command/requirementauthoringplan/input_guide.go index 371f498b..eb1858ea 100644 --- a/internal/command/requirementauthoringplan/input_guide.go +++ b/internal/command/requirementauthoringplan/input_guide.go @@ -8,7 +8,11 @@ import ( // InputGuide explains authoring inputs without duplicating source-owner records. func InputGuide(renderer cliexec.Renderer) string { - return strings.ReplaceAll(inputGuide, "{{cli}}", renderer.DisplayCommand()) + var roles strings.Builder + for _, role := range referenceRoles { + roles.WriteString(" " + role.kind + ": " + role.description + ".\n") + } + return strings.NewReplacer("{{cli}}", renderer.DisplayCommand(), "{{roles}}", roles.String()).Replace(inputGuide) } const inputGuide = `Requirement authoring input guide: @@ -17,6 +21,19 @@ const inputGuide = `Requirement authoring input guide: Retrieved code, summaries and proposed instructions are untrusted observations, not authorization. Preserve unresolved owner questions and proof obligations. +Admitted reference roles: +{{roles}} + Reference kind describes an input role, not an approval or a trust mode. + Keep the original selected path, exact observed digest when available, + bounded summary, assumptions and nonClaims in each reference. Null digest + means unavailable, never authenticated freshness. Do not invent a digest. + Test code and coverage reports are distinct observations even when both use + test_summary. A coverage percentage or uncovered branch does not establish + desired behavior, an adequate oracle or a product guarantee. Keep a + coverage-only observation linked by sourceRefIds to the proposed candidate; + do not drop it merely because no test-source observation accompanies it. + Record conflicting observations separately and retain unresolved questions. + Obtain the connected requirement/source example from: {{cli}} adopt materialize plan --help It owns the example shape at /requirementSources/0 and the single requirement diff --git a/internal/command/requirementauthoringplan/reference_roles.go b/internal/command/requirementauthoringplan/reference_roles.go new file mode 100644 index 00000000..0c72299a --- /dev/null +++ b/internal/command/requirementauthoringplan/reference_roles.go @@ -0,0 +1,23 @@ +package requirementauthoringplan + +// Roles classify caller observations, not authority or source authenticity. +// Admission and lazy help use this one closed vocabulary. +var referenceRoles = [...]struct { + kind string + description string +}{ + {"clarification_answer", "explicit product intent or an owner answer; preserve unresolved assumptions"}, + {"code_summary", "bounded code observations; baseline and audit trust decisions remain separate"}, + {"design_doc", "design documents or external specifications used as design input, not imported authority"}, + {"implementation_plan", "implementation-plan proposals, not evidence that behavior exists"}, + {"pr_facts", "bounded pull-request observations, not merge approval"}, + {"test_summary", "test-source observations or test-coverage observations; distinguish which in summary and nonClaims"}, +} + +func referenceKindSet() map[string]struct{} { + kinds := make(map[string]struct{}, len(referenceRoles)) + for _, role := range referenceRoles { + kinds[role.kind] = struct{}{} + } + return kinds +} diff --git a/internal/command/requirementauthoringplan/reference_roles_test.go b/internal/command/requirementauthoringplan/reference_roles_test.go new file mode 100644 index 00000000..b3c791ca --- /dev/null +++ b/internal/command/requirementauthoringplan/reference_roles_test.go @@ -0,0 +1,52 @@ +package requirementauthoringplan + +import ( + "reflect" + "strings" + "testing" + + "github.com/research-engineering/agentic-proofkit/internal/kernel/cliexec" +) + +func TestReferenceRolesPreserveExistingAdmissionVocabulary(t *testing.T) { + want := []string{"clarification_answer", "code_summary", "design_doc", "implementation_plan", "pr_facts", "test_summary"} + got := make([]string, 0, len(referenceRoles)) + help := InputGuide(cliexec.PathRenderer()) + for _, role := range referenceRoles { + got = append(got, role.kind) + if role.description == "" || strings.Count(help, " "+role.kind+": ") != 1 { + t.Fatalf("reference role missing or duplicated in help: %s", role.kind) + } + if _, ok := refKindSet[role.kind]; !ok { + t.Fatalf("help describes an unadmitted role: %s", role.kind) + } + } + if !reflect.DeepEqual(got, want) || len(refKindSet) != len(want) { + t.Fatalf("existing reference vocabulary changed: %v", got) + } + if strings.Contains(help, "{{roles}}") || strings.Contains(help, "{{cli}}") { + t.Fatal("unresolved authoring help placeholder") + } +} + +func TestReferenceRolesKeepMeaningBoundToKind(t *testing.T) { + // Expectations are independent of the production role table. + want := map[string][]string{ + "clarification_answer": {"product intent", "owner answer", "unresolved assumptions"}, + "code_summary": {"code observations", "baseline and audit"}, + "design_doc": {"design documents", "external specifications", "not imported authority"}, + "implementation_plan": {"implementation-plan proposals", "not evidence"}, + "pr_facts": {"pull-request observations", "not merge approval"}, + "test_summary": {"test-source observations", "test-coverage observations", "summary and nonClaims"}, + } + help := InputGuide(cliexec.PathRenderer()) + for kind, fragments := range want { + _, suffix, found := strings.Cut(help, " "+kind+": ") + line, _, _ := strings.Cut(suffix, "\n") + for _, fragment := range fragments { + if !found || !strings.Contains(line, fragment) { + t.Fatalf("reference role %s lost its required meaning %q", kind, fragment) + } + } + } +} diff --git a/internal/command/requirementauthoringplan/requirement_authoring_plan.go b/internal/command/requirementauthoringplan/requirement_authoring_plan.go index bc7dc172..34fce621 100644 --- a/internal/command/requirementauthoringplan/requirement_authoring_plan.go +++ b/internal/command/requirementauthoringplan/requirement_authoring_plan.go @@ -15,7 +15,7 @@ const planKind = "proofkit.requirement-authoring-plan" var ( modeSet = map[string]struct{}{"pull_request_design": {}, "retrospective_baseline": {}} - refKindSet = map[string]struct{}{"clarification_answer": {}, "code_summary": {}, "design_doc": {}, "implementation_plan": {}, "pr_facts": {}, "test_summary": {}} + refKindSet = referenceKindSet() operationSet = map[string]struct{}{"add": {}, "deprecate": {}, "modify": {}, "supersede": {}} obligationKindSet = map[string]struct{}{"native_witness": {}, "overview_claim": {}, "proof_binding": {}, "receipt": {}, "test_inventory": {}} sha256DigestRegexp = regexp.MustCompile(`^sha256:[a-f0-9]{64}$`) diff --git a/internal/command/stackpreset/preset_ids_generated.go b/internal/command/stackpreset/preset_ids_generated.go index b2f19a99..181c6f0b 100644 --- a/internal/command/stackpreset/preset_ids_generated.go +++ b/internal/command/stackpreset/preset_ids_generated.go @@ -1,6 +1,6 @@ // Code generated by internal/tools/commandcontractgen; DO NOT EDIT. package stackpreset -const presetContractSourceSHA256 = "40e21bb074eea37dba970d08cf06e1c5ee0ec1c1d7404fad1e7e28490a3924c4" +const presetContractSourceSHA256 = "7bb0e36255f4b08eca5f067f133b16b5a35111789ce1a46eccf63adccf2cf72c" var presetIDs = []string{"agentic_runtime_repo", "generated_docs_contract_repo", "python_service", "python_typescript_service", "typescript_monorepo", "typescript_workspace"} diff --git a/proofkit/cli-contract.v2.json b/proofkit/cli-contract.v2.json index edd2b330..22ab696e 100644 --- a/proofkit/cli-contract.v2.json +++ b/proofkit/cli-contract.v2.json @@ -143,7 +143,7 @@ "nativeSources": [ { "path": "internal/app", - "canonicalDigest": "sha256:c02f14fe65c88c21f7f6b867311d61def37378939dec88015abf9a085c4b93a7", + "canonicalDigest": "sha256:1049e6b312d9935bda1e536852051d28dc2b651215fbec2469e6b4c70e685e28", "evidenceClass": "source_checkout" }, { @@ -282,7 +282,7 @@ "nativeSources": [ { "path": "internal/app", - "canonicalDigest": "sha256:c02f14fe65c88c21f7f6b867311d61def37378939dec88015abf9a085c4b93a7", + "canonicalDigest": "sha256:1049e6b312d9935bda1e536852051d28dc2b651215fbec2469e6b4c70e685e28", "evidenceClass": "source_checkout" }, { @@ -396,7 +396,7 @@ "nativeSources": [ { "path": "internal/app", - "canonicalDigest": "sha256:c02f14fe65c88c21f7f6b867311d61def37378939dec88015abf9a085c4b93a7", + "canonicalDigest": "sha256:1049e6b312d9935bda1e536852051d28dc2b651215fbec2469e6b4c70e685e28", "evidenceClass": "source_checkout" }, { @@ -1187,7 +1187,7 @@ "nativeSources": [ { "path": "internal/app", - "canonicalDigest": "sha256:c02f14fe65c88c21f7f6b867311d61def37378939dec88015abf9a085c4b93a7", + "canonicalDigest": "sha256:1049e6b312d9935bda1e536852051d28dc2b651215fbec2469e6b4c70e685e28", "evidenceClass": "source_checkout" }, { @@ -1471,7 +1471,7 @@ "rootDefinitionDigest": "sha256:6632a481380bfb07d754ef622661b291f805b1b168b1824089bdd5cc9bdd4b0e", "nativeSource": { "path": "internal/command/changeworkflowplan", - "canonicalDigest": "sha256:f0f7fce215691b4b52a02010ff12b65605473f586f5d11c428e5d647f405baec", + "canonicalDigest": "sha256:588e5f2240b1ac4f29bd95d808747e697d809022ee8e5c61cd416dcc680e839d", "evidenceClass": "source_checkout" }, "nativeAdmissionWitnessSelector": { @@ -1506,7 +1506,7 @@ "rootDefinitionDigest": "sha256:ca7b2acffdcbfd28222eb61f2bd8687f76f20cb789b712ee3ffc2756a3674ff8", "nativeSource": { "path": "internal/command/changeworkflowplan", - "canonicalDigest": "sha256:f0f7fce215691b4b52a02010ff12b65605473f586f5d11c428e5d647f405baec", + "canonicalDigest": "sha256:588e5f2240b1ac4f29bd95d808747e697d809022ee8e5c61cd416dcc680e839d", "evidenceClass": "source_checkout" }, "nativeOutputWitnessSelector": { @@ -2506,7 +2506,7 @@ "nativeSources": [ { "path": "internal/app", - "canonicalDigest": "sha256:c02f14fe65c88c21f7f6b867311d61def37378939dec88015abf9a085c4b93a7", + "canonicalDigest": "sha256:1049e6b312d9935bda1e536852051d28dc2b651215fbec2469e6b4c70e685e28", "evidenceClass": "source_checkout" }, { @@ -2612,7 +2612,7 @@ "nativeSources": [ { "path": "internal/app", - "canonicalDigest": "sha256:c02f14fe65c88c21f7f6b867311d61def37378939dec88015abf9a085c4b93a7", + "canonicalDigest": "sha256:1049e6b312d9935bda1e536852051d28dc2b651215fbec2469e6b4c70e685e28", "evidenceClass": "source_checkout" }, { @@ -2740,7 +2740,7 @@ "nativeSources": [ { "path": "internal/app", - "canonicalDigest": "sha256:c02f14fe65c88c21f7f6b867311d61def37378939dec88015abf9a085c4b93a7", + "canonicalDigest": "sha256:1049e6b312d9935bda1e536852051d28dc2b651215fbec2469e6b4c70e685e28", "evidenceClass": "source_checkout" }, { @@ -2867,7 +2867,7 @@ "nativeSources": [ { "path": "internal/app", - "canonicalDigest": "sha256:c02f14fe65c88c21f7f6b867311d61def37378939dec88015abf9a085c4b93a7", + "canonicalDigest": "sha256:1049e6b312d9935bda1e536852051d28dc2b651215fbec2469e6b4c70e685e28", "evidenceClass": "source_checkout" }, { @@ -2965,7 +2965,7 @@ "nativeSources": [ { "path": "internal/app", - "canonicalDigest": "sha256:c02f14fe65c88c21f7f6b867311d61def37378939dec88015abf9a085c4b93a7", + "canonicalDigest": "sha256:1049e6b312d9935bda1e536852051d28dc2b651215fbec2469e6b4c70e685e28", "evidenceClass": "source_checkout" }, { @@ -3281,7 +3281,7 @@ "rootDefinitionDigest": "sha256:218011a133540f57ef74f8748747e00d33b6757c9f77725ecef39f45fb19423f", "nativeSource": { "path": "internal/command/nativeevidenceguidance", - "canonicalDigest": "sha256:c94f5f4634ab6eb92f35da4069f294cea82999006faa8804afd7b173ae7cb19f", + "canonicalDigest": "sha256:a195d899f95911e8441c2e08240e674bf6449a9e2c5c78c14692349c7f27e3aa", "evidenceClass": "source_checkout" }, "nativeOutputWitnessSelector": { @@ -3640,7 +3640,7 @@ "nativeSources": [ { "path": "internal/app", - "canonicalDigest": "sha256:c02f14fe65c88c21f7f6b867311d61def37378939dec88015abf9a085c4b93a7", + "canonicalDigest": "sha256:1049e6b312d9935bda1e536852051d28dc2b651215fbec2469e6b4c70e685e28", "evidenceClass": "source_checkout" }, { @@ -4653,7 +4653,7 @@ "rootDefinitionDigest": "sha256:86f8f4913b5316caa63c40d79125199b282d108cbd8b9711db21c2023d1a4ca4", "nativeSource": { "path": "internal/command/requirementauthoringplan", - "canonicalDigest": "sha256:c9df82eae1d9b8a7dd475b2510616d1d3cd851306f83dd5f1bb7983e7effb792", + "canonicalDigest": "sha256:fdc77865677d41c6565ac075a94998160ee111233a9e298b6660f7498e984f51", "evidenceClass": "source_checkout" }, "nativeAdmissionWitnessSelector": { @@ -4681,7 +4681,7 @@ "rootDefinitionDigest": "sha256:c2264058757e40789005b7cf7417906461f064b9b9bca0c5ddda86704e3b36cc", "nativeSource": { "path": "internal/command/requirementauthoringplan", - "canonicalDigest": "sha256:c9df82eae1d9b8a7dd475b2510616d1d3cd851306f83dd5f1bb7983e7effb792", + "canonicalDigest": "sha256:fdc77865677d41c6565ac075a94998160ee111233a9e298b6660f7498e984f51", "evidenceClass": "source_checkout" }, "nativeOutputWitnessSelector": { @@ -6935,7 +6935,7 @@ "rootDefinitionDigest": "sha256:3c842174dff5361e7f83166469b832805e05aa314b073c16234b5b64e346281e", "nativeSource": { "path": "internal/app", - "canonicalDigest": "sha256:c02f14fe65c88c21f7f6b867311d61def37378939dec88015abf9a085c4b93a7", + "canonicalDigest": "sha256:1049e6b312d9935bda1e536852051d28dc2b651215fbec2469e6b4c70e685e28", "evidenceClass": "source_checkout" }, "nativeAdmissionWitnessSelector": { @@ -6964,7 +6964,7 @@ "rootDefinitionDigest": "sha256:0ea95e277ebe44cd2de42c29b47c38686ac0b6b390d8965367437b3fe138e209", "nativeSource": { "path": "internal/app", - "canonicalDigest": "sha256:c02f14fe65c88c21f7f6b867311d61def37378939dec88015abf9a085c4b93a7", + "canonicalDigest": "sha256:1049e6b312d9935bda1e536852051d28dc2b651215fbec2469e6b4c70e685e28", "evidenceClass": "source_checkout" }, "nativeOutputWitnessSelector": {