Skip to content

Diagnostics

This page lists every diagnostic the checker emits: one parse diagnostic and 31 semantic ones. Each entry is headed by the exact first line that shp prints, so pasting that line into page search finds its entry. Where the title varies, the heading uses a placeholder such as <kind>, and the entry lists every printed value.

In the index, check stands for every command that runs the semantic checks: shp check, shp coverage, and the language server (shp lsp). shp obligations also lists five of them without failing: missing required context, missing required description, guarded shape changed, invalid reevaluation, and stale design memory.

Printed titleKindEmitted byGroup
error: parse errorparseshp check, coverage, explain, graph, memory, obligations, inspect, and analyze --shape-filesParse and names
error: unknown <kind>unknown_namecheckParse and names
error: ambiguous <kind>ambiguous_namecheckParse and names
error: duplicate <kind>duplicate_declarationcheckParse and names
error: invalid implementationinvalid_implementationcheckParse and names
error: forbidden effectfinal_forbidden_effectcheckEffects and grants
error: missing grantmissing_grantcheckEffects and grants
error: unknown effectsunknown_effectscheck; a warning under --allow-unknown-effectsEffects and grants
error: unsafe effects missing policy metadataunsafe_effectscheckEffects and grants
error: invalid relationinvalid_relationcheckRelations and rules
error: invalid ruleinvalid_rulecheckRelations and rules
error: forbidden pathforbidden_pathcheckRelations and rules
error: forbidden hypercycleforbidden_hypercyclecheckRelations and rules
error: forbidden providesforbidden_providescheckRelations and rules
error: duplicate fingerprintduplicate_fingerprintcheckFingerprints and AST candidates
error: stale fingerprint expectationfingerprint_mismatchcheckFingerprints and AST candidates
error: stale candidate effect pincandidate_pin_fingerprint_mismatchcheckFingerprints and AST candidates
error: invalid candidate effectinvalid_candidate_effectcheckFingerprints and AST candidates
error: governed source changed without current Shape updatemissing_shape_updateshp check --changed-files, shp coverageChange sets
error: bound docs change missingmissing_bound_docs_changeshp check --changed-filesChange sets
warning: stale attestationstale_attestationcheck with --base-ref or --base-modelChange sets
error: missing cited pathmissing_cited_pathshp check --check-cited-pathsChange sets
error: rule looseningrule_looseningshp check --check-looseningChange sets
error: missing required contextmissing_required_contextcheckDesign memory
error: missing required descriptionmissing_required_descriptioncheckDesign memory
error: invalid context targetinvalid_context_targetcheckDesign memory
error: context target mismatchcontext_target_mismatchcheckDesign memory
error: invalid require_contextinvalid_require_contextcheckDesign memory
error: guarded shape changedguarded_shape_changedcheckDesign memory
error: guarded source changedguarded_source_changedshp check --changed-files, shp coverageDesign memory
error: invalid reevaluationinvalid_reevaluationcheckDesign memory
error: stale design memorystale_memoryshp check --as-of or --strict-freshnessDesign memory

Diagnostics judge the declared Shape model. They describe claims in .shape files, not the application source that source and evidence name, which the checker never opens.

Every semantic diagnostic has the same layout. This model grants HardDelete<Revision> and still fails, because a final forbid on the resource’s trait wins over any grant:

module history
resource Revision : AppendOnly
component RevisionLog {
owns Revision
grants Append<Revision>
grants HardDelete<Revision>
fn appendRevision
source ts("src/history/log.ts#appendRevision")
effects complete {
Append<Revision>
evidence ts("src/history/log.ts#appendRevision")
}
fn purgeOldRevisions
source ts("src/history/purge.ts#purgeOldRevisions")
effects complete {
HardDelete<Revision>
evidence ts("src/history/purge.ts#purgeOldRevisions")
}
}

shp check history.shape prints this to stderr and exits 1:

