Skip to main content

harn_parser/
diagnostic_codes.rs

1//! Stable diagnostic code registry.
2//!
3//! Codes use `HARN-<CATEGORY>-<NNN>` identifiers so CLI output, editor
4//! diagnostics, docs, and future `harn explain` lookups can refer to one
5//! durable namespace.
6//!
7//! ```
8//! use harn_parser::diagnostic_codes::Category;
9//!
10//! let categories: Vec<_> = Category::ALL.iter().map(|category| category.as_str()).collect();
11//! assert_eq!(
12//!     categories,
13//!     [
14//!         "TYP", "PAR", "NAM", "CAP", "LLM", "ORC", "STD", "PRM",
15//!         "MOD", "RMD", "SUS", "LNT", "FMT", "IMP", "OWN", "RCV",
16//!         "MAT", "POL", "MET", "CST", "CMP",
17//!     ],
18//! );
19//! ```
20
21use std::{fmt, str::FromStr};
22/// Top-level diagnostic category used in a stable Harn diagnostic code.
23#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
24pub enum Category {
25    Typ,
26    Par,
27    Nam,
28    Cap,
29    Llm,
30    Orc,
31    Std,
32    Prm,
33    Mod,
34    Rmd,
35    Sus,
36    Lnt,
37    Fmt,
38    Imp,
39    Own,
40    Rcv,
41    Mat,
42    Pol,
43    /// Meta restrictions for bounded compile-time evaluation (issue #1791).
44    Met,
45    /// Const-eval sandbox limits and capability violations (issue #1791).
46    Cst,
47    /// Structural/codegen errors that prevent bytecode execution and surface
48    /// through both `harn check` and `harn run`.
49    Cmp,
50}
51
52impl Category {
53    pub const ALL: &'static [Category] = &[
54        Category::Typ,
55        Category::Par,
56        Category::Nam,
57        Category::Cap,
58        Category::Llm,
59        Category::Orc,
60        Category::Std,
61        Category::Prm,
62        Category::Mod,
63        Category::Rmd,
64        Category::Sus,
65        Category::Lnt,
66        Category::Fmt,
67        Category::Imp,
68        Category::Own,
69        Category::Rcv,
70        Category::Mat,
71        Category::Pol,
72        Category::Met,
73        Category::Cst,
74        Category::Cmp,
75    ];
76
77    pub const fn as_str(self) -> &'static str {
78        match self {
79            Category::Typ => "TYP",
80            Category::Par => "PAR",
81            Category::Nam => "NAM",
82            Category::Cap => "CAP",
83            Category::Llm => "LLM",
84            Category::Orc => "ORC",
85            Category::Std => "STD",
86            Category::Prm => "PRM",
87            Category::Mod => "MOD",
88            Category::Rmd => "RMD",
89            Category::Sus => "SUS",
90            Category::Lnt => "LNT",
91            Category::Fmt => "FMT",
92            Category::Imp => "IMP",
93            Category::Own => "OWN",
94            Category::Rcv => "RCV",
95            Category::Mat => "MAT",
96            Category::Pol => "POL",
97            Category::Met => "MET",
98            Category::Cst => "CST",
99            Category::Cmp => "CMP",
100        }
101    }
102}
103
104impl fmt::Display for Category {
105    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
106        f.write_str(self.as_str())
107    }
108}
109
110/// One registered diagnostic code.
111#[derive(Debug, Clone, Copy, PartialEq, Eq)]
112pub struct RegistryEntry {
113    pub code: Code,
114    pub identifier: &'static str,
115    pub category: Category,
116    pub summary: &'static str,
117}
118
119macro_rules! diagnostic_codes {
120    ($($variant:ident, $identifier:literal, $category:ident, $summary:literal;)*) => {
121        /// Stable diagnostic identifier.
122        #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
123        pub enum Code {
124            $($variant,)*
125        }
126
127        impl Code {
128            pub const ALL: &'static [Code] = &[
129                $(Code::$variant,)*
130            ];
131
132            pub const fn as_str(self) -> &'static str {
133                match self {
134                    $(Code::$variant => $identifier,)*
135                }
136            }
137
138            pub const fn category(self) -> Category {
139                match self {
140                    $(Code::$variant => Category::$category,)*
141                }
142            }
143
144            pub const fn summary(self) -> &'static str {
145                match self {
146                    $(Code::$variant => $summary,)*
147                }
148            }
149
150            /// Embedded markdown; a missing explanation file fails the build.
151            pub const fn explanation(self) -> &'static str {
152                match self {
153                    $(Code::$variant => include_str!(
154                        concat!("diagnostic_codes/explanations/", $identifier, ".md")
155                    ),)*
156                }
157            }
158        }
159
160        pub const REGISTRY: &[RegistryEntry] = &[
161            $(RegistryEntry {
162                code: Code::$variant,
163                identifier: $identifier,
164                category: Category::$category,
165                summary: $summary,
166            },)*
167        ];
168    };
169}
170
171diagnostic_codes! {
172    TypeMismatch, "HARN-TYP-001", Typ, "expected and actual types are incompatible";
173    InvalidBinaryOperator, "HARN-TYP-002", Typ, "binary operator is not defined for the operand types";
174    StringInterpolationRewrite, "HARN-TYP-003", Typ, "string concatenation should be rewritten as interpolation";
175    ReturnTypeMismatch, "HARN-TYP-004", Typ, "returned expression does not match the declared return type";
176    AssignmentTypeMismatch, "HARN-TYP-005", Typ, "assigned value does not match the target type";
177    ArgumentTypeMismatch, "HARN-TYP-006", Typ, "argument value does not match the parameter type";
178    VariableTypeMismatch, "HARN-TYP-007", Typ, "initializer does not match the declared variable type";
179    ClosureReturnTypeMismatch, "HARN-TYP-008", Typ, "closure return expression does not match its declared type";
180    FieldTypeMismatch, "HARN-TYP-009", Typ, "field value does not match its declared type";
181    MethodTypeMismatch, "HARN-TYP-010", Typ, "method receiver or result type is incompatible";
182    GenericTypeArgumentUnsupported, "HARN-TYP-011", Typ, "callable does not accept type arguments";
183    GenericTypeArgumentMismatch, "HARN-TYP-012", Typ, "type argument does not satisfy the generic parameter";
184    GenericTypeArgumentArity, "HARN-TYP-013", Typ, "generic call has the wrong number of type arguments";
185    TypeParameterArity, "HARN-TYP-014", Typ, "declaration has the wrong number of type parameters";
186    WhereConstraintMismatch, "HARN-TYP-015", Typ, "type argument does not satisfy a where-clause constraint";
187    IterableExpected, "HARN-TYP-016", Typ, "expression must be iterable";
188    InvalidIndexType, "HARN-TYP-017", Typ, "subscript index type is invalid";
189    CallableExpected, "HARN-TYP-018", Typ, "expression must be callable";
190    InvalidCast, "HARN-TYP-019", Typ, "cast cannot be proven valid";
191    UnknownTypeName, "HARN-TYP-020", Typ, "type name cannot be resolved";
192    InvalidVariantUse, "HARN-TYP-021", Typ, "variant type is used in an invalid position";
193    InvalidStructLiteral, "HARN-TYP-022", Typ, "struct literal is invalid";
194    InvalidEnumConstruct, "HARN-TYP-023", Typ, "enum construction is invalid";
195    InvalidPatternBinding, "HARN-TYP-024", Typ, "pattern binding is invalid for the expected type";
196    InvalidOptionalAccess, "HARN-TYP-025", Typ, "optional access is invalid for the receiver type";
197    ThrowsTypeMismatch, "HARN-TYP-026", Typ, "thrown value type is not covered by the callable's declared throws set";
198    TupleIndexOutOfBounds, "HARN-TYP-027", Typ, "constant tuple index is outside the fixed arity";
199    ImplicitAnyParameter, "HARN-TYP-028", Typ, "declared parameter has no type annotation";
200    InvalidTypePredicate, "HARN-TYP-029", Typ, "type predicate contract is invalid";
201    PredicateInputInvalid, "HARN-TYP-030", Typ, "probabilistic predicate input must have a closed serializable type";
202    PredicateBooleanUse, "HARN-TYP-031", Typ, "probabilistic predicate outcome cannot be used as a boolean";
203    PredicateOutcomeUnused, "HARN-TYP-032", Typ, "probabilistic predicate outcome must be consumed";
204    PredicateSiteInvalid, "HARN-TYP-033", Typ, "probabilistic predicate site identity must be literal and unique";
205    PredicateOutcomeUnnarrowed, "HARN-TYP-034", Typ, "probabilistic predicate variant fields require outcome narrowing";
206    PredicateModelOperationMissing, "HARN-TYP-035", Typ, "probabilistic predicate model must declare the decision operation";
207    PredicateQuestionSetInvalid, "HARN-TYP-036", Typ, "probabilistic evaluation question set must be a literal with unique ids and labels";
208    ParserUnexpectedToken, "HARN-PAR-001", Par, "parser found an unexpected token";
209    ParserUnexpectedEof, "HARN-PAR-002", Par, "parser reached end of file while expecting syntax";
210    ParserUnexpectedCharacter, "HARN-PAR-003", Par, "lexer found an unexpected character";
211    ParserUnterminatedString, "HARN-PAR-004", Par, "string literal is unterminated";
212    ParserUnterminatedBlockComment, "HARN-PAR-005", Par, "block comment is unterminated";
213    ParserIntegerLiteralOutOfRange, "HARN-PAR-006", Par, "integer literal is out of range for int (i64)";
214    CompilerError, "HARN-CMP-001", Cmp, "the program failed to compile to bytecode";
215    UndefinedVariable, "HARN-NAM-001", Nam, "variable name cannot be resolved";
216    UndefinedFunction, "HARN-NAM-002", Nam, "function name cannot be resolved";
217    UnknownAttribute, "HARN-NAM-003", Nam, "attribute name is not recognized";
218    UnknownField, "HARN-NAM-004", Nam, "field name does not exist on the target type";
219    UnknownMethod, "HARN-NAM-005", Nam, "method name does not exist on the receiver type";
220    DuplicateArgument, "HARN-NAM-006", Nam, "argument name is duplicated";
221    UnknownBuiltin, "HARN-NAM-008", Nam, "builtin name cannot be resolved";
222    DeprecatedFunction, "HARN-NAM-009", Nam, "function call targets a deprecated declaration";
223    UnknownDeclaration, "HARN-NAM-010", Nam, "declaration reference cannot be resolved";
224    InvalidAttributeTarget, "HARN-NAM-011", Nam, "attribute is attached to an unsupported declaration";
225    InvalidAttributeArgument, "HARN-NAM-012", Nam, "attribute argument is invalid";
226    InvalidMainSignature, "HARN-NAM-101", Nam, "`fn main` must take an explicit `harness: Harness` parameter";
227    CapabilityPayloadInvalid, "HARN-CAP-001", Cap, "capability payload is invalid";
228    CapabilityResultUnchecked, "HARN-CAP-004", Cap, "capability result must be checked";
229    CapabilityUnknownOperation, "HARN-CAP-005", Cap, "host capability operation is not declared";
230    CapabilityCallStaticNameRequired, "HARN-CAP-006", Cap, "host capability call must use a static operation name";
231    CapabilityBindingInvalid, "HARN-CAP-007", Cap, "tool host capability binding is invalid";
232    CapabilityOperationUnserved, "HARN-CAP-008", Cap, "declared host capability operation is not served";
233    EffectInheritanceViolation, "HARN-CAP-301", Cap, "child agent effect set exceeds the parent's declared effects";
234    LlmSchemaMissing, "HARN-LLM-003", Llm, "LLM call is missing schema validation";
235    LlmSchemaInvalid, "HARN-LLM-004", Llm, "LLM schema option is invalid";
236    LlmProviderIdentityBranch, "HARN-LLM-005", Llm, "prompt branches on provider identity instead of capability flags";
237    LlmCapabilityCompositionInvalid, "HARN-LLM-006", Llm, "provider, model, and requested options form a known-unsafe composition";
238    OrchestrationArity, "HARN-ORC-001", Orc, "orchestration construct has invalid arity";
239    OrchestrationType, "HARN-ORC-002", Orc, "orchestration construct argument has invalid type";
240    AgentDefinitionInvalid, "HARN-ORC-003", Orc, "agent declaration is invalid";
241    WorkflowDefinitionInvalid, "HARN-ORC-004", Orc, "workflow declaration is invalid";
242    ToolDefinitionInvalid, "HARN-ORC-005", Orc, "tool declaration is invalid";
243    PipelineDefinitionInvalid, "HARN-ORC-006", Orc, "pipeline declaration is invalid";
244    InvalidSelectConstruct, "HARN-ORC-007", Orc, "select construct is invalid";
245    UnreachableCode, "HARN-ORC-008", Orc, "statement cannot be reached";
246    FlowInvariantAttributeInvalid, "HARN-ORC-009", Orc, "Flow invariant attribute set is invalid";
247    ExecutionTargetMissing, "HARN-ORC-010", Orc, "execution target path cannot be found";
248    SelfDeadlockDetected, "HARN-ORC-011", Orc, "a self-deadlock acquire would block forever";
249    WaitForGraphDeadlockDetected, "HARN-ORC-012", Orc, "a wait-for graph cycle would block forever";
250    DeprecatedStdlibSymbol, "HARN-STD-001", Std, "stdlib symbol has been renamed or deprecated";
251    StdlibUsageInvalid, "HARN-STD-002", Std, "stdlib call is invalid";
252    BuiltinArity, "HARN-STD-003", Std, "builtin call has invalid arity";
253    LintMissingStdlibMetadata, "HARN-STD-101", Std, "public stdlib function is missing declared metadata";
254    LintMissingStdlibReturnType, "HARN-STD-102", Std, "public stdlib function is missing an explicit return type";
255    PromptTemplateParse, "HARN-PRM-001", Prm, "prompt template cannot be parsed";
256    PromptVariantExplosion, "HARN-PRM-002", Prm, "prompt template has too many capability-aware branches";
257    PromptInjectionRisk, "HARN-PRM-003", Prm, "prompt construction risks direct injection";
258    PromptProviderIdentityBranch, "HARN-PRM-004", Prm, "prompt template branches on provider identity";
259    PromptToolSurfaceUnknown, "HARN-PRM-005", Prm, "prompt references a tool outside the declared surface";
260    PromptToolSurfaceDeferredReference, "HARN-PRM-006", Prm, "prompt references a deferred tool without tool search";
261    PromptTargetMissing, "HARN-PRM-007", Prm, "prompt or template target cannot be found";
262    ModuleImportUnresolved, "HARN-MOD-001", Mod, "module import cannot be resolved";
263    ModuleImportUnused, "HARN-MOD-002", Mod, "module import is unused";
264    ModuleImportOrder, "HARN-MOD-003", Mod, "module imports are not in canonical order";
265    ModuleExportInvalid, "HARN-MOD-004", Mod, "module export is invalid";
266    ModuleImportCollision, "HARN-MOD-005", Mod, "module imports expose colliding names";
267    ModuleReExportConflict, "HARN-MOD-006", Mod, "module re-exports conflict";
268    ModuleImportCompileFailed, "HARN-MOD-007", Mod, "imported module failed to compile";
269    ReminderUnknownOption, "HARN-RMD-001", Rmd, "reminder lifecycle option key is not recognized";
270    ReminderInvalidShape, "HARN-RMD-002", Rmd, "reminder payload shape is invalid";
271    ReminderUnsupportedUserBlockRoleHint, "HARN-RMD-003", Rmd, "retired provider-specific reminder role-hint diagnostic";
272    ReminderInfiniteDiscardable, "HARN-RMD-004", Rmd, "discardable reminder has no TTL";
273    ReminderUnknownPropagate, "HARN-RMD-005", Rmd, "reminder propagate value is not recognized";
274    ReminderProviderMalformedSpec, "HARN-RMD-006", Rmd, "reminder provider returned a malformed reminder spec";
275    ReminderProviderBloat, "HARN-RMD-007", Rmd, "too many reminder providers are enabled";
276    ReminderUnsupportedHookEvent, "HARN-RMD-008", Rmd, "hook event does not support reminder effects";
277    SuspendWorkerNotRunning, "HARN-SUS-001", Sus, "suspend_agent target worker is not running";
278    ResumeConditionsInvalid, "HARN-SUS-002", Sus, "ResumeConditions validation failed";
279    ResumeWorkerNotSuspended, "HARN-SUS-003", Sus, "resume_agent target worker is not suspended";
280    ResumeSnapshotInvalid, "HARN-SUS-004", Sus, "resume snapshot cannot be loaded or used";
281    AwaitResumptionOutsideAgentLoop, "HARN-SUS-005", Sus, "agent_await_resumption was invoked outside agent_loop structural handling";
282    ConcurrentResumeConflict, "HARN-SUS-006", Sus, "concurrent resume changed the worker before resume could complete";
283    ResumeTriggerRegistrationFailed, "HARN-SUS-007", Sus, "ResumeConditions trigger could not be registered";
284    ResumeTimeoutUnsupported, "HARN-SUS-008", Sus, "resume timeout action is unsupported";
285    ResumeInputInvalid, "HARN-SUS-009", Sus, "resume input failed agent_loop input validation";
286    ResumeWorkerClosed, "HARN-SUS-010", Sus, "closed suspended worker cannot be resumed";
287    ReplayResumeInputHashMismatch, "HARN-SUS-011", Sus, "replay resume input hash diverges from journaled suspension";
288    ReplayDrainDecisionPromptHashMismatch, "HARN-SUS-012", Sus, "replay drain decision prompt hash diverges from journaled receipt";
289    LifecycleSignatureMismatch, "HARN-SUS-013", Sus, "lifecycle receipt signed timestamp failed verification";
290    LintRenamedStdlibSymbol, "HARN-LNT-001", Lnt, "renamed stdlib symbol lint";
291    LintCyclomaticComplexity, "HARN-LNT-002", Lnt, "cyclomatic complexity lint";
292    LintNamingConvention, "HARN-LNT-003", Lnt, "naming convention lint";
293    LintEagerCollectionConversion, "HARN-LNT-004", Lnt, "eager collection conversion lint";
294    LintRedundantClone, "HARN-LNT-005", Lnt, "redundant clone lint";
295    LintLongRunningWithoutCleanup, "HARN-LNT-006", Lnt, "long-running workflow cleanup lint";
296    LintMcpToolAnnotations, "HARN-LNT-007", Lnt, "MCP tool annotations lint";
297    LintPrOpenWithoutSecretScan, "HARN-LNT-008", Lnt, "PR open without secret scan lint";
298    LintShadowVariable, "HARN-LNT-009", Lnt, "shadow variable lint";
299    LintPersonaHookTarget, "HARN-LNT-010", Lnt, "persona hook target lint";
300    LintDeadCodeAfterReturn, "HARN-LNT-011", Lnt, "dead code after return lint";
301    LintLetThenReturn, "HARN-LNT-012", Lnt, "let then return lint";
302    LintUnhandledApprovalResult, "HARN-LNT-013", Lnt, "unhandled approval result lint";
303    LintUnusedVariable, "HARN-LNT-014", Lnt, "unused variable lint";
304    LintUnusedPatternBinding, "HARN-LNT-015", Lnt, "unused pattern binding lint";
305    LintUnusedParameter, "HARN-LNT-016", Lnt, "unused parameter lint";
306    LintUnusedImport, "HARN-LNT-017", Lnt, "unused import lint";
307    LintMutableNeverReassigned, "HARN-LNT-018", Lnt, "mutable never reassigned lint";
308    LintUnusedFunction, "HARN-LNT-019", Lnt, "unused function lint";
309    LintUnusedType, "HARN-LNT-020", Lnt, "unused type lint";
310    LintPersonaBodyMustCallSteps, "HARN-LNT-021", Lnt, "persona body must call steps lint";
311    LintUndefinedFunction, "HARN-LNT-022", Lnt, "undefined function lint";
312    LintPipelineReturnType, "HARN-LNT-023", Lnt, "pipeline return type lint";
313    LintMissingHarndoc, "HARN-LNT-024", Lnt, "missing harndoc lint";
314    LintAssertOutsideTest, "HARN-LNT-025", Lnt, "assert outside test lint";
315    LintPromptInjectionRisk, "HARN-LNT-026", Lnt, "prompt injection risk lint";
316    LintConnectorEffectPolicy, "HARN-LNT-027", Lnt, "connector effect policy lint";
317    LintUnnecessaryCast, "HARN-LNT-028", Lnt, "unnecessary cast lint";
318    LintUntypedDictAccess, "HARN-LNT-029", Lnt, "untyped dict access lint";
319    LintConstantLogicalOperand, "HARN-LNT-030", Lnt, "constant logical operand lint";
320    LintPointlessComparison, "HARN-LNT-031", Lnt, "pointless comparison lint";
321    LintComparisonToBool, "HARN-LNT-032", Lnt, "comparison to bool lint";
322    LintInvalidBinaryOpLiteral, "HARN-LNT-033", Lnt, "invalid binary operator literal lint";
323    LintRedundantNilTernary, "HARN-LNT-034", Lnt, "redundant nil ternary lint";
324    LintEmptyBlock, "HARN-LNT-035", Lnt, "empty block lint";
325    LintUnnecessaryElseReturn, "HARN-LNT-036", Lnt, "unnecessary else return lint";
326    LintDuplicateMatchArm, "HARN-LNT-037", Lnt, "duplicate match arm lint";
327    LintRequireInTest, "HARN-LNT-038", Lnt, "require in test lint";
328    LintBreakOutsideLoop, "HARN-LNT-039", Lnt, "break outside loop lint";
329    LintTemplateParse, "HARN-LNT-040", Lnt, "template parse lint";
330    LintBlankLineBetweenItems, "HARN-LNT-041", Lnt, "blank line between items lint";
331    LintTrailingComma, "HARN-LNT-042", Lnt, "trailing comma lint";
332    LintUnnecessaryParentheses, "HARN-LNT-043", Lnt, "unnecessary parentheses lint";
333    LintTemplateVariantExplosion, "HARN-LNT-044", Lnt, "template variant explosion lint";
334    LintRequireFileHeader, "HARN-LNT-045", Lnt, "require file header lint";
335    LintTemplateProviderIdentityBranch, "HARN-LNT-046", Lnt, "template provider identity branch lint";
336    LintImportOrder, "HARN-LNT-047", Lnt, "import order lint";
337    LintPreferOptionalShorthand, "HARN-LNT-048", Lnt, "prefer optional shorthand lint";
338    LintLegacyDocComment, "HARN-LNT-049", Lnt, "legacy doc comment lint";
339    LintRemovedLlmOptions, "HARN-LNT-050", Lnt, "removed LLM options lint";
340    LintUnnecessarySafeNavigation, "HARN-LNT-051", Lnt, "unnecessary safe navigation lint";
341    LintAmbientClockBuiltin, "HARN-LNT-052", Lnt, "ambient clock builtin replaced by `harness.clock.*`";
342    LintAmbientStdioBuiltin, "HARN-LNT-053", Lnt, "ambient stdio builtin replaced by `harness.stdio.*`";
343    LintAmbientFsBuiltin, "HARN-LNT-054", Lnt, "ambient fs builtin replaced by `harness.fs.*`";
344    LintAmbientEnvBuiltin, "HARN-LNT-055", Lnt, "ambient env builtin replaced by `harness.env.*`";
345    LintAmbientRandomBuiltin, "HARN-LNT-056", Lnt, "ambient random builtin replaced by `harness.random.*`";
346    LintAmbientNetBuiltin, "HARN-LNT-057", Lnt, "ambient net builtin replaced by `harness.net.*`";
347    LintVacuousCondition, "HARN-LNT-058", Lnt, "if / while / guard condition is statically known to always succeed or always fail";
348    LintRuleEngine, "HARN-LNT-059", Lnt, "project rule-engine or native lint rule";
349    LintUnnormalizedOptions, "HARN-LNT-060", Lnt, "inline options dict bypasses the typed option constructors";
350    LintNilCoalesceNoop, "HARN-LNT-061", Lnt, "nil coalesce fallback has no effect";
351    LintNilCoalesceUnreachableFallback, "HARN-LNT-062", Lnt, "nil coalesce fallback is unreachable";
352    LintUnnecessaryNonNullAssert, "HARN-LNT-063", Lnt, "non-null assertion `!` on an already-non-nil value";
353    LintMutableCaptureAcrossParallel, "HARN-LNT-064", Lnt, "a mutable variable captured from an enclosing scope is reassigned inside a `parallel`/`spawn` body, so concurrent branches share one cell and race";
354    LintNilCoalesceSelfFallback, "HARN-LNT-065", Lnt, "nil coalesce fallback repeats the left identifier";
355    LintDiscardedPureResult, "HARN-LNT-066", Lnt, "the result of a pure collection method is discarded, so the call has no effect on the receiver";
356    LintTemplateUnknownFilter, "HARN-LNT-068", Lnt, "prompt template names a filter the engine does not implement";
357    LintBroadHarnessParameter, "HARN-LNT-069", Lnt, "helper accepts root Harness but uses only narrow capability handles";
358    LintHomogeneousPositionalApi, "HARN-LNT-070", Lnt, "public API has too many same-typed positional parameters";
359    LintAmbientHarnessMethod, "HARN-LNT-071", Lnt, "global builtin has moved to a Harness capability method";
360    LintNonSourceCallableBuiltin, "HARN-LNT-072", Lnt, "call names a builtin whose declared exposure keeps Harn source from naming it";
361    LintCapabilityParameterName, "HARN-LNT-073", Lnt, "parameter carrying a narrow capability handle is not named for that capability";
362    LintUnusedPipelineInput, "HARN-LNT-074", Lnt, "explicitly unused private pipeline input can be removed";
363    LintUntypedToolHandlerResult, "HARN-LNT-075", Lnt, "tool handler returns a freeform dict, so its outcome must be inferred from key names instead of declared by its type";
364    LintToolHandlerHostCall, "HARN-LNT-076", Lnt, "tool handler reaches the privileged host wire";
365    LintPreferPick, "HARN-LNT-077", Lnt, "record literal copies fields one by one from a value that `pick` can select";
366    LintSchemaShapedToolParameters, "HARN-LNT-078", Lnt, "tool descriptor spells its per-parameter map as a JSON Schema document";
367    LintUnboundedNativeDecisionState, "HARN-LNT-079", Lnt, "evaluation site hands a native decision route an input whose declared type has no finite size bound";
368    SandboxCapabilityDenied, "HARN-CAP-201", Cap, "harness capability denied by active sandbox profile";
369    HostLoopbackBindDenied, "HARN-CAP-202", Cap, "confined host process cannot open the loopback listener a child's egress proxy needs";
370    FormatterParseFailed, "HARN-FMT-001", Fmt, "formatter could not parse the source";
371    FormatterWouldReformat, "HARN-FMT-002", Fmt, "source is not in canonical format";
372    FormatterTrailingComma, "HARN-FMT-003", Fmt, "formatter normalized trailing comma layout";
373    ImportResolutionFailed, "HARN-IMP-001", Imp, "import target cannot be resolved";
374    ImportSymbolMissing, "HARN-IMP-002", Imp, "imported symbol does not exist";
375    ImportCycle, "HARN-IMP-003", Imp, "import graph contains a cycle";
376    ImmutableAssignment, "HARN-OWN-001", Own, "immutable binding is reassigned";
377    MutableNeverReassigned, "HARN-OWN-002", Own, "mutable binding is never reassigned";
378    OwnershipEscape, "HARN-OWN-003", Own, "owned value escapes its valid scope";
379    BoundaryValueUnvalidated, "HARN-OWN-004", Own, "unvalidated boundary value is used directly";
380    RescueOutsideFunction, "HARN-RCV-001", Rcv, "rescue construct is outside a function body";
381    TryOutsideFunction, "HARN-RCV-002", Rcv, "try construct is outside a function body";
382    InvalidRescueConstruct, "HARN-RCV-003", Rcv, "rescue construct is invalid";
383    NonExhaustiveMatch, "HARN-MAT-001", Mat, "match expression is not exhaustive";
384    DuplicateMatchArm, "HARN-MAT-002", Mat, "match expression contains a duplicate arm";
385    InvalidMatchPattern, "HARN-MAT-003", Mat, "match pattern is invalid";
386    PoolBackpressureFull, "HARN-POL-001", Pol, "pool backpressure rejected a submit";
387    PoolFailFastFull, "HARN-POL-002", Pol, "fail-fast pool has no immediate capacity";
388    ConstEvalDisallowedExpression, "HARN-MET-001", Met, "expression is not permitted in a const initializer";
389    ConstEvalStepLimit, "HARN-CST-001", Cst, "const initializer exceeded the step budget";
390    ConstEvalRecursionLimit, "HARN-CST-002", Cst, "const initializer exceeded the recursion depth budget";
391    ConstEvalSandboxViolation, "HARN-CST-003", Cst, "const initializer attempted a sandboxed capability";
392    ConstEvalRuntimeError, "HARN-CST-004", Cst, "const initializer raised a runtime error during evaluation";
393}
394impl Code {
395    pub const fn registry() -> &'static [RegistryEntry] {
396        REGISTRY
397    }
398
399    /// Codes that an agent should consider alongside this one when planning
400    /// repairs. Curated per-code — typically near-neighbours in the same
401    /// category that share a fix shape. Returns an empty slice for codes
402    /// without curated cross-references.
403    pub const fn related(self) -> &'static [Code] {
404        match self {
405            // Type mismatches form a family — surfacing the others helps an
406            // agent disambiguate between assignment, argument, return, etc.
407            Code::TypeMismatch => &[
408                Code::AssignmentTypeMismatch,
409                Code::ArgumentTypeMismatch,
410                Code::ReturnTypeMismatch,
411                Code::VariableTypeMismatch,
412                Code::FieldTypeMismatch,
413            ],
414            Code::AssignmentTypeMismatch => &[Code::TypeMismatch, Code::VariableTypeMismatch],
415            Code::ArgumentTypeMismatch => &[Code::TypeMismatch, Code::GenericTypeArgumentMismatch],
416            Code::ReturnTypeMismatch => &[Code::TypeMismatch, Code::ClosureReturnTypeMismatch],
417            Code::VariableTypeMismatch => &[Code::TypeMismatch, Code::AssignmentTypeMismatch],
418            Code::ClosureReturnTypeMismatch => &[Code::ReturnTypeMismatch],
419            Code::FieldTypeMismatch => &[Code::TypeMismatch, Code::InvalidStructLiteral],
420            Code::MethodTypeMismatch => &[Code::TypeMismatch, Code::CallableExpected],
421            // Generic type-argument family.
422            Code::GenericTypeArgumentUnsupported => &[
423                Code::GenericTypeArgumentMismatch,
424                Code::GenericTypeArgumentArity,
425            ],
426            Code::GenericTypeArgumentMismatch => &[
427                Code::GenericTypeArgumentArity,
428                Code::WhereConstraintMismatch,
429            ],
430            Code::GenericTypeArgumentArity => {
431                &[Code::GenericTypeArgumentMismatch, Code::TypeParameterArity]
432            }
433            Code::TypeParameterArity => &[Code::GenericTypeArgumentArity],
434            Code::WhereConstraintMismatch => &[Code::GenericTypeArgumentMismatch],
435            // Naming.
436            Code::UndefinedVariable => &[Code::UndefinedFunction, Code::UnknownDeclaration],
437            Code::UndefinedFunction => &[Code::UnknownBuiltin, Code::UnknownDeclaration],
438            Code::UnknownField => &[Code::UnknownMethod, Code::InvalidStructLiteral],
439            Code::UnknownMethod => &[Code::UnknownField, Code::CallableExpected],
440            Code::UnknownAttribute => {
441                &[Code::InvalidAttributeArgument, Code::InvalidAttributeTarget]
442            }
443            Code::InvalidAttributeArgument => {
444                &[Code::UnknownAttribute, Code::InvalidAttributeTarget]
445            }
446            Code::InvalidAttributeTarget => {
447                &[Code::UnknownAttribute, Code::InvalidAttributeArgument]
448            }
449            // LLM call family — schema, options, provider branching.
450            Code::LlmSchemaMissing => &[Code::LlmSchemaInvalid],
451            Code::LlmSchemaInvalid => &[Code::LlmSchemaMissing],
452            Code::LlmProviderIdentityBranch => &[Code::PromptProviderIdentityBranch],
453            // Prompt-template family.
454            Code::PromptTemplateParse => &[Code::PromptTargetMissing],
455            Code::PromptInjectionRisk => &[Code::LintPromptInjectionRisk],
456            Code::PromptProviderIdentityBranch => &[
457                Code::LlmProviderIdentityBranch,
458                Code::LintTemplateProviderIdentityBranch,
459            ],
460            Code::PromptVariantExplosion => &[Code::LintTemplateVariantExplosion],
461            // Capabilities.
462            Code::CapabilityResultUnchecked => {
463                &[Code::RescueOutsideFunction, Code::TryOutsideFunction]
464            }
465            Code::CapabilityUnknownOperation => &[Code::CapabilityCallStaticNameRequired],
466            Code::EffectInheritanceViolation => &[
467                Code::CapabilityPayloadInvalid,
468                Code::CapabilityBindingInvalid,
469            ],
470            // Recovery / match.
471            Code::RescueOutsideFunction => {
472                &[Code::TryOutsideFunction, Code::InvalidRescueConstruct]
473            }
474            Code::TryOutsideFunction => &[Code::RescueOutsideFunction],
475            Code::NonExhaustiveMatch => &[Code::InvalidMatchPattern, Code::DuplicateMatchArm],
476            Code::DuplicateMatchArm => &[Code::NonExhaustiveMatch, Code::LintDuplicateMatchArm],
477            // Module / import family.
478            Code::ModuleImportUnresolved => {
479                &[Code::ImportResolutionFailed, Code::ImportSymbolMissing]
480            }
481            Code::ModuleImportUnused => &[Code::LintUnusedImport],
482            Code::ImportResolutionFailed => {
483                &[Code::ModuleImportUnresolved, Code::ImportSymbolMissing]
484            }
485            Code::ImportCycle => &[Code::ImportResolutionFailed],
486            // Suspend / resume lifecycle.
487            Code::SuspendWorkerNotRunning => {
488                &[Code::ResumeWorkerNotSuspended, Code::ResumeWorkerClosed]
489            }
490            Code::ResumeConditionsInvalid => &[
491                Code::ResumeTriggerRegistrationFailed,
492                Code::ResumeTimeoutUnsupported,
493            ],
494            Code::ResumeWorkerNotSuspended => &[
495                Code::SuspendWorkerNotRunning,
496                Code::ConcurrentResumeConflict,
497            ],
498            Code::ResumeSnapshotInvalid => &[Code::ResumeWorkerNotSuspended],
499            Code::AwaitResumptionOutsideAgentLoop => &[Code::ResumeConditionsInvalid],
500            Code::ConcurrentResumeConflict => {
501                &[Code::ResumeWorkerNotSuspended, Code::ResumeWorkerClosed]
502            }
503            Code::ResumeTriggerRegistrationFailed => &[
504                Code::ResumeConditionsInvalid,
505                Code::ResumeTimeoutUnsupported,
506            ],
507            Code::ResumeTimeoutUnsupported => &[
508                Code::ResumeConditionsInvalid,
509                Code::ResumeTriggerRegistrationFailed,
510            ],
511            Code::ResumeInputInvalid => &[Code::ResumeWorkerNotSuspended],
512            Code::ResumeWorkerClosed => &[
513                Code::ResumeWorkerNotSuspended,
514                Code::ConcurrentResumeConflict,
515            ],
516            // Reminder lifecycle diagnostics share the same payload shape and
517            // propagation field, so nearby codes help route runtime vs lint
518            // failures to the right fix.
519            Code::ReminderUnknownOption => {
520                &[Code::ReminderInvalidShape, Code::ReminderUnknownPropagate]
521            }
522            Code::ReminderInvalidShape => {
523                &[Code::ReminderUnknownOption, Code::ReminderUnknownPropagate]
524            }
525            Code::ReminderUnknownPropagate => {
526                &[Code::ReminderUnknownOption, Code::ReminderInvalidShape]
527            }
528            Code::ReminderProviderMalformedSpec => &[Code::ReminderInvalidShape],
529            Code::ReminderProviderBloat => &[Code::ReminderInfiniteDiscardable],
530            Code::ReminderUnsupportedHookEvent => &[Code::ReminderProviderMalformedSpec],
531            // Ownership.
532            Code::ImmutableAssignment => &[Code::MutableNeverReassigned],
533            Code::MutableNeverReassigned => &[Code::LintMutableNeverReassigned],
534            // Lint pairs (drift between lint and runtime/typecheck codes).
535            Code::LintUnnormalizedOptions => {
536                &[Code::LintRemovedLlmOptions, Code::LintUntypedDictAccess]
537            }
538            Code::LintPromptInjectionRisk => &[Code::PromptInjectionRisk],
539            Code::LintTemplateVariantExplosion => &[Code::PromptVariantExplosion],
540            Code::LintTemplateProviderIdentityBranch => &[Code::PromptProviderIdentityBranch],
541            Code::LintRenamedStdlibSymbol => &[Code::DeprecatedStdlibSymbol],
542            Code::LintAmbientClockBuiltin
543            | Code::LintAmbientStdioBuiltin
544            | Code::LintAmbientFsBuiltin
545            | Code::LintAmbientEnvBuiltin
546            | Code::LintAmbientRandomBuiltin
547            | Code::LintAmbientNetBuiltin => {
548                &[Code::InvalidMainSignature, Code::LintRenamedStdlibSymbol]
549            }
550            Code::SandboxCapabilityDenied => &[Code::CapabilityPayloadInvalid],
551            Code::LintMutableNeverReassigned => &[Code::MutableNeverReassigned],
552            Code::LintUnusedImport => &[Code::ModuleImportUnused],
553            Code::LintDuplicateMatchArm => &[Code::DuplicateMatchArm],
554            _ => &[],
555        }
556    }
557}
558
559impl fmt::Display for Code {
560    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
561        f.write_str(self.as_str())
562    }
563}
564
565/// Error returned when parsing an unknown diagnostic code.
566#[derive(Debug, Clone, Copy, PartialEq, Eq)]
567pub struct ParseCodeError;
568
569impl fmt::Display for ParseCodeError {
570    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
571        f.write_str("unknown Harn diagnostic code")
572    }
573}
574
575impl std::error::Error for ParseCodeError {}
576
577impl FromStr for Code {
578    type Err = ParseCodeError;
579
580    fn from_str(value: &str) -> Result<Self, Self::Err> {
581        Code::ALL
582            .iter()
583            .copied()
584            .find(|code| code.as_str() == value)
585            .ok_or(ParseCodeError)
586    }
587}
588
589mod repairs;
590
591pub use repairs::*;