wayfinder 0.2.0
wayfinder: ^0.2.0 copied to clipboard
Core Wayfinder library that validates OKF knowledge bundles and evaluates the rules of any Profile package.
0.2.0 #
wayfinderdepends onack, which replaces the engine's own JSON Schema evaluator. Ack evaluates every rule schema. The engine still admits only its keyword subset, checks a schema's property names against its subject's facts, and words every message.SchemaCheck.schemais the parsed rule schema;SchemaCheck.defs,slotsandcompileare gone. A rule schema now follows 2020-12 where the old evaluator did not: an emptyenummatches nothing instead of being refused; a$refbelow a$defsentry, a$idor$schemabelow the root and a$schemathat does not name 2020-12 are unsupported; a malformed annotation (a non-stringtitle,descriptionor$comment, non-listexamples, a non-booleandeprecated), a duplicaterequiredortypeentry and an emptytypelist are refused; and Ack words these refusals and a nonproductive$refcycle.- Ack also checks
wayfinder.jsonand each package against the published schemas, and the engine words the first failure as before, with three changes: a rootnullis reported as "must not be null"; with several violations, the first is the first in Ack's keyword order rather than document order; and a number too large for a double is reported as "must contain only finite numbers".schemaFailureWhereis gone; it was never meant to be public. - A non-finite frontmatter number (YAML
.inf,.nan) reads as the string factInfinityorNaN, as other non-JSON scalars already do, so a rule schema only ever sees JSON. - A package may name its agent skill directory in
skill(ProfilePackage.skill), relative to the package. A Profile id has at most 64 characters (ProfileId.maxLength,maxLengthin both schemas), the Agent Skills name limit, because the id names the installed skill. The newwayfinder/profile-skill-stalewarning reports a Profile skill whose installed copy is not the locked revision, carried bySelectedProfile.notes. - A package names its own parent in
extends:{"path"}is the package at that path in the same repository at the same commit, and{"git", "ref", "path"}resolves its own revision (PackageParent,SameRevision,OtherRevision).wayfinder.jsonlosesextends, andapplies_toneeds at least one path.ProfileValidator.validatetakes aProfileSelection, eitherSelectedProfileorUnselectedProfile, instead of reading the configuration itself;WayfinderProjectConfig.bindfinds a bundle's binding or throwsBundleBindingExceptionwith its one diagnostic.ProfileSourceResolution,WayfinderProjectConfig.read,resolveandWayfinderResolvedConfigare gone. Whenever a Profile was selected, including underBLOCKED BY OKF, the JSON result names it asprofile.idandprofile.releaseand its chain asprofile.chain({id, release, commit}, root first). OnlyNOT ASSESSEDomits them. Text printsProfile <id> <release>: <state>, and SARIF gains theprofile_idrun property. - A Profile is one package file,
wayfinder-profile.jsonin package format 2, read byProfilePackage.parsefor every Profile alike. The manifest and rule catalog are merged (standard_typesistypes,frontmatter_keysis a list of definitions, the rule shape moves in, the per-rulerefis gone),wayfinder-rules.schema.jsonfolds intowayfinder-profile.schema.json, and the engine embeds no Profile. Bitwild is the package atprofiles/bitwild/with idbitwild-profile, so its findings arebitwild-profile/*(formerlyconcepta-profile/*), and it is fetched like any Profile; no chain has to reach it. A package id is the finding namespace, in kebab-case.EffectiveProfile.composemerges a chain and the project additions, and a name collision, a repeated frontmatter key or a tag equal to another vocabulary value is thewayfinder/profile-compositiondiagnostic (a tag collision wasconfig-invalid). A malformed package iswayfinder/profile-invalid; a package with anotherformat, an OKF release this okf cannot read or an unknown builtin iswayfinder/profile-unsupported. Findings and summary entries carryhelp_uri, the packagedocsURI with the rule id as its fragment, instead ofrule; SARIF rule descriptors carryhelpUriand loseproperties.ref. Builtins are engine capabilities with params:files-present(paths),path-targets-exist(fields) andmatches-generated(generator,version,keep,extra), and the generator declares the package'simplements.release. The JSON result gainsengine.okfand SARIFtool.extensionsnames the okf package the engine generates with. New root factshas_conceptsandindex_links, and the Bitwild ruleroot-index-lists-log. The generator istool/generate_published_schemas.dart, writingpublished_schemas.g.dart. - The engine selects a Profile only through
wayfinder.json. The 2026.2 dispatch through an in-bundleprofile.mddeclaration is gone, with itstypes.mdandactors.mdregistry readers and its index projection. A bundle with nowayfinder.jsonabove it isNOT ASSESSEDwithwayfinder/config-missingand gateINCOMPLETE, whatever its root files say, and--fixwrites nothing there. Aprofile.mdno longer exempts a bundle fromwayfinder/config-invalidorwayfinder/bundle-unbound. The 19 builtins frozen for 2026.2, the builtins'installedOnlyInrestriction,tag-literal-duplication(dead since 2026.3 checks tag collisions while reading the binding), and the 2026.2-onlyreservedparam ofroot-structure-filesare deleted, as areLegacyRegistries,EffectiveProfile.legacyDispatch,Vocabulary.standardTypes,legacyProfileRelease, andlegacyStandardTypes, and theyamldependency is dropped. A 2026.2 bundle keeps validating on wayfinder 0.1.x, or migrates to awayfinder.jsonbinding. - The engine reports on its own run as
EngineDiagnostics, a closed set ofwayfinder/*codes with a level, instead of dressing them as Profile findings. Release dispatch problems (DispatchRuleis gone), thelink-graph-unavailableandconfigured-type-extensioncatalog rules and their builtins, and--fixfailure or refusal (ProfileFixis gone) become diagnostics.ProfileValidationResultholds a sealedProfileAssessment(Assessed,BlockedByOkf,NotAssessed) and derivesgate:FAILwhen OKF fails or a finding is an error, elseINCOMPLETEwhen a diagnostic is an error, elsePASS, exiting 0, 1 or 2. JSON gainsdiagnosticsandgateand losesjudgment_rulesandautomated_gate;fixis{written}. Profile stateUNSUPPORTEDbecomesNOT ASSESSED. SARIF reports diagnostics as invocation notifications withdriver.notificationsdescriptors, andexecutionSuccessfulis false only for an error diagnostic.internalErrorJsonandinternalErrorSarifdescribe a run that stopped. A link graph that cannot be built now makes the gateINCOMPLETErather thanFAIL, and skips every rule that reads a link fact: by name, through a$refapplied to the subject, or through a keyword that reads the whole key set (propertyNames,additionalProperties,minProperties,enum,const).ProfileValidatortakes abuildGraphfunction so a test can force that path. index-currentandvalidate --fixcompare an index with CRLF line endings, as a Windows checkout writes it, equal to the generated LF text, so neither reports nor rewrites it.validate --fixreplaces each generated index atomically, refuses a symbolic link at any path segment, and reports a failed write with the files already written. SARIF locations inside the working directory are relative to a recordedWORKINGDIRbase, and summary results carry levelnone. A failed fix fails the SARIF invocation through itswayfinder/fix-failednotification, and the run'sfixproperty lists the files written before it.ProfileFindingtakes aFindingDescriptor, which only an error or advisory descriptor can become, so a note rule has no path to a finding.- A rule schema names a composed vocabulary as
{"$ref": "#/$defs/<slot>"}, such as#/$defs/profile.types. The engine supplies those entries, so a package or rule$defsentry may not use a slot id. Thex-slotkeyword is gone, and anyx-keyword now makes a package unsupported rather than being ignored, so every rule schema is plain JSON Schema. ProfilePackage.parserejects more at load: a rule whose own examples disagree with its schema;eachover a fact that is not a list;failing_fieldthat is not an element field; apropertiesorrequiredname at the subject level, inline or through a$refapplied to the same instance, that no fact or element field of a closed subject carries; params for a builtin that declares none; and a message placeholder the builtin does not fill.failingExamplesis gone; load runs the examples.- Bitwild 2026.3
relationship-shapefails arelationshipsvalue that is null, and an entry whoseresourceokf resolves asinvalidor as a scopedescriptor. The rule moves to theconceptsubject: eachrelationshipselement carries the authoredentrywith theresolutionbeside it, and a non-list value stays the value itself.okfFieldEdgesresolves targets as source resources, so prose resolves asdescriptorrather thanunresolved. The engine tests a non-listeachfact as one{"value": ...}instance instead of failing it outright, so the rule's schema decides. - Bitwild 2026.3 reports an undeclared relationship name as the new
used-relationship-declared(vocabulary, error), likeused-type-registeredandused-actor-registered, instead ofrelationship-shape, which now checks thatrelationshipis a nonempty string, not that it is declared. The new rule tests a name only once the entry is a mapping with nonempty text there, so one defect never reports under both. {failing}and{fact}placeholders render a non-string value as compact JSON instead of Dart's{key: value}text, so a failing relationships entry reads as it was authored. Strings are unchanged.- A failure while resolving relationship targets no longer drops the
relationshipsandinboundfacts silently. okf's graph and the relationship edges resolve as one link layer; when it fails, no link fact exists for a link rule to pass on, and the run reports it.BundleFacts.projecttakes abuildGraphfunction so a test can force that path. - Export
OkfLinkField,OkfFieldEdgeandokfFieldEdges, the typed link-field model and resolutionwayfinder_embeddingsand the CLI graph shared with the engine, plusrelationshipsLinkFieldfor the Profile'srelationshipskey. The engine's relationship facts resolve through the same function. - Bitwild 2026.3 reports what it permits as summary entries instead of
advisories. Rules take a third severity,
note, whose results fillProfileValidationResult.summary(ProfileSummaryEntry), JSONprofile.summary, a textSummary:block and SARIF results of kindinformationalwith levelnone, and never affect a state or the exit code.internal-link-unresolvedandrelationship-unresolvedbecome notes.evaluatereturns findings and summary entries apart. A declared tag that equals a type, status, trust tier or relationship name failsWayfinderProjectConfig.parseand binding composition, and Bitwild 2026.3 dropstag-literal-duplication. - Bitwild 2026.3 types relationships in the
relationshipsfrontmatter key instead of a# Relationshipsbody section. Bitwild 2026.3 declares the key in its newfrontmatter_keys, renamesfrontmatter-fields-okftofrontmatter-fields-declared, addsrelationship-shape(error) and therelationship-bundle-relativeandrelationship-unresolvedadvisories, and dropsrelationships-shapeandrelationship-label-extension.tag-literal-duplicationcompares tags with the declared relationship names. Relationship names are vocabulary: Bitwild declares eleven andWayfinderProfileBinding.relationshipsadds project names. A package declaring an OKF key fails to load. - Bitwild 2026.3 indexes are okf's generated output:
index-currentreplacesindex-semantic-projectionanddirectory-index-presentin Bitwild 2026.3 and reports each generated index that is missing or differs.ProfileValidator.validate(fix: true)writes those indexes first and reports what it wrote asProfileValidationResult.fixed. It also reports a leftoverindex.mdthe generator no longer writes, such as one in araw/tier, so the parent index stops linking to it. Conformance now depends on okf's generator output; the configured-fixture goldens fail if an okf release changes it, which is the signal to update the guide's pin. - Add direct-source project bindings in
wayfinder.json, with strict type, tag, actor, and path checks. Version 1 accepts onlysource+applies_to; the earlier unpublishedbundles/implementsdraft is not a compatibility form. Bitwild's twelve types include OKF's Attested Computation. - Inspect OKF independently before Profile selection. Bitwild's
okf-release-bindingchecks the rootokf_version. - Report a configured project type at the configuration path as supplied, or
wayfinder.jsonwhen discovered, instead of the file's absolute path. - Stop reporting nested
profile.md,types.md, oractors.mdconcepts. Bitwild forbids only the legacy root registries. - Bitwild 2026.3
log-entry-lead-wordno longer fails a root log without entries. The rule requires a lead word on every entry, not that entries exist. okf'smissing-log-dateandempty-log-dateerrors still reject such a log before Profile validation runs.
0.1.0 #
- Validate against Concepta Profile 2026.2, which adopts the OKF 0.2 revision
where every timestamp is an ISO 8601 datetime with an explicit UTC offset, and
pins the specification to its canonical
open-knowledge-formatrepository atad30107. A bundle still declaringconcepta_profile: "2026.1"now reports an unsupported release rather than a conformance verdict; update the declaration and, where timestamps are date-only, runokf format --migrate-timestamps. - Depend on
okf^0.5.0. A date-only timestamp is reported through okf's non-blockingokf/timestamp-without-offsetadvisory, so a bundle conformant under 2026.1 stays conformant once its declaration is updated. - Raise the Dart floor from 3.6.0 to 3.11.0, matching every Concepta package. A consumer on an older SDK no longer resolves this package and must upgrade Dart to take 0.1.0.
0.0.1 #
Core library replaces okf_profile; import package:wayfinder/wayfinder.dart. Validation contracts remain unchanged. The command and MCP server now live in wayfinder_cli.
Changelog #
0.2.1-dev.0 #
- Expose the existing validator and result contracts for Wayfinder without changing
okfpcommands, validation semantics or exit codes.
Release history of the okf_profile Dart package (the okfp toolchain).
This is package semver; profile releases are recorded in profile/, not here.
0.2.0 #
- Migrate to okf 0.2.0 and adopt its finding contract as the wire format
(ADR-0008): the
okf.reportJSON object is now okf's own projection — a canonically orderedfindingsarray of{id, severity, message, location}objects with namespaced kebab-case IDs — and the separateokf.load_issueschannel is retired, because load failures are error-severity findings in the same report. - Text output reports the OKF component as
N error(s), N advisory(ies); thewarningtier no longer exists upstream. ProfileValidatorvalidates through okf's single report-composition seam (OkfBundleLoadResult.validate()) and no longer takes an okf validator.- Profile findings speak the same finding grammar (ADR-0008): each JSON
finding is the okf projection —
{id, severity, message, location}— plus theprofile_releaseandrulereferences guide §4.2 requires, and findings sort in okf's canonical report order (path, line, column, id, severity, message) instead of emission order. - Add the profile rule descriptor registry (id, severity, normative rule
reference), mirroring okf's
okfSpecRuleDescriptors. Every finding is built from its rule's descriptor, so id, severity, and rule reference cannot drift from the registry — a call site names only the rule, the observation, and its path — and a corpus test holds every emitted finding to a registered rule. - The automated gate's exit codes are okf's
OkfExitCodecontract:success/findings/usagefor PASS/FAIL/UNSUPPORTED (values unchanged). - Index and log parsing go through okf's
OkfIndexDocument/OkfLogDocumententry format instead of a hand-rolled markdown-AST parallel; ADR-0007's percent-decoded target comparison is unchanged on top of it. okf 0.2.0's angle-bracket destination form means a raw)no longer forces the percent-encoded spelling; the authoring skill teaches both. The §9 expected projection stays profile-owned — okf's generic index generator synthesizes directory descriptions the Concepta projection deliberately leaves empty.
0.1.1 #
- Enforce the Profile 2026.1
raw/tier amendment (ADR-0006): non-index markdown under araw/directory inreferences/fails deterministically asconcepta-profile/raw-directory-markdown, and araw/directory sitting directly underreferences/fails asconcepta-profile/raw-directory-placement— the tier is per source directory, andreferences/itself is not one.
0.1.0 #
- Bootstrap the
okf_profilepackage and theokfpcommand-line interface, as a pub workspace member atpackages/wayfinder/. - Ship the closed
validate <bundle> [--output text|json]automated gate for the Concepta Profile, backed by the independent OKF 0.2 result. - Keep deterministic Profile findings, contextual judgment, and automated-gate states separate in stable text and JSON contracts.