error: forbidden effect
RevisionLog.purgeOldRevisions emits HardDelete<Revision>.
Revision has trait AppendOnly.
AppendOnly forbids final HardDelete<Revision>.
evidence: ts("src/history/purge.ts#purgeOldRevisions")
caused by:
- history.shape: effect RevisionLog.purgeOldRevisions emits HardDelete<Revision>
- history.shape: resource Revision : AppendOnly
- standard prelude: trait AppendOnly forbids final HardDelete<T>
  1. Title. The first line is the severity, error: or warning:, followed by a title that names the kind of claim that failed.
  2. Body. The lines after the blank line state the chain of claims in the model’s own terms: the function emits the effect, the resource has the trait, and the trait forbids that effect finally. Some bodies end with a Required: line or block that names what would satisfy the check.
  3. evidence: Only forbidden effect prints this line, and only when the failing effect entry declares an evidence reference. The reference is copied verbatim.
  4. caused by: The declarations that produced the diagnostic, one per line, as FILE: DECLARATION. FILE is the path as it was passed to shp or discovered, or standard prelude for a built-in declaration such as the prelude AppendOnly. Declaration labels omit module qualifiers. Every semantic diagnostic ends with this block; parse errors do not have one.

The graph rules use the same layout with a different body: the rule, one line per relation in the witness, and a witness: line with the vertex path. Each rule clause reports one shortest witness, so fixing it can reveal the next; see Relations and Graph Rules.

Names. Most bodies print local names. A few print a raw, module-qualified name, and the outputs on this page show exactly where: the relation in invalid relation, the reevaluation in invalid reevaluation, the candidate in invalid candidate effect, the context in context target mismatch, the binding in bound docs change missing, the implementation in governed source changed without current Shape update, and the matches: list in ambiguous <kind>. forbidden path qualifies only the names that collide across modules.

Order. Semantic diagnostics are sorted by kind code, then by rendered text in codepoint order, and separated by a blank line, so the order of declarations and files never decides the order of the output.

Parse errors. When any file fails to parse or cannot be read, shp check reports only the parse errors and exits 2 without running a semantic check. Parse errors are not sorted; they appear in input-file order.

Streams. Failing output goes to stderr with exit 1. When the only diagnostics are warnings, warning: unknown effects under --allow-unknown-effects or warning: stale attestation, they go to stdout, followed by Shape check passed with warnings., with exit 0. The full exit-code contract is in CLI Reference.

shp analyze warnings and shp author critic advisories are not checker diagnostics. They are advisory hints from separate tools and are not listed here; see Analyzer Hints and Author Updates with an Agent.

Kind parse · emitted by shp check, coverage, explain, graph, memory, obligations, inspect, and analyze --shape-files · exit 2

error: parse error
history.shape:10:5: Expecting token of type '}' but found `effects`.

Cause. The parser rejected the file, here because a function declares a second effects block. The location is FILE:LINE:COLUMN:, or FILE: alone when no position is known. A file that cannot be read produces the same title with the read error, for example missing.shape: ENOENT: no such file or directory, open 'missing.shape'. One diagnostic is printed per problem, and no semantic check runs.

Three other tools report the same parser problem in their own form:

  • shp fmt prints history.shape: Expecting token of type '}' but found `effects`. and exits 1.
  • shp author --critic-prompt prints error: failed to parse history.shape:10:5: Expecting token of type '}' but found `effects`. and exits 2.
  • The language server publishes only the message, at the reported position.

Fix. Correct the syntax at the reported position. Every declaration form and the reserved keywords are listed in Language Syntax.

Kind unknown_name · emitted by check

error: unknown relation_endpoint
relation_endpoint GhostService is referenced but not declared.
caused by:
- editor.shape: relation EditorCallsGhost

Cause. A reference names nothing of the expected kind in the loaded Shape model. The printed title depends on where the reference appears:

Printed titleReference
error: unknown resourceowns; the target of an effect in effects complete; a concrete target in a trait or rule forbid; a forbid provides target; an effect candidate effect target or pin resource
error: unknown componentconforms_to; forbid provides … except; the fn of an effect candidate; the component of an add fn or modify fn entry in a change block
error: unknown traita trait on a resource, component, or function; the trait in a rule’s when … has
error: unknown relation_endpointa relation endpoint that is neither a component nor a resource; a forbid path endpoint

An effect candidate whose fn names an undeclared function is reported as unknown component with the function as the name, for example component RevisionLog.missing is referenced but not declared. A candidate with no fn member is reported as component NAME function is referenced but not declared., next to invalid candidate effect. Not every reference is name-checked: grants targets, function requires terms, and the component of a remove fn entry can name undeclared declarations without a diagnostic.

Fix. Declare the missing name, correct the spelling, add the import for its module, or qualify the reference as module::Name.

Kind ambiguous_name · emitted by check

This output comes from three files: history.shape and billing.shape each declare component Store, and app.shape imports both modules and writes conforms_to Store.

error: ambiguous component
component Store matches more than one imported declaration.
Use a module-qualified reference.
matches: billing::Store, history::Store
caused by:
- app.shape: component reference Store
error: unknown component
component Store is referenced but not declared.
caused by:
- app.shape: implementation StoreImpl

Cause. An unqualified name is not declared in the referencing module and matches declarations in more than one imported module. A declaration in the referencing module always wins over imports, so it never causes this diagnostic. <kind> is the kind the reference expects: resource, component, trait, or relation_endpoint for most references, and relation, implementation, binding, rule, rationale, or memory for a context target, a satisfies, or a change entry that names one. The ambiguous reference resolves to nothing, so an unknown <kind> for the same name usually follows, as above.

Fix. Qualify the reference, as in conforms_to history::Store, or remove one of the imports.

Kind duplicate_declaration · emitted by check

error: duplicate component
component RevisionLog is declared more than once.
caused by:
- history.shape: component RevisionLog
- history.shape: component RevisionLog

Cause. One module declares the same name twice for one kind. <kind> is resource, trait, component, relation, candidate_effect, binding, rationale, memory, or reevaluation. The first declaration, in file order and then declaration order, is kept and the later one is ignored, so diagnostics that only the later one would cause do not appear. Equal names in different modules are not duplicates, and a trait with a prelude trait’s name shadows the prelude trait instead. Duplicate implementation, rule, and attest declarations are not reported, and a second fn with the same name in one component silently replaces the first.

Fix. Remove or rename one declaration.

Kind invalid_implementation · emitted by check

error: invalid implementation
implementation RevisionLogImpl is invalid: on_change require shape_delta is not a supported requirement; expected shape_update.
caused by:
- history.shape: implementation RevisionLogImpl on_change require shape_delta

Cause. An implementation declares an on_change require value other than shape_update, the only supported requirement. Coverage acts only on shape_update, so an unknown value, such as a typo or the pre-rename spelling shape_delta, would otherwise leave the implementation’s paths silently ungoverned.

Fix. Replace the value with shape_update, or remove the on_change member if the paths should be mapped to a component without a coverage obligation.

How effects, traits, and grants interact is explained in Effect Model.

Kind final_forbidden_effect · emitted by check

The annotated output under Reading a diagnostic is this diagnostic.

Cause. A function’s effect entry targets a resource, and a trait of that resource, or a rule that matches it, declares forbid final for that effect. This check runs before the grant check, so a matching grants does not help, and no missing grant is reported for the entry. For a rule-derived forbid, the trait line names the rule’s first when trait. An effect without a <Resource> target is never checked.

Fix. Remove the effect, move the behaviour to a resource without the trait, or change the resource’s traits or the forbidding trait or rule. Nothing waives a final forbid: grants, rationale, memory, reevaluations, attestations, and imports cannot.

Kind missing_grant · emitted by check

error: missing grant
RevisionLog.appendRevision emits Append<Revision>.
RevisionLog does not grant Append<Revision>.
caused by:
- history.shape: effect RevisionLog.appendRevision emits Append<Revision>
- history.shape: component RevisionLog

Cause. A function’s effect entry has a <Resource> target, no final forbid matches it, and the function’s component has no grants with the same effect name and target. owns does not imply any grant.

Fix. Add grants Append<Revision> to the component only if the component may perform that effect; otherwise remove the effect or move the function.

Kind unknown_effects · emitted by check; printed as warning: unknown effects under shp check --allow-unknown-effects

error: unknown effects
RevisionLog.appendRevision declares effects unknown.
caused by:
- history.shape: fn RevisionLog.appendRevision

Cause. A function in an authored module declares effects unknown. Strict checking always rejects it; no declaration in the model allows it. Functions in generated AST modules are exempt entirely: the module name must be shape.generated.ast or start with shape.generated.ast., and the file must be under shape/generated/ast/.

Fix. Replace the placeholder with a reviewed effects complete { … } summary. While drafting, --allow-unknown-effects turns the error into a warning. The exemption is described in Generate Drafts from Source.

error: unsafe effects missing policy metadata

Section titled “error: unsafe effects missing policy metadata”

Kind unsafe_effects · emitted by check

error: unsafe effects missing policy metadata
RevisionLog.importLegacyRevisions declares unsafe effects.
Missing: expires, required capability.
caused by:
- history.shape: fn RevisionLog.importLegacyRevisions

Cause. A function marked unsafe lacks at least one of reason "…", expires "…", and a requires Capability term. Missing: lists the absent items in the order reason, expires, required capability. The values are not interpreted.

Fix. Add the missing members after the function’s effects block, as shown under fn in Language Syntax.

Relation kinds, traversal, and witness selection are explained in Relations and Graph Rules.

Kind invalid_relation · emitted by check

error: invalid relation
relation editor::EditorCallsLog is invalid: kind calls requires exactly two endpoints.
caused by:
- editor.shape: relation EditorCallsLog

Cause. A relation declaration is malformed. These reasons drop the relation from the hypergraph:

  • missing kind
  • missing connects
  • duplicate endpoint X
  • kind K requires exactly two endpoints, for calls, callbacks, and provides
  • kind K requires ordered connects (A -> B), for calls, callbacks, and provides written with { … }
  • kind K requires ordered connects (A -> B -> ...), for coordinated_call written with { … }

These reasons keep the relation, ignoring the offending member where there is one:

  • duplicate kind, duplicate connects, duplicate roles, duplicate summary
  • role X is not a connects endpoint, duplicate role for X
  • endpoint X resolves to both a component and a resource
  • provides provider X must be a component, provides target X must be a resource
  • fingerprint expectation X is not a connects endpoint
  • fingerprint expectation endpoint X must be a resource
  • fingerprint expectation endpoint X resolves to both a component and a resource

Fix. Correct the named member. Custom kinds accept any arity and either connects form.

Kind invalid_rule · emitted by check

error: invalid rule
rule no_multi_subject_delete is invalid: final effect forbids may bind only one subject, but found T, U.
caused by:
- rules.shape: rule no_multi_subject_delete

Cause. A rule cannot perform the check it declares. The reasons are:

  • final effect forbids require exactly one when subject: the rule has a forbid final but no when.
  • final effect forbids may bind only one subject, but found T, U: its when clauses name different subjects. Repeated clauses with one subject are a conjunction and are valid.
  • rule condition trait X declares N type parameters; expected no type parameters or exactly one Resource-bound parameter
  • rule condition trait X type parameter T is unbound; expected Resource
  • rule condition trait X type parameter T has incompatible bound B; expected Resource
  • forbidden path endpoints must be distinct; use forbid hypercycle for cycles
  • relation kind K has no directed traversal semantics, or relation kinds K, L have no directed traversal semantics: a forbid path lists a kind other than calls, callbacks, provides, or coordinated_call.
  • path endpoint X resolves to both a component and a resource

Only the offending part of an invalid rule is inert: an invalid final-forbid rule derives no forbid, and an invalid forbid path clause is not evaluated.

Fix. Bind one subject, give a condition trait no type parameter or one Resource-bound parameter, use forbid hypercycle for cycles, and list only traversable kinds in forbid path.

Kind forbidden_path · emitted by check

error: forbidden path
rule no_feed_to_drafts rejects this dependency path:
calls FeedCallsRecommender: Feed -> Recommender
provides RecommenderProvidesDrafts: Recommender -> PrivateDraft
witness: Feed -> Recommender -> PrivateDraft
caused by:
- feed.shape: rule no_feed_to_drafts forbids path Feed -> PrivateDraft over calls or provides
- feed.shape: relation FeedCallsRecommender
- feed.shape: relation RecommenderProvidesDrafts

Cause. A forbid path SOURCE -> TARGET over KIND … clause found a directed path from SOURCE to TARGET whose every step uses a listed kind. Each step line reads KIND RELATION: FROM -> TO. The clause reports its one fewest-step witness. Relations with an unresolved or ambiguous endpoint, and provides relations with invalid endpoint kinds, contribute no steps.

Fix. Remove or redirect a relation on the witness, narrow the rule’s kind list, or revise the rule.

Kind forbidden_hypercycle · emitted by check

error: forbidden hypercycle
rule no_runtime_cycle rejects this hypercycle:
calls EditorCallsLog
callbacks LogCallsEditor
witness: Editor -> RevisionLog -> Editor
caused by:
- editor.shape: rule no_runtime_cycle forbids hypercycle over calls or callbacks
- editor.shape: relation EditorCallsLog
- editor.shape: relation LogCallsEditor

Cause. A forbid hypercycle clause found a directed cycle among relations of the listed kinds, or of every kind when over is omitted. The relation lines follow the witness walk, which starts at the codepoint-smallest vertex, and the witness: line ends where it began. Each clause reports its one shortest cycle. Custom kinds contribute no steps, so over with only custom kinds is accepted but never matches.

Fix. Remove or redirect one relation in the cycle, or narrow the rule’s kind list.

Kind forbidden_provides · emitted by check

error: forbidden provides
Preview provides StoryEndpoint via relation PreviewProvidesStories.
rule publisher_only_story_endpoint forbids provides StoryEndpoint except Publisher.
caused by:
- publishing.shape: relation PreviewProvidesStories
- publishing.shape: rule publisher_only_story_endpoint forbids provides StoryEndpoint

Cause. A forbid provides RESOURCE except COMPONENT clause found a provides relation that supplies RESOURCE from a provider other than COMPONENT. except is optional; without it, every provider is rejected and the second line reads, for example, rule no_story_endpoint forbids provides StoryEndpoint. One diagnostic is emitted per offending relation.

Fix. Move the provides relation onto the allowed component, or change the rule.

Fingerprints and candidate effects come from generated AST drafts; see Generate Drafts from Source.

Kind duplicate_fingerprint · emitted by check

error: duplicate fingerprint
resource RevisionLogAstAnchor declares fingerprint provider ast.semantic_subtree_v1 more than once.
caused by:
- history.shape: resource RevisionLogAstAnchor fingerprint ast.semantic_subtree_v1
- history.shape: resource RevisionLogAstAnchor fingerprint ast.semantic_subtree_v1

Cause. One resource declares two fingerprint members with the same provider. The first is used and the later one is ignored.

Fix. Keep one fingerprint per provider.

Kind fingerprint_mismatch · emitted by check

error: stale fingerprint expectation
relation ReviewedFromAst expects RevisionLogAstAnchor fingerprint ast.semantic_subtree_v1.
expected: sha256:aaaa
actual: sha256:bbbb
caused by:
- history.shape: relation ReviewedFromAst expects RevisionLogAstAnchor fingerprint ast.semantic_subtree_v1
- history.shape: resource RevisionLogAstAnchor
- history.shape: resource RevisionLogAstAnchor fingerprint ast.semantic_subtree_v1

Cause. A relation’s expects ENDPOINT fingerprint PROVIDER("VALUE") names a resource endpoint whose fingerprint for that provider differs, or is absent, which prints actual: missing. An expects endpoint that is not one of the relation’s connects endpoints, or is not a resource, is reported as invalid relation instead.

Fix. Regenerate the AST drafts, review the changed code the anchor points at, then update the pinned value or revise the claim that depends on it.

Kind candidate_pin_fingerprint_mismatch · emitted by check

error: stale candidate effect pin
candidate effect AppendRevisionCandidate pins RevisionLogAppendRevisionAstAnchor fingerprint ast.semantic_subtree_v1.
expected: sha256:aaaa
actual: sha256:bbbb
caused by:
- history.shape: effect candidate AppendRevisionCandidate
- history.shape: resource RevisionLogAppendRevisionAstAnchor
- history.shape: resource RevisionLogAppendRevisionAstAnchor fingerprint ast.semantic_subtree_v1

Cause. An effect candidate’s pin RESOURCE fingerprint PROVIDER("VALUE") no longer matches that resource’s fingerprint, or the resource has none (actual: missing). A pin resource that is not declared is reported as unknown resource instead.

Fix. Regenerate the AST drafts so the candidate and its anchor agree.

Kind invalid_candidate_effect · emitted by check

error: invalid candidate effect
candidate effect history::AppendRevisionCandidate: missing pin.
caused by:
- history.shape: effect candidate AppendRevisionCandidate

Cause. Each effect candidate needs exactly one each of fn, effect, source, confidence, and pin. The reason is missing FIELD or duplicate FIELD, with one diagnostic per problem.

Fix. Supply each member once, or regenerate the draft.

These diagnostics compare the model with a change. The first two need a changed-file list, stale attestation needs a base model, and missing cited path needs the repository’s file list. What counts as a current update, attestation, or bound change is defined in Keep the Model Current.

error: governed source changed without current Shape update

Section titled “error: governed source changed without current Shape update”

Kind missing_shape_update · emitted by shp check --changed-files and shp coverage

error: governed source changed without current Shape update
Changed file: src/history/purge.ts
Governed by: history::RevisionLogImpl
Matched path: src/history/**/*.ts
Required: update a current .shape file with matching source/evidence, or add a no_shape_change attestation.
caused by:
- shape/history.shape: implementation RevisionLogImpl
- shape/history.shape: implementation RevisionLogImpl path src/history/**/*.ts

Cause. A changed path that does not end in .shape matches a paths glob of an implementation with on_change require shape_update, and nothing current covers it. Matched path: is the first matching glob. The path counts as covered only when either exists:

  • a function source, or an effect evidence, naming exactly that path, ignoring any #anchor and :line or :line-line suffix, in a .shape file that is itself in the changed-file list and whose module is not generated AST; or
  • a current attest no_shape_change whose source names exactly that path and whose reason is not empty. With a base model (--base-ref or --base-model), current means its kind, path, and reason are new relative to the base; without one, it means its .shape file is in the changed-file list.

Fix. Update the claim for that path in a .shape file included in the change, or, when the architecture did not change, add a narrow attest no_shape_change for it written for this change.

Kind missing_bound_docs_change · emitted by shp check --changed-files only

error: bound docs change missing
binding repo::CheckerDocs was triggered by packages/shp-checker/src/checker/rules.ts.
Required: change one of docs-site/src/content/docs/reference/diagnostics.md, or add attest docs_not_needed.
caused by:
- shape/repo.shape: binding CheckerDocs
- shape/repo.shape: binding CheckerDocs when_changed packages/shp-checker/src/checker/**/*.ts

Cause. A changed path matches a when_changed glob of a binding, no changed path matches any of its require_changed globs, and the triggering path has no current attestation of a kind the binding lists in allow attest. One diagnostic is emitted per triggering path. Without allow attest, the Required: line ends after the path list; with several kinds, they are joined with or.

Fix. Change one of the required paths in the same change set, or add a current attestation of an allowed kind whose source is the triggering path, with a non-empty reason, as described for missing_shape_update above.

Kind stale_attestation · emitted by check when given --base-ref or --base-model; never fails the check

warning: stale attestation
attest no_shape_change for src/history/reporting.ts is unchanged from the base model, so it no longer satisfies coverage or bindings.
Remove it with `shp attest prune`; git history keeps the decision.
caused by:
- shape/history.shape: attest no_shape_change for src/history/reporting.ts

Cause. An attestation with the same kind, path, and reason already exists in the base model. It was carried over from an earlier change, so it no longer satisfies coverage or bindings.

Fix. Run shp attest prune with the same --base-ref or --base-model to delete every stale attestation at once. If its path changed again in this change set and the contract is still unchanged, write a new attestation with a reason for this change.

Kind missing_cited_path · emitted by shp check --check-cited-paths

error: missing cited path
docs-site/src/content/docs/guides/renamed-away.md is cited by the model but is not in the repository.
Update the citation to the file's new path, or remove it if the file is gone.
caused by:
- shape/docs.shape: effect DocsSite.verifyDocs emits Read<DocsContent>

Cause. A source, evidence, or observed path cited by a function (generated or authored), candidate effect, rationale, memory, or reevaluation is not a file in the repository, usually because the file was renamed or deleted without updating the model. caused by names every declaration that cites the path. Attestation sources are not checked, since attesting a deletion names a removed file.

Fix. Point the citation at the file’s new path, or remove the citation if the file is gone.

Kind rule_loosening · emitted by shp check --check-loosening with --base-ref or --base-model

error: rule loosening
This change removes trait AppendOnly from resource Revision.
With the base version restored, the check fails:
error: forbidden effect
RevisionLog.purgeOldRevisions emits HardDelete<Revision>.
Revision has trait AppendOnly.
AppendOnly forbids final HardDelete<Revision>.
evidence: ts("src/history/purge.ts#purgeOldRevisions")
caused by:
- shape/history.shape: effect RevisionLog.purgeOldRevisions emits HardDelete<Revision>
- shape/history.shape: resource Revision : AppendOnly
- standard prelude: trait AppendOnly forbids final HardDelete<T>
Restore the base version, or have the people who own this architecture approve the loosening.
caused by:
- base shape/history.shape: resource Revision : AppendOnly
- shape/history.shape: resource Revision

Cause. The change removed or edited a declaration in the rule layer (a trait, rule, memory, rationale, implementation, binding, role, or policy), or removed a trait from a resource, component, or function. With that edit put back to its base version, the check reports the quoted error, so the edit is what lets the model pass. Here a nightly job deletes old revisions, and the change removed AppendOnly from Revision so that the final forbid no longer applies. The first line says what the change did: removes, edits, or removes trait. The quoted error is the one the edit silenced, and caused by names the declaration at the base and in the change. Rule loosening describes how edits are found and which errors count.

Fix. If nobody asked for the behaviour the rule forbids, restore the base version and change the code instead. If a person did ask for it, the loosening is a design decision: have the people who own the architecture approve it, then run the check without --check-loosening for that change. How they approve is a CI policy; Run Shape in CI shows one.

Shape traits, rationale, memory, guards, and reevaluations are explained in Design Memory.

Kind missing_required_context · emitted by check

error: missing required context
fn Editor.mergeAutosaves has shape PreserveInline.
PreserveInline requires InlineRationale<fn Editor.mergeAutosaves>.
No matching rationale or memory found.
caused by:
- editor.shape: fn Editor.mergeAutosaves : PreserveInline
- standard prelude: PreserveInline requires InlineRationale

Cause. A function, component, or resource carries a shape trait whose context obligation is unmet. The obligation is met only by a context of the named type, of a kind the trait accepts, whose type target equals the target and whose applies_to, when present, equals it too. Each prelude trait fixes the accepted kinds; for example, PreserveInline accepts only a rationale and RefactorSensitive only a memory. A trait that declares its own require_context produces the same diagnostic, and its caused by: names that trait instead of the standard prelude.

Fix. Add a rationale or memory of the named context type, of an accepted kind, for the same target.

Kind missing_required_description · emitted by check

error: missing required description
fn Editor.mergeAutosaves has shape RequiresDescription.
RequiresDescription requires a description.
caused by:
- editor.shape: fn Editor.mergeAutosaves : RequiresDescription
- standard prelude: RequiresDescription requires description

Cause. A function has the RequiresDescription trait but no non-empty description, or declares description required "" with an empty string. The second form prints fn Editor.summarise has shape description required. RequiresDescription also requires a DescriptionRationale, which is reported separately as missing required context.

Fix. Give the function a non-empty description "…".

Kind invalid_context_target · emitted by check

error: invalid context target
memory MergeRefactorConstraint applies to fn Editor.missingFn,
but that target is not declared.
caused by:
- editor.shape: memory MergeRefactorConstraint

Cause. The target in a rationale or memory type, or its applies_to target, does not exist. A target is fn, component, resource, implementation, rule, or relation. A change block that removes the target also produces this diagnostic for every context still attached to it.

Fix. Correct the target, declare it, or remove the context.

Kind context_target_mismatch · emitted by check

error: context target mismatch
rationale editor::MergeAutosavesInline declares fn Editor.mergeAutosaves,
but applies_to references fn Editor.otherMerge.
caused by:
- editor.shape: rationale MergeAutosavesInline

Cause. The target in the context type and the applies_to target differ. Such a context satisfies no obligation, so a missing required context for the intended target can accompany this diagnostic.

Fix. Make both targets identical, or drop applies_to.

Kind invalid_require_context · emitted by check

error: invalid require_context
trait ComponentBoundary require_context BoundaryReason<X> is invalid: type parameter X is not declared by the trait.
caused by:
- editor.shape: trait ComponentBoundary require_context BoundaryReason<X>

Cause. A trait’s require_context TYPE<T> names a type parameter the trait does not declare, or one whose bound is not Fn, Function, Component, or Resource. The second reason reads type parameter T has unsupported bound B (expected Fn, Component, or Resource). The obligation is dropped rather than silently attached to the wrong target.

Fix. Name a declared type parameter and bound it with Fn, Component, or Resource, or leave it unbound to target functions.

Kind guarded_shape_changed · emitted by check

error: guarded shape changed
fn Editor.mergeAutosaves is protected by memory MergeRefactorConstraint.
This change modifies the guarded target.
Required:
add reevaluation satisfying memory MergeRefactorConstraint
or preserve the protected shape.
caused by:
- editor.shape: change RefactorMerge modify fn Editor.mergeAutosaves
- editor.shape: memory MergeRefactorConstraint guards on_change require ReEvaluation<Self>

Cause. A modify or remove entry in a change block targets a function, component, resource, or relation that a rationale or memory guards, and no valid reevaluation satisfies that context. Editing a declaration in place produces no change event and never triggers this diagnostic. The second line says which guard fired:

  • This change modifies the guarded target. for on_change require ReEvaluation<Self> when the context has no protects entries or any entry is not detectable;
  • This change removes shape trait X from the guarded target. or This change removes description from the guarded target. when every protects entry is detectable and the change removes one;
  • This change applies the L transform to the guarded target. for forbid transform L when a modify fn declares transform L.

Fix. Add a valid reevaluation that satisfies the named context, or keep the protected shape. An attestation never satisfies a guard.

Kind guarded_source_changed · emitted by shp check --changed-files and shp coverage

error: guarded source changed
src/editor/merge.ts changed. It is the source of fn Editor.mergeAutosaves, which is protected by memory MergeRefactorConstraint.
Required:
add reevaluation satisfying memory MergeRefactorConstraint in this change
or leave src/editor/merge.ts unchanged.
caused by:
- shape/editor.shape: fn Editor.mergeAutosaves
- shape/editor.shape: memory MergeRefactorConstraint guards on_change require ReEvaluation<Self>

Cause. A changed file is the source of a function that a rationale or memory guards with on_change require ReEvaluation, and no valid reevaluation of that context was written for this change: new relative to the base model when there is one, or declared in a changed .shape file when there is not. caused by names the function and the guard clause. When the guarded code changes lists the guards that do not fire this way.

Fix. Review the change against the context’s summary, then add a reevaluation that satisfies it and records the review, with its evidence. A reevaluation carried over from an earlier change does not count, so write a new one rather than editing the model around the guard. If the edit was not meant to touch the guarded function, move it out of that file or undo it.

Kind invalid_reevaluation · emitted by check

error: invalid reevaluation
reevaluation editor::MergeRechecked is invalid: missing evidence.
caused by:
- editor.shape: reevaluation MergeRechecked

Cause. A reevaluation is incomplete. Each reason is its own diagnostic:

  • missing satisfies, or unknown satisfied memory / unknown satisfied rationale when the named context does not exist;
  • missing outcome, missing summary (absent or blank), missing evidence, missing reviewer, missing decided_on;
  • missing approver required by policy, when a policy { require approver } exists and the satisfied memory is sensitive;
  • unknown reviewer role X, unknown approver role X, once any role is declared.

An invalid reevaluation satisfies no guard.

Fix. Supply the missing members, declare the role, or correct the satisfies name.

Kind stale_memory · emitted by shp check --as-of or --strict-freshness; listed by shp obligations with the same flags

error: stale design memory
memory MergeRefactorConstraint protects fn Editor.mergeAutosaves.
Its review_by date 2026-01-01 is before 2026-05-30.
Required:
review the design memory and update review_by, or replace it with a reevaluation.
caused by:
- editor.shape: memory MergeRefactorConstraint

Cause. Freshness checking is on and a rationale or memory has a valid ISO review_by date strictly before the reference date. Without the freshness flags this diagnostic never appears; the flags are described in CLI Reference.

Fix. Review the entry and move its review_by forward, or remove the date. A reevaluation that satisfies the entry does not clear this diagnostic.