create-agdf 0.14.2 → 0.14.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -1
- package/generated/.opencode/contracts/control-scaffold.md +17 -2
- package/generated/.opencode/skills/agdf-delivery-path-search/SKILL.md +16 -4
- package/generated/plugins/agdf/.claude-plugin/plugin.json +1 -1
- package/generated/plugins/agdf/.codex-plugin/plugin.json +1 -1
- package/generated/plugins/agdf/meta/agdf-plugin.definition.json +1 -1
- package/generated/plugins/agdf/meta/contracts/control-scaffold.md +17 -2
- package/generated/plugins/agdf/meta/copilot-payload-baseline.json +2 -2
- package/generated/plugins/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-plugin.definition.json +1 -1
- package/generated/plugins/agdf/runtime/create-agdf/lib/cli/delivery-path-search-command.js +51 -19
- package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/contracts.js +37 -0
- package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/persistence.js +14 -2
- package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/search-engine.js +126 -36
- package/generated/plugins/agdf/runtime/create-agdf/lib/delivery-path-search/state-adapter.js +40 -92
- package/generated/plugins/agdf/runtime/create-agdf/package.json +1 -1
- package/generated/plugins/agdf/runtime/runtime-manifest.json +2 -2
- package/generated/plugins/agdf/skills/delivery-path-search/SKILL.md +16 -4
- package/generated/plugins/agdf/submission/openai/availability.md +1 -1
- package/generated/plugins/agdf/submission/openai/capability-matrix.json +1 -1
- package/generated/plugins/agdf/submission/openai/release-notes.md +7 -1
- package/generated/plugins/agdf/submission/openai/reviewer-cases.json +1 -1
- package/generated/plugins/copilot/agdf/.agdf-payload-inventory.json +27 -27
- package/generated/plugins/copilot/agdf/copilot-skills/agdf-delivery-path-search/SKILL.md +16 -4
- package/generated/plugins/copilot/agdf/copilot-skills/contracts/control-scaffold.md +17 -2
- package/generated/plugins/copilot/agdf/meta/agdf-plugin.definition.json +1 -1
- package/generated/plugins/copilot/agdf/plugin.json +1 -1
- package/generated/plugins/copilot/agdf/runtime/create-agdf/generated/plugins/agdf/meta/agdf-plugin.definition.json +1 -1
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/cli/delivery-path-search-command.js +51 -19
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/contracts.js +37 -0
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/persistence.js +14 -2
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/search-engine.js +126 -36
- package/generated/plugins/copilot/agdf/runtime/create-agdf/lib/delivery-path-search/state-adapter.js +40 -92
- package/generated/plugins/copilot/agdf/runtime/create-agdf/package.json +1 -1
- package/generated/plugins/copilot/agdf/runtime/runtime-manifest.json +2 -2
- package/generated/submissions/openai/agdf/.codex-plugin/plugin.json +1 -1
- package/generated/submissions/openai/agdf/meta/agdf-plugin.definition.json +1 -1
- package/generated/submissions/openai/agdf/meta/contracts/control-scaffold.md +17 -2
- package/generated/submissions/openai/agdf/meta/copilot-payload-baseline.json +2 -2
- package/generated/submissions/openai/agdf/skills/delivery-path-search/SKILL.md +16 -4
- package/generated/submissions/openai/agdf/submission/openai/availability.md +1 -1
- package/generated/submissions/openai/agdf/submission/openai/capability-matrix.json +1 -1
- package/generated/submissions/openai/agdf/submission/openai/inventory.json +12 -12
- package/generated/submissions/openai/agdf/submission/openai/listing.json +1 -1
- package/generated/submissions/openai/agdf/submission/openai/readiness.json +2 -2
- package/generated/submissions/openai/agdf/submission/openai/readiness.md +2 -2
- package/generated/submissions/openai/agdf/submission/openai/release-notes.md +7 -1
- package/generated/submissions/openai/agdf/submission/openai/reviewer-cases.json +1 -1
- package/lib/cli/delivery-path-search-command.js +51 -19
- package/lib/delivery-path-search/contracts.js +37 -0
- package/lib/delivery-path-search/persistence.js +14 -2
- package/lib/delivery-path-search/search-engine.js +126 -36
- package/lib/delivery-path-search/state-adapter.js +40 -92
- package/package.json +1 -1
|
@@ -4,11 +4,24 @@
|
|
|
4
4
|
|
|
5
5
|
Delivery Path Search is an optional read-only planning step for high-impact decisions with several materially different next actions.
|
|
6
6
|
|
|
7
|
-
- It consumes
|
|
8
|
-
|
|
7
|
+
- It consumes the canonical selected-run `gate-check` evaluation for run, revision, current gate and
|
|
8
|
+
legal actions. Persisted presentation Markdown such as the Run Status Card is never policy input.
|
|
9
|
+
- It binds the selected `scope_key`, `scope_revision` and objective to one control snapshot. A stale
|
|
10
|
+
or incomplete snapshot fails before candidate generation or evaluation.
|
|
11
|
+
- It reports the phase that actually ran: `input | candidate | evaluation | search`. A phase that
|
|
12
|
+
did not run cannot produce a later-phase conclusion.
|
|
13
|
+
- Terminal status is `input_unavailable | no_legal_candidates | evaluator_unavailable |
|
|
14
|
+
evaluator_error | recommendation | no_safe_recommendation`. Recommendation-facing statuses
|
|
15
|
+
require at least one contract-valid evaluation. `candidate_queue_exhausted` is a stopping reason,
|
|
16
|
+
not recommendation evidence.
|
|
17
|
+
- It reports baseline/generated/legal/rejected candidate counts and attempted/valid/invalid
|
|
18
|
+
evaluation counts. Zero valid evaluations must never be presented or persisted as an evaluated
|
|
19
|
+
recommendation conclusion.
|
|
9
20
|
- It must report budgets, stopping reason and `full | tool_enforced | instruction_only` enforcement.
|
|
10
21
|
- Model scores are judgements, not measurements.
|
|
11
22
|
- Search output is evidence only. Canonical `gate-check` independently decides what may proceed.
|
|
23
|
+
- Search applies only to the selected run objective. An unrelated decision needs the correct
|
|
24
|
+
governed scope; Delivery Path Search is not a second task-target resolver.
|
|
12
25
|
- The bounded first-release algorithm must not be labelled MCTS.
|
|
13
26
|
- Surface adapters may translate transport and presentation, but must not fork scoring, search or gate semantics.
|
|
14
27
|
- Optional AI-native candidate generation supplements the deterministic candidate baseline; it never replaces it.
|
|
@@ -19,6 +32,8 @@ Delivery Path Search is an optional read-only planning step for high-impact deci
|
|
|
19
32
|
- Codex and Claude Code may provide tool-enforced generator transports. Copilot, OpenCode and generic surfaces remain instruction-only without conforming evidence.
|
|
20
33
|
- OpenCode may provide a tool-enforced evaluator only for an invocation whose capability preflight proves `opencode run --pure --agent`, the owned evaluator agent and effective executable-tool denies. Preflight or transport failure must return `evaluator_unavailable` with `instruction_only` enforcement and point to the existing instruction-only workflow; it must not continue through a weaker subprocess.
|
|
21
34
|
- OpenCode candidate generation remains unavailable.
|
|
35
|
+
- Persistence accepts only contract-valid `recommendation` or `no_safe_recommendation` results with
|
|
36
|
+
at least one valid evaluation. Input, candidate and evaluator failure results remain transient.
|
|
22
37
|
|
|
23
38
|
The field names above are the stable machine-readable contract used by JSON
|
|
24
39
|
reports and automation. Human-facing Markdown must present the same projection
|
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
"schema_version": 1,
|
|
3
3
|
"profile_id": "copilot-runtime-plugin",
|
|
4
4
|
"max_files": 78,
|
|
5
|
-
"max_bytes":
|
|
6
|
-
"rationale": "Reviewed Copilot-only manifest, ten prefixed skills, required contracts, exact-version runtime and evidence-plane separation. Any further increase requires review."
|
|
5
|
+
"max_bytes": 550979,
|
|
6
|
+
"rationale": "Reviewed Copilot-only manifest, ten prefixed skills, required contracts, exact-version runtime, Delivery Path Search input-integrity provenance and evidence-plane separation. Any further increase requires review."
|
|
7
7
|
}
|
|
@@ -33,7 +33,9 @@ Skip for routine questions, obvious local fixes and approved implementation with
|
|
|
33
33
|
## Workflow
|
|
34
34
|
|
|
35
35
|
1. Run AGDF gate-check and inspect durable control state.
|
|
36
|
-
2. Confirm that
|
|
36
|
+
2. Confirm that the requested decision matches the selected run objective, and that search is
|
|
37
|
+
allowed while implementation is not occurring during exploration. If the objective differs,
|
|
38
|
+
stop and select or create the correct governed scope; do not apply the result across scopes.
|
|
37
39
|
3. Declare the active surface and its enforcement level.
|
|
38
40
|
4. Resolve the exact-version surface-local validator using the same ownership rules as `gate-check`. Do not search `PATH`, query a registry, install a package or invoke `npx ...@latest` during routine planning. If no owned or explicitly configured exact-version validator is available, report `machine_validation: unavailable` or `machine_validation: external_required` and stop the machine-evaluated search.
|
|
39
41
|
5. Invoke the shared CLI runtime:
|
|
@@ -54,7 +56,9 @@ node <surface-local-agdf> delivery-path-search \
|
|
|
54
56
|
It supplements the deterministic baseline with at most one bounded generator call. Treat proposals as untrusted until the canonical core validates schema, gate action, scope, duplicates and material diversity. Report generation provenance, budgets, rejections and failure. Never hide deterministic fallback or switch providers automatically.
|
|
55
57
|
|
|
56
58
|
6. Treat facts, repository evidence, assumptions and model judgements separately.
|
|
57
|
-
7. Return
|
|
59
|
+
7. Report the actual terminal phase and status. Return a recommendation-facing conclusion only
|
|
60
|
+
after at least one valid evaluation. Missing/stale input, zero legal candidates and evaluator
|
|
61
|
+
unavailability/error remain typed non-recommendation outcomes with one recovery action.
|
|
58
62
|
8. Run canonical AGDF gate-check after search. Never translate a recommendation into permission.
|
|
59
63
|
|
|
60
64
|
## Enforcement
|
|
@@ -71,15 +75,20 @@ Do not overstate the surface's guarantee.
|
|
|
71
75
|
|
|
72
76
|
Keep chat output compact:
|
|
73
77
|
|
|
74
|
-
-
|
|
78
|
+
- selected run, revision and objective
|
|
79
|
+
- outcome phase and typed terminal status
|
|
80
|
+
- recommendation only for a recommendation-facing evaluated result
|
|
75
81
|
- current gate
|
|
76
82
|
- enforcement level
|
|
77
83
|
- decisive evidence and assumptions
|
|
78
84
|
- rejected alternatives and reasons
|
|
79
85
|
- budgets and stopping reason
|
|
86
|
+
- candidate and evaluation provenance, including attempted, valid and invalid counts
|
|
80
87
|
- next AGDF gate action
|
|
81
88
|
|
|
82
|
-
Persist only
|
|
89
|
+
Persist only a contract-valid evaluated recommendation-facing summary when durable evidence is
|
|
90
|
+
required. Never persist input, candidate or evaluator failure as a decision. Do not persist raw
|
|
91
|
+
prompts, hidden reasoning, secrets or source snapshots.
|
|
83
92
|
|
|
84
93
|
## Boundaries
|
|
85
94
|
|
|
@@ -87,6 +96,9 @@ Persist only the redacted decision summary when durable evidence is required. Do
|
|
|
87
96
|
- Do not modify repository files during search.
|
|
88
97
|
- Do not execute evaluator-returned commands.
|
|
89
98
|
- Do not invent default scores for invalid evaluator output.
|
|
99
|
+
- Do not parse Run Status Card or other presentation Markdown as gate-policy input.
|
|
100
|
+
- Do not describe zero valid evaluations as `no_safe_recommendation`.
|
|
101
|
+
- Do not apply one selected run's result to an unrelated question.
|
|
90
102
|
- Do not implement, approve or release based on search output.
|
|
91
103
|
- Do not create agent-specific scoring, gate logic or skill copies.
|
|
92
104
|
- Do not replace deterministic candidates with generated proposals.
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"releaseVersion": "0.14.
|
|
4
|
-
"digest": "
|
|
3
|
+
"releaseVersion": "0.14.3",
|
|
4
|
+
"digest": "88a2d665f6b0a11cc7de1d0200979d58bc601164f0418faa66e200f7d8a6635c",
|
|
5
5
|
"files": [
|
|
6
6
|
{
|
|
7
7
|
"path": ".codex-plugin/plugin.json",
|
|
8
|
-
"sha256": "
|
|
8
|
+
"sha256": "1723041a1f54829e14dd90d95017fe403e72074e569ae64fca4fc62f9d74b318"
|
|
9
9
|
},
|
|
10
10
|
{
|
|
11
11
|
"path": "assets/agdf-icon.svg",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
},
|
|
30
30
|
{
|
|
31
31
|
"path": "meta/agdf-plugin.definition.json",
|
|
32
|
-
"sha256": "
|
|
32
|
+
"sha256": "16b69b796510bf4f6907fd986ad64dcf8e5ac4f3860d12e0e62381ea2582b012"
|
|
33
33
|
},
|
|
34
34
|
{
|
|
35
35
|
"path": "meta/agdf-runtime-contract.md",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
},
|
|
54
54
|
{
|
|
55
55
|
"path": "meta/contracts/control-scaffold.md",
|
|
56
|
-
"sha256": "
|
|
56
|
+
"sha256": "82d298d5399c56ecbaeef78ac367556b675200c09ea96e160534ec03adb07f42"
|
|
57
57
|
},
|
|
58
58
|
{
|
|
59
59
|
"path": "meta/contracts/gate-transition.md",
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
},
|
|
78
78
|
{
|
|
79
79
|
"path": "meta/copilot-payload-baseline.json",
|
|
80
|
-
"sha256": "
|
|
80
|
+
"sha256": "7f9d12592af01da501c2e5e2c4fc79cff86e7677384db3b2c72c6f8ec589aa4c"
|
|
81
81
|
},
|
|
82
82
|
{
|
|
83
83
|
"path": "skills/brownfield-analysis/SKILL.md",
|
|
@@ -113,7 +113,7 @@
|
|
|
113
113
|
},
|
|
114
114
|
{
|
|
115
115
|
"path": "skills/delivery-path-search/SKILL.md",
|
|
116
|
-
"sha256": "
|
|
116
|
+
"sha256": "688a0e04f6a1a39be17ded0047f88187b109f25bd9f22927a3d4261cbfdc0bd5"
|
|
117
117
|
},
|
|
118
118
|
{
|
|
119
119
|
"path": "skills/delivery-path-search/help.md",
|
|
@@ -161,23 +161,23 @@
|
|
|
161
161
|
},
|
|
162
162
|
{
|
|
163
163
|
"path": "submission/openai/availability.md",
|
|
164
|
-
"sha256": "
|
|
164
|
+
"sha256": "6e2a4d12acfd22a728841169ae5d68b57d303ec3632aba09b5aa6c64d033253b"
|
|
165
165
|
},
|
|
166
166
|
{
|
|
167
167
|
"path": "submission/openai/capability-matrix.json",
|
|
168
|
-
"sha256": "
|
|
168
|
+
"sha256": "81425b79a427492d3e46e6f665ebc65e5a6ad47b8e897044180a8946e91c94b9"
|
|
169
169
|
},
|
|
170
170
|
{
|
|
171
171
|
"path": "submission/openai/listing.json",
|
|
172
|
-
"sha256": "
|
|
172
|
+
"sha256": "8302d3c25e7385767456b9ffa8a8939f9476cc28ce5a2357eb8b08cceb58fbb0"
|
|
173
173
|
},
|
|
174
174
|
{
|
|
175
175
|
"path": "submission/openai/release-notes.md",
|
|
176
|
-
"sha256": "
|
|
176
|
+
"sha256": "ece61208d4538e5fd9a239d3c6bca98e1e0a34a5204fae1d4666b0bbaabf54f4"
|
|
177
177
|
},
|
|
178
178
|
{
|
|
179
179
|
"path": "submission/openai/reviewer-cases.json",
|
|
180
|
-
"sha256": "
|
|
180
|
+
"sha256": "83b192f19d11e28ed16b33a81cadbcef8d6dd4b46bd2022841dc317ba6612b7a"
|
|
181
181
|
}
|
|
182
182
|
]
|
|
183
183
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"releaseVersion": "0.14.
|
|
3
|
+
"releaseVersion": "0.14.3",
|
|
4
4
|
"candidateState": "repository_ready",
|
|
5
5
|
"submissionReady": false,
|
|
6
6
|
"submissionBlockers": [
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
},
|
|
17
17
|
"bundle": {
|
|
18
18
|
"state": "pass",
|
|
19
|
-
"detail": "44 inventoried files; inventory digest
|
|
19
|
+
"detail": "44 inventoried files; inventory digest 88a2d665f6b0a11cc7de1d0200979d58bc601164f0418faa66e200f7d8a6635c"
|
|
20
20
|
},
|
|
21
21
|
"installed_host": {
|
|
22
22
|
"state": "unverified",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# AGDF Public Plugin Readiness
|
|
2
2
|
|
|
3
|
-
- release: `0.14.
|
|
3
|
+
- release: `0.14.3`
|
|
4
4
|
- candidate_state: `repository_ready`
|
|
5
5
|
- submission_ready: `false`
|
|
6
6
|
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
| Class | State | Detail |
|
|
10
10
|
|---|---|---|
|
|
11
11
|
| repository | pass | canonical contract and deterministic source checks |
|
|
12
|
-
| bundle | pass | 44 inventoried files; inventory digest
|
|
12
|
+
| bundle | pass | 44 inventoried files; inventory digest 88a2d665f6b0a11cc7de1d0200979d58bc601164f0418faa66e200f7d8a6635c |
|
|
13
13
|
| installed_host | unverified | PPD-L02 and PPD-L03 not performed |
|
|
14
14
|
| portal | unverified | unverified |
|
|
15
15
|
| post_publication | unverified | not published |
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# AGDF 0.14.
|
|
1
|
+
# AGDF 0.14.3 — Initial OpenAI Public Plugin Candidate
|
|
2
2
|
|
|
3
3
|
This candidate packages the canonical AGDF workflow skills for public discovery in ChatGPT and
|
|
4
4
|
Codex. It helps users assess delivery fit, preserve explicit human approvals, inspect existing-system
|
|
@@ -19,6 +19,12 @@ runtime or hooks, so automatic runtime checks remain unavailable in this profile
|
|
|
19
19
|
installers also show the target and verified installed AGDF version, distinguish previous intent from
|
|
20
20
|
effective host permission, explain manual mode and recover visibly from an invalid key.
|
|
21
21
|
|
|
22
|
+
Delivery Path Search now consumes canonical selected-run gate actions instead of persisted
|
|
23
|
+
presentation Markdown. Its additive version-1 result fields expose run revision, objective, outcome
|
|
24
|
+
phase and candidate/evaluation provenance. Missing input, zero legal candidates and evaluator
|
|
25
|
+
failures no longer appear as `no_safe_recommendation`; recommendation-facing results require at
|
|
26
|
+
least one valid evaluation and are the only persistable outcomes.
|
|
27
|
+
|
|
22
28
|
AGDF is an independent open-source project by Arndt Gold. It is not affiliated with, endorsed by or
|
|
23
29
|
sponsored by OpenAI and is not a security sandbox, legal assessment, compliance certification or
|
|
24
30
|
autonomous shipping system.
|
|
@@ -12,21 +12,25 @@ import { enforcementForSurface } from '../delivery-path-search/surfaces/capabili
|
|
|
12
12
|
import { persistSearchResult } from '../delivery-path-search/persistence.js';
|
|
13
13
|
|
|
14
14
|
function unavailableOpenCodeResult({ options, preflight, input = null, error = null }) {
|
|
15
|
+
const surface = options.surface ?? "opencode";
|
|
15
16
|
const mutation = error?.code === "OPENCODE_EVALUATOR_MUTATION_DETECTED";
|
|
16
|
-
const attempted = Boolean(input);
|
|
17
|
+
const attempted = Boolean(input && error);
|
|
17
18
|
const nextAction = mutation
|
|
18
19
|
? "Investigate and revert the detected repository mutation before any evaluator fallback or retry."
|
|
19
20
|
: "Repair the reported OpenCode capability and retry, or use the existing instruction-only Delivery Path Search workflow.";
|
|
20
21
|
return {
|
|
21
22
|
contract_version: "1",
|
|
22
|
-
surface
|
|
23
|
+
surface,
|
|
23
24
|
scope_key: input?.scope_key ?? options.runId ?? null,
|
|
25
|
+
scope_revision: input?.scope_revision ?? "unversioned",
|
|
26
|
+
objective: input?.objective ?? "Delivery Path Search evaluator capability",
|
|
24
27
|
current_gate: input?.current_gate ?? null,
|
|
28
|
+
outcome_phase: "evaluation",
|
|
25
29
|
status: mutation ? "evaluator_error" : "evaluator_unavailable",
|
|
26
30
|
recommendation: null,
|
|
27
|
-
enforcement: enforcementForSurface(
|
|
31
|
+
enforcement: enforcementForSurface(surface),
|
|
28
32
|
evaluator: {
|
|
29
|
-
name:
|
|
33
|
+
name: surface,
|
|
30
34
|
preflight: preflight?.code ?? "not_run",
|
|
31
35
|
failure_code: error?.code ?? preflight?.code,
|
|
32
36
|
detail: error?.message ?? preflight?.detail,
|
|
@@ -38,6 +42,16 @@ function unavailableOpenCodeResult({ options, preflight, input = null, error = n
|
|
|
38
42
|
failure_code: error?.code ?? preflight?.code,
|
|
39
43
|
evidence: preflight?.evidence ?? [],
|
|
40
44
|
},
|
|
45
|
+
provenance: {
|
|
46
|
+
baseline_candidates: Math.min(input?.allowed_actions?.length ?? 0, input?.budgets?.max_candidates ?? 0),
|
|
47
|
+
generated_candidates: 0,
|
|
48
|
+
legal_candidates: attempted ? 1 : 0,
|
|
49
|
+
rejected_candidates: 0,
|
|
50
|
+
evaluation_attempts: attempted ? 1 : 0,
|
|
51
|
+
valid_evaluations: 0,
|
|
52
|
+
invalid_evaluations: attempted ? 1 : 0,
|
|
53
|
+
},
|
|
54
|
+
failure_code: error?.code ?? preflight?.code,
|
|
41
55
|
stopping_reason: mutation ? "opencode_mutation_detected" : attempted ? "opencode_evaluator_failed" : "opencode_preflight_failed",
|
|
42
56
|
next_action: nextAction,
|
|
43
57
|
next_gate_action: nextAction,
|
|
@@ -46,11 +60,26 @@ function unavailableOpenCodeResult({ options, preflight, input = null, error = n
|
|
|
46
60
|
|
|
47
61
|
export async function executeDeliveryPathSearch(options, io = console, dependencies = {}) {
|
|
48
62
|
const fixture = options.fixture ? JSON.parse(readFileSync(options.fixture, "utf8")) : null;
|
|
63
|
+
const fixtureGeneration = fixture?.generator_response;
|
|
64
|
+
const generationEnabled = Boolean(fixtureGeneration || options.generateCandidates);
|
|
65
|
+
const initialEnforcement = fixture?.input?.enforcement ?? enforcementForSurface(options.surface);
|
|
66
|
+
const initialInput = fixture?.input ?? (dependencies.searchInputFromControl ?? searchInputFromControl)(options.dir, {
|
|
67
|
+
scopeKey: options.runId,
|
|
68
|
+
enforcement: initialEnforcement,
|
|
69
|
+
generation: generationEnabled ? {
|
|
70
|
+
enabled: true,
|
|
71
|
+
maxProposals: options.maxGeneratedCandidates,
|
|
72
|
+
maxDurationMs: options.generationTimeoutMs,
|
|
73
|
+
maxCostUnits: options.generationCostUnits,
|
|
74
|
+
} : undefined,
|
|
75
|
+
});
|
|
49
76
|
const preflight = !fixture && options.surface === "opencode"
|
|
50
77
|
? (dependencies.preflightOpenCodeEvaluator ?? preflightOpenCodeEvaluator)({ cwd: options.dir })
|
|
51
78
|
: null;
|
|
52
79
|
if (preflight?.status === "failed") {
|
|
53
|
-
const result =
|
|
80
|
+
const result = initialInput.input_failure_code
|
|
81
|
+
? await runDeliveryPathSearch(initialInput, { name: "not-invoked", async evaluate() { throw new Error("input failure must stop before evaluation"); } })
|
|
82
|
+
: unavailableOpenCodeResult({ options, preflight, input: initialInput });
|
|
54
83
|
printDeliveryPathSearchResult(result, options, io);
|
|
55
84
|
return result;
|
|
56
85
|
}
|
|
@@ -58,18 +87,7 @@ export async function executeDeliveryPathSearch(options, io = console, dependenc
|
|
|
58
87
|
?? (preflight
|
|
59
88
|
? enforcementForSurface("opencode", preflight.evidence, { preflight })
|
|
60
89
|
: enforcementForSurface(options.surface));
|
|
61
|
-
const
|
|
62
|
-
const generationEnabled = Boolean(fixtureGeneration || options.generateCandidates);
|
|
63
|
-
const baseInput = fixture?.input ?? (dependencies.searchInputFromControl ?? searchInputFromControl)(options.dir, {
|
|
64
|
-
scopeKey: options.runId,
|
|
65
|
-
enforcement,
|
|
66
|
-
generation: generationEnabled ? {
|
|
67
|
-
enabled: true,
|
|
68
|
-
maxProposals: options.maxGeneratedCandidates,
|
|
69
|
-
maxDurationMs: options.generationTimeoutMs,
|
|
70
|
-
maxCostUnits: options.generationCostUnits,
|
|
71
|
-
} : undefined,
|
|
72
|
-
});
|
|
90
|
+
const baseInput = fixture ? initialInput : { ...initialInput, enforcement };
|
|
73
91
|
const input = generationEnabled && !baseInput.generation ? {
|
|
74
92
|
...baseInput,
|
|
75
93
|
generation: {
|
|
@@ -90,7 +108,13 @@ export async function executeDeliveryPathSearch(options, io = console, dependenc
|
|
|
90
108
|
? (dependencies.openCodeEvaluator ?? openCodeEvaluator)({ cwd: options.dir, model: options.model, preflight })
|
|
91
109
|
: null;
|
|
92
110
|
if (!evaluator) {
|
|
93
|
-
|
|
111
|
+
const detail = `${options.surface} has no executable evaluator in this release. Codex, Claude and preflight-qualified OpenCode are the executable adapters; --fixture is available for deterministic contract testing.`;
|
|
112
|
+
const result = {
|
|
113
|
+
...unavailableOpenCodeResult({ options, preflight: { code: "surface_evaluator_unavailable", detail, evidence: [] }, input }),
|
|
114
|
+
surface: options.surface,
|
|
115
|
+
};
|
|
116
|
+
printDeliveryPathSearchResult(result, options, io);
|
|
117
|
+
return result;
|
|
94
118
|
}
|
|
95
119
|
const generator = fixtureGeneration
|
|
96
120
|
? fixtureGenerator(fixtureGeneration)
|
|
@@ -125,15 +149,23 @@ function printDeliveryPathSearchResult(result, options, io) {
|
|
|
125
149
|
return;
|
|
126
150
|
}
|
|
127
151
|
io.log(`AGDF Delivery Path Search: ${result.status}`);
|
|
152
|
+
io.log(`Scope: ${result.scope_key ?? "unknown"} @ ${result.scope_revision ?? "unversioned"}`);
|
|
153
|
+
if (result.objective) io.log(`Objective: ${result.objective}`);
|
|
128
154
|
io.log(`Current gate: ${result.current_gate ?? "unknown"}`);
|
|
155
|
+
io.log(`Outcome phase: ${result.outcome_phase ?? "unknown"}`);
|
|
129
156
|
io.log(`Enforcement: ${result.enforcement.level}`);
|
|
130
157
|
io.log(`Recommendation: ${result.recommendation?.action ?? "none"}`);
|
|
131
158
|
if (result.budgets) io.log(`Evaluations: ${result.budgets.evaluations}`);
|
|
159
|
+
if (result.provenance) {
|
|
160
|
+
io.log(`Candidates: ${result.provenance.legal_candidates} legal, ${result.provenance.rejected_candidates} rejected`);
|
|
161
|
+
io.log(`Evaluation provenance: ${result.provenance.valid_evaluations}/${result.provenance.evaluation_attempts} valid, ${result.provenance.invalid_evaluations} invalid`);
|
|
162
|
+
}
|
|
132
163
|
if (result.generation) {
|
|
133
164
|
io.log(`Generation: ${result.generation.status} (${result.generation.accepted}/${result.generation.returned} accepted)`);
|
|
134
165
|
io.log(`Generation budget: ${result.generation.cost_units} cost units, ${result.generation.duration_ms} ms`);
|
|
135
166
|
if (result.generation.failure_code) io.log(`Generation failure: ${result.generation.failure_code}`);
|
|
136
167
|
}
|
|
137
168
|
io.log(`Stopping reason: ${result.stopping_reason}`);
|
|
138
|
-
io.log(result.
|
|
169
|
+
if (result.failure_code) io.log(`Failure: ${result.failure_code}`);
|
|
170
|
+
io.log(result.next_action ?? result.next_gate_action);
|
|
139
171
|
}
|
|
@@ -68,6 +68,10 @@ export function validateSearchInput(value) {
|
|
|
68
68
|
}
|
|
69
69
|
requireString(input.objective, "objective");
|
|
70
70
|
requireString(input.current_gate, "current_gate");
|
|
71
|
+
optionalBoundedString(input.scope_revision, "scope_revision", 200);
|
|
72
|
+
optionalBoundedString(input.input_failure_code, "input_failure_code", 200);
|
|
73
|
+
optionalBoundedString(input.input_failure_detail, "input_failure_detail", 1000);
|
|
74
|
+
optionalBoundedString(input.input_recovery_action, "input_recovery_action", 1000);
|
|
71
75
|
stringArray(input.allowed_actions, "allowed_actions");
|
|
72
76
|
stringArray(input.forbidden_actions, "forbidden_actions");
|
|
73
77
|
stringArray(input.evidence_refs ?? [], "evidence_refs");
|
|
@@ -81,6 +85,39 @@ export function validateSearchInput(value) {
|
|
|
81
85
|
return structuredClone(input);
|
|
82
86
|
}
|
|
83
87
|
|
|
88
|
+
const RESULT_PHASE_BY_STATUS = new Map([
|
|
89
|
+
["input_unavailable", "input"],
|
|
90
|
+
["no_legal_candidates", "candidate"],
|
|
91
|
+
["evaluator_unavailable", "evaluation"],
|
|
92
|
+
["evaluator_error", "evaluation"],
|
|
93
|
+
["recommendation", "search"],
|
|
94
|
+
["no_safe_recommendation", "search"],
|
|
95
|
+
]);
|
|
96
|
+
|
|
97
|
+
export function validateSearchResult(value) {
|
|
98
|
+
const result = requireObject(value, "search result");
|
|
99
|
+
if (result.contract_version !== CONTRACT_VERSION) throw new Error(`unsupported search result contract_version: ${result.contract_version}`);
|
|
100
|
+
const status = requireString(result.status, "result.status");
|
|
101
|
+
const expectedPhase = RESULT_PHASE_BY_STATUS.get(status);
|
|
102
|
+
if (!expectedPhase) throw new Error(`unsupported search result status: ${status}`);
|
|
103
|
+
if (result.outcome_phase !== expectedPhase) throw new Error(`${status} requires outcome_phase ${expectedPhase}`);
|
|
104
|
+
requireString(result.scope_key, "result.scope_key");
|
|
105
|
+
optionalBoundedString(result.scope_revision, "result.scope_revision", 200);
|
|
106
|
+
const provenance = requireObject(result.provenance, "result.provenance");
|
|
107
|
+
for (const key of ["baseline_candidates", "generated_candidates", "legal_candidates", "rejected_candidates", "evaluation_attempts", "valid_evaluations", "invalid_evaluations"]) {
|
|
108
|
+
if (!Number.isInteger(provenance[key]) || provenance[key] < 0) throw new Error(`result.provenance.${key} must be a non-negative integer`);
|
|
109
|
+
}
|
|
110
|
+
if (provenance.evaluation_attempts !== provenance.valid_evaluations + provenance.invalid_evaluations) throw new Error("result evaluation provenance counts are inconsistent");
|
|
111
|
+
const recommendationFacing = status === "recommendation" || status === "no_safe_recommendation";
|
|
112
|
+
if (recommendationFacing && provenance.valid_evaluations < 1) throw new Error(`${status} requires at least one valid evaluation`);
|
|
113
|
+
if (status === "recommendation" && !result.recommendation) throw new Error("recommendation status requires recommendation content");
|
|
114
|
+
if (status !== "recommendation" && result.recommendation != null) throw new Error(`${status} must not contain recommendation content`);
|
|
115
|
+
if (status === "no_legal_candidates" && (provenance.legal_candidates !== 0 || provenance.evaluation_attempts !== 0)) throw new Error("no_legal_candidates requires zero legal candidates and evaluation attempts");
|
|
116
|
+
if (status === "input_unavailable" && provenance.evaluation_attempts !== 0) throw new Error("input_unavailable requires zero evaluation attempts");
|
|
117
|
+
if ((status === "evaluator_unavailable" || status === "evaluator_error") && provenance.valid_evaluations !== 0) throw new Error(`${status} requires zero valid evaluations`);
|
|
118
|
+
return structuredClone(result);
|
|
119
|
+
}
|
|
120
|
+
|
|
84
121
|
export function validateCandidate(value) {
|
|
85
122
|
const candidate = requireObject(value, "candidate");
|
|
86
123
|
requireString(candidate.id, "candidate.id");
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { mkdirSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { dirname, join } from "node:path";
|
|
3
|
+
import { validateSearchResult } from "./contracts.js";
|
|
3
4
|
|
|
4
5
|
function safeResult(result) {
|
|
5
6
|
return JSON.parse(JSON.stringify(result, (key, value) => {
|
|
@@ -9,22 +10,33 @@ function safeResult(result) {
|
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
export function persistSearchResult(targetDir, result) {
|
|
12
|
-
const
|
|
13
|
+
const validated = validateSearchResult(result);
|
|
14
|
+
if (!["recommendation", "no_safe_recommendation"].includes(validated.status)) {
|
|
15
|
+
throw new Error(`search result status ${validated.status} is not persistable`);
|
|
16
|
+
}
|
|
17
|
+
if (validated.provenance.valid_evaluations < 1) {
|
|
18
|
+
throw new Error("search result requires at least one valid evaluation before persistence");
|
|
19
|
+
}
|
|
20
|
+
const root = join(targetDir, ".agdf", "control", "artefacts", validated.scope_key);
|
|
13
21
|
const jsonPath = join(root, "DELIVERY_PATH_SEARCH.json");
|
|
14
22
|
const markdownPath = join(root, "DELIVERY_PATH_SEARCH.md");
|
|
15
23
|
mkdirSync(dirname(jsonPath), { recursive: true });
|
|
16
|
-
const safe = safeResult(
|
|
24
|
+
const safe = safeResult(validated);
|
|
17
25
|
writeFileSync(jsonPath, `${JSON.stringify(safe, null, 2)}\n`, "utf8");
|
|
18
26
|
const recommendation = safe.recommendation?.action ?? "No safe recommendation";
|
|
19
27
|
writeFileSync(markdownPath, [
|
|
20
28
|
"# Delivery Path Search Decision",
|
|
21
29
|
"",
|
|
22
30
|
`- status: ${safe.status}`,
|
|
31
|
+
`- outcome_phase: ${safe.outcome_phase}`,
|
|
32
|
+
`- scope_revision: ${safe.scope_revision}`,
|
|
23
33
|
`- current_gate: ${safe.current_gate}`,
|
|
24
34
|
`- enforcement: ${safe.enforcement.level}`,
|
|
25
35
|
`- recommendation: ${recommendation}`,
|
|
26
36
|
`- stopping_reason: ${safe.stopping_reason}`,
|
|
27
37
|
`- evaluations: ${safe.budgets.evaluations}`,
|
|
38
|
+
`- evaluation_attempts: ${safe.provenance.evaluation_attempts}`,
|
|
39
|
+
`- invalid_evaluations: ${safe.provenance.invalid_evaluations}`,
|
|
28
40
|
`- generation_status: ${safe.generation?.status ?? "legacy_deterministic"}`,
|
|
29
41
|
`- generated_candidates: ${safe.generation ? `${safe.generation.accepted}/${safe.generation.returned}` : "0/0"}`,
|
|
30
42
|
`- generation_cost_units: ${safe.generation?.cost_units ?? 0}`,
|