CANP-WP-0002 T01: input defaults, static and derived
Closes the gap that made optional inputs unusable: rendering rule 5.1(4) made any unresolved placeholder an error while inputs had no `default`, so an input marked `required: false` and referenced from the template failed every render in which the caller omitted it — including the spec's own section 4 example. Section 10 already carried the derivation mechanism (`requirement: generate`, resolution deliberately undefined), so a derived default needed a binding rather than a new concept: the input's default names a declared prompt dependency. Spec: - 5.1 rewritten as "Resolution and rendering". Resolution may be non-deterministic and must report what it derived; rendering is deterministic and must not derive. A tool that handles only supplied values and static defaults is stated to be conforming. - 6.1 (new) covers both declaration forms. Reference form is preferred, with the reason stated — an inline prompt is anonymous, so unversioned, unprovenanced and un-evaluable — and validators should warn when a published package derives inline. - A derived default may declare a static fallback `value`. Without one the input stays unresolved, which is an error; derivation never silently yields empty content. - 4, 10, 18 (rules 11-13), 19 (two new MUST NOTs), 21 updated accordingly. Reference CLI: - New `resolve` verb reporting the origin of every value. - `Resolution` dataclass and `resolve_inputs`; `resolve_values` kept as a wrapper so existing callers are unaffected. - `render` refuses with a specific error naming underivable inputs rather than substituting empty text. - Tests 3 -> 11. Example package lifecycle re-verified end to end. INTENT.md is unchanged: splitting resolve from render preserves success criterion 4 (deterministic rendering) as written. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Bjefh8NUiEiahN4JLwoSKM Assistant: claude-code Assistant-Model: opus Assistant-Process: 388925@bnt-lap001 Assistant-Session: 3507023f-e0fd-4a1e-9d90-a0d4217d1502
This commit is contained in:
parent
0caf065544
commit
169db25d25
6 changed files with 600 additions and 36 deletions
|
|
@ -163,6 +163,9 @@ inputs:
|
|||
type: content
|
||||
required: false
|
||||
description: Optional surrounding repository context.
|
||||
default:
|
||||
derive: context/repository-summary
|
||||
value: "(no repository context provided)"
|
||||
|
||||
parameters:
|
||||
depth:
|
||||
|
|
@ -186,7 +189,10 @@ compatibility:
|
|||
providers: []
|
||||
|
||||
dependencies:
|
||||
prompts: []
|
||||
prompts:
|
||||
- id: context/repository-summary
|
||||
version: 1.0.0
|
||||
requirement: generate
|
||||
context: []
|
||||
capabilities: []
|
||||
|
||||
|
|
@ -235,14 +241,44 @@ Review the following change at {{ depth }} depth.
|
|||
{{ change }}
|
||||
```
|
||||
|
||||
### 5.1 Rendering rules
|
||||
### 5.1 Resolution and rendering
|
||||
|
||||
Producing a final prompt is two steps:
|
||||
|
||||
1. **Resolve** — determine a value for every declared input and parameter.
|
||||
2. **Render** — substitute those values into the template as text.
|
||||
|
||||
The steps are separate because only the first may be non-deterministic.
|
||||
**Rendering is deterministic:** the same resolved values and the same template
|
||||
always produce the same output. A consumer that satisfies a derived default
|
||||
(§ 6.1) does so during resolution, never during rendering.
|
||||
|
||||
**Resolution rules:**
|
||||
|
||||
1. Call-supplied values override defaults.
|
||||
2. A declared parameter default is used when no call value is supplied.
|
||||
3. A required input without a value is an error.
|
||||
4. A placeholder with no resolved value is an error.
|
||||
5. Values are substituted as text in v0.1.
|
||||
6. Template evaluation MUST NOT execute arbitrary code.
|
||||
3. A declared static input default is used when no call value is supplied.
|
||||
4. A required input without a value is an error.
|
||||
5. A derived input default is satisfied only by a consumer that is able and
|
||||
permitted to derive it. A consumer that does not derive uses the default's
|
||||
static fallback `value` when one is declared, and otherwise leaves the
|
||||
input unresolved.
|
||||
6. Resolution MUST report which values were derived, so that a caller can see
|
||||
what was added on its behalf before the prompt is used.
|
||||
|
||||
**Rendering rules:**
|
||||
|
||||
7. Values are substituted as text in v0.1.
|
||||
8. A placeholder with no resolved value is an error.
|
||||
9. Template evaluation MUST NOT execute arbitrary code.
|
||||
10. Rendering MUST NOT derive values. A tool offering derivation MUST perform
|
||||
it as a distinct resolve step whose results are visible to the caller
|
||||
before rendering.
|
||||
|
||||
A minimal implementation may implement resolution for supplied values and
|
||||
static defaults only. Such a tool is conforming: it reports an input with an
|
||||
unsatisfied derived default and no static fallback as unresolved, which
|
||||
rule 8 makes an error.
|
||||
|
||||
CPF v0.1 does not define conditionals, loops, filters, or functions. Implementations MAY offer richer rendering modes only when explicitly declared by an extension; they MUST NOT silently reinterpret a v0.1 template as executable code.
|
||||
|
||||
|
|
@ -266,6 +302,7 @@ Fields:
|
|||
| `type` | no | Suggested semantic type; defaults to `content` |
|
||||
| `required` | no | Whether a caller must supply it; defaults to `false` |
|
||||
| `description` | no | Human-readable explanation |
|
||||
| `default` | no | Value used when the caller supplies none; see § 6.1 |
|
||||
|
||||
Recommended v0.1 input types are:
|
||||
|
||||
|
|
@ -277,6 +314,94 @@ Recommended v0.1 input types are:
|
|||
|
||||
These are descriptive hints in v0.1. A runtime MAY use them for validation or adapters.
|
||||
|
||||
### 6.1 Input defaults
|
||||
|
||||
An input MAY declare a `default`, used when the caller supplies no value.
|
||||
|
||||
`default` MUST NOT be combined with `required: true`: a required input is always
|
||||
supplied by the caller, so a default could never apply.
|
||||
|
||||
Without this field an optional input is close to unusable. Rendering rule 8
|
||||
makes an unresolved placeholder an error, so an input marked `required: false`
|
||||
and referenced from the template would fail every render in which the caller
|
||||
omitted it.
|
||||
|
||||
A default takes one of two forms.
|
||||
|
||||
#### Static default
|
||||
|
||||
A literal value, used as-is:
|
||||
|
||||
```yaml
|
||||
inputs:
|
||||
- name: repository_context
|
||||
type: content
|
||||
required: false
|
||||
default: "(no repository context provided)"
|
||||
```
|
||||
|
||||
Every conforming implementation supports static defaults.
|
||||
|
||||
#### Derived default
|
||||
|
||||
A declaration that the value **may** be produced from available context by a
|
||||
consumer able to do so. It is a request to the consumer, not an instruction the
|
||||
package executes.
|
||||
|
||||
The preferred form references a package already declared in
|
||||
`dependencies.prompts` with `requirement: generate` (§ 10):
|
||||
|
||||
```yaml
|
||||
dependencies:
|
||||
prompts:
|
||||
- id: context/repository-summary
|
||||
version: 1.0.0
|
||||
requirement: generate
|
||||
|
||||
inputs:
|
||||
- name: repository_context
|
||||
type: content
|
||||
required: false
|
||||
default:
|
||||
derive: context/repository-summary
|
||||
value: "(no repository context provided)"
|
||||
```
|
||||
|
||||
A derivation prompt MAY instead be written inline:
|
||||
|
||||
```yaml
|
||||
inputs:
|
||||
- name: repository_context
|
||||
type: content
|
||||
required: false
|
||||
default:
|
||||
derive:
|
||||
prompt: |
|
||||
Summarize the repository this prompt is being run against,
|
||||
in under 200 words.
|
||||
value: "(no repository context provided)"
|
||||
```
|
||||
|
||||
`derive` is therefore either a string naming a declared prompt dependency, or a
|
||||
mapping carrying an inline `prompt`. A single default MUST NOT use both.
|
||||
|
||||
Prefer the reference form wherever the derivation is worth keeping. An inline
|
||||
prompt is anonymous: it has no version, provenance, examples or evals, and
|
||||
cannot be reused, evaluated or improved independently of its host package —
|
||||
the situation this format exists to replace. Validators SHOULD warn when a
|
||||
**published** package derives inline. Inline derivation is intended for local
|
||||
and draft packages.
|
||||
|
||||
`value` inside a derived default is an optional **static fallback**. Its
|
||||
meaning is defined by resolution rule 5: a consumer that does not derive uses
|
||||
it, and an input with neither a derived value nor a fallback stays unresolved,
|
||||
which rule 8 makes an error. Derivation never silently yields empty content.
|
||||
|
||||
Declaring a derived default does not oblige any consumer to derive anything,
|
||||
and does not make the package depend on a particular resolver, model or
|
||||
runtime. Resolution belongs to the consumer; the package only declares what it
|
||||
would like resolved.
|
||||
|
||||
## 7. Parameters
|
||||
|
||||
`parameters` is an optional mapping keyed by parameter name.
|
||||
|
|
@ -377,6 +502,12 @@ Recommended requirement values:
|
|||
|
||||
This allows richer systems to integrate prompt resolution without forcing simple tools to implement an agent runtime.
|
||||
|
||||
A prompt dependency declared `requirement: generate` is the mechanism behind a
|
||||
referenced derived default (§ 6.1): the input's `default.derive` names the
|
||||
dependency, and a consumer able to generate satisfies both at once. Declaring
|
||||
the dependency records *what* may be generated and at which version; the input
|
||||
default records *where the result lands*. Neither states how generation works.
|
||||
|
||||
## 11. Examples
|
||||
|
||||
`examples` is a list of relative paths.
|
||||
|
|
@ -492,7 +623,14 @@ A v0.1 validator SHOULD verify at least:
|
|||
7. referenced example/eval paths do not escape the package;
|
||||
8. required inputs and parameter names are unique;
|
||||
9. every template placeholder resolves to a declared input or parameter;
|
||||
10. no required value is silently omitted during rendering.
|
||||
10. no required value is silently omitted during rendering;
|
||||
11. no input declares both `default` and `required: true`;
|
||||
12. a derived default declares either a `derive` reference or an inline
|
||||
`derive.prompt`, never both;
|
||||
13. a `derive` reference names a package declared in `dependencies.prompts`.
|
||||
|
||||
A validator SHOULD additionally warn when a package intended for publication
|
||||
declares an inline derivation prompt (§ 6.1).
|
||||
|
||||
## 19. Security requirements
|
||||
|
||||
|
|
@ -502,6 +640,11 @@ Implementations MUST NOT:
|
|||
|
||||
- execute code merely because it appears in a package;
|
||||
- treat template expressions as arbitrary code;
|
||||
- treat a derived default's prompt text as instructions addressed to the
|
||||
consuming tool itself; it is content to be resolved on the package's behalf,
|
||||
and it carries no more authority than any other package text;
|
||||
- derive an input default without the caller being able to see that it
|
||||
happened (§ 5.1 rule 6);
|
||||
- interpolate environment variables or credentials implicitly;
|
||||
- follow paths outside the package without explicit user action;
|
||||
- embed or require secrets in published package metadata.
|
||||
|
|
@ -566,11 +709,17 @@ Commands:
|
|||
add PATH validate and copy a package into the local catalog
|
||||
search QUERY search locally installed package metadata
|
||||
show ID display one installed package manifest
|
||||
resolve ID report the resolved value of every input and parameter
|
||||
render ID render an installed prompt with supplied values
|
||||
publish PATH validate and copy a package into a filesystem registry
|
||||
install ID copy a package version from the registry into the catalog
|
||||
```
|
||||
|
||||
The reference tool never calls a model, so its `resolve` handles supplied
|
||||
values and static defaults only and reports any input whose derived default it
|
||||
cannot satisfy. `render` performs the same resolution and then substitutes;
|
||||
per § 5.1 rule 10 it never derives.
|
||||
|
||||
These semantics are illustrative, not mandatory for other implementations.
|
||||
|
||||
## 22. Worked example
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue