From 7ee271292265f910691324cd7fb2711813754e67 Mon Sep 17 00:00:00 2001 From: Thorsten Fuchs <76904008+ThorFuchs@users.noreply.github.com> Date: Thu, 15 Oct 2026 22:23:40 +0200 Subject: [PATCH 1/2] Qualify opt-in JSONNavigation product candidate --- AGENTS.md | 6 +- Documentation/Architecture/API.md | 7 +- .../StructuralIntelligence/N1Promotion.md | 25 + .../StructuralIntelligence/N1PublicAudit.json | 500 ++++++++++++++++++ .../SourceReconciliation.md | 22 + Documentation/CI/README.md | 10 + Documentation/DocumentationTooling.md | 10 +- .../Qualification/TestDiscovery.json | 6 +- Documentation/README.md | 3 +- Package.swift | 3 +- README.md | 21 +- Scripts/README.md | 6 +- Scripts/build_documentation.py | 2 +- Scripts/build_documentation_site.py | 8 +- Scripts/ci.py | 4 +- Scripts/documentation_catalog.py | 2 +- Scripts/qualify_navigation.py | 12 +- Scripts/wasm_support.py | 2 +- Sources/JSONCLIEngine/CLIBuildIdentity.swift | 2 +- .../Documentation.docc/JSONNavigation.md | 6 +- .../Documentation.docc/Traversal.md | 6 + .../JSONNavigationTests/PromotionTests.swift | 36 ++ Tools/NavigationQualification/Package.swift | 9 + Tools/NavigationQualification/README.md | 8 + 24 files changed, 675 insertions(+), 41 deletions(-) create mode 100644 Documentation/Architecture/StructuralIntelligence/N1Promotion.md create mode 100644 Documentation/Architecture/StructuralIntelligence/N1PublicAudit.json create mode 100644 Documentation/Architecture/StructuralIntelligence/SourceReconciliation.md create mode 100644 Tests/JSONNavigationTests/PromotionTests.swift create mode 100644 Tools/NavigationQualification/Package.swift create mode 100644 Tools/NavigationQualification/README.md diff --git a/AGENTS.md b/AGENTS.md index e5e6be1..7e36c49 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -4,11 +4,11 @@ Swift-JSON requires Swift tools/compiler 6.4+, Swift language mode 6 and macOS/SDK 27+. Read README.md, CONTRIBUTING.md and the relevant contracts in Documentation/Architecture before changing behavior. -- Keep seven public products: JSON, JSONSchema, JSONStreaming, JSONPatch, JSONHTML, - JSONBridges and the swift-json executable. JSONFilterRuntime and JSONCLIEngine are package-private. +- Keep eight public products: JSON, JSONSchema, JSONStreaming, JSONPatch, JSONHTML, + JSONBridges, JSONNavigation and the swift-json executable. JSONFilterRuntime and JSONCLIEngine are package-private. JSONHTML and opt-in JSONBridges depend on JSON only; core never re-exports the bridges. The approved CLI and E2 additions preserve historical product contracts. - JSONNavigation is experimental without a public product until its N1 release gate. + JSONNavigation is an opt-in product candidate depending on JSON only; merge/release remain human-gated. JSONRegexRuntime is package-private. Root package dependencies remain empty. - Preserve exact bounded decimals, decoded Unicode scalar identity, ordered objects with order-independent equality, one strict UTF-8 grammar, native diff --git a/Documentation/Architecture/API.md b/Documentation/Architecture/API.md index 0acd3c2..55b5292 100644 --- a/Documentation/Architecture/API.md +++ b/Documentation/Architecture/API.md @@ -1,7 +1,7 @@ # Public API contract This document describes the implemented public interface. Native compiler symbol -graphs supply the complete declarations in the six DocC catalogs. Examples +graphs supply the complete declarations in the seven DocC catalogs. Examples in the [README](../../README.md) are compiled and executed by the public consumer. ## Products and ownership @@ -9,6 +9,7 @@ in the [README](../../README.md) are compiled and executed by the public consume | Product | Main entry points | Owned implementation boundary | | --- | --- | --- | | JSON | JSON, JSONNumber, JSONObject, JSONParser, JSONWriter, JSONValueEncoder, JSONValueDecoder, JSONPointer, JSONDocument | Shared strict codec, exact decimal model, bounded traversal and native coding | +| JSONNavigation | JSONTraversal, JSONTraversalScope, JSONTraversalOptions | Exact many-node DFS, strict physical/virtual scopes, bounded metadata and explicit coverage; one core read-scope meter | | JSONBridges | BinaryInteger.jsonNumber, FixedWidthInteger/Double/Decimal.init(jsonNumber:), Double.jsonNumberFromRoundTripText | Optional one-delegate numeric conversions; explicit fidelity, no new authority | | JSONSchema | JSONSchemaDocument, JSONSchemaRegistry, JSONSchemaCompiler, CompiledJSONSchema, JSONSchemaValidator | Offline immutable plan, invocation-owned evaluation and private native regex | | JSONStreaming | JSONEventSequence, JSONValueSequence, NDJSONValueSequence, JSONTopLevelArraySequence, JSONAsyncWriter | Exclusive pull state, shared codec, strict framing and awaited handoffs | @@ -17,7 +18,7 @@ in the [README](../../README.md) are compiled and executed by the public consume | JSONHTML | JSONHTMLRenderer, JSONHTMLRenderingOptions, JSONHTMLLimits, JSONHTMLRenderReport, JSONHTMLAnnotation, JSONExportDocument, JSONExportOptions, JSONExportReport | Structured forms/cards and bounded native previews, exact HTML, native Apple transfer, immutable prepared JSON/text/Markdown/static HTML/opt-in styled RTF and cumulative budgets | JSON imports no siblings. JSONSchema depends on JSON and package-private -JSONRegexRuntime. Streaming, Patch, HTML and Bridges depend on JSON. There are seven public products: six libraries and the swift-json executable, +JSONRegexRuntime. Streaming, Patch, HTML and Bridges depend on JSON. There are eight candidate public products: seven libraries and the swift-json executable, and no external root-package dependencies. No HTTP, MCP or documentation-tool dependency is introduced. JSONHTML conditionally uses Apple SDK frameworks for explicit native transfer/PDF preparation; the portable value, schema, Patch and streaming contracts do not acquire UI semantics. @@ -244,3 +245,5 @@ includes `revisionKind: "source-sha256"` and `revision: "sha256:"`. This is SHA-256 of the ordered Package.swift plus Sources content manifest, excluding only the generated identity file itself. It is not a Git commit, binary digest or claim of publication. Generation/checking needs no Git, time, environment or network. + +JSONNavigation product promotion preserves all 56 N1 public declarations and resource semantics. Full-source admission precedes invalid depth/record-option validation, including oversized sources; N1Promotion.md records this preserved precedence. JSON imports no Navigation symbols implicitly. diff --git a/Documentation/Architecture/StructuralIntelligence/N1Promotion.md b/Documentation/Architecture/StructuralIntelligence/N1Promotion.md new file mode 100644 index 0000000..850057c --- /dev/null +++ b/Documentation/Architecture/StructuralIntelligence/N1Promotion.md @@ -0,0 +1,25 @@ +# N1 public-product candidate decision + +Approved for implementation: preserve all 56 existing public declarations, now +resolvable as the opt-in JSONNavigation library product. N1PublicAudit.json lists +the source-aware per-declaration decisions. New visibility is additive; this is +not a package version, merge approval or a published release. + +The immutable traversal captures its source; paths describe that source, not a +replacement. Mutable options configure each independent invocation. Selection +indices and occurrence ordinals retain their zero-based, first-examined semantics. +Filters affect emission; coverage is per occurrence rather than a union proof. +Errors/cancellation throw; callback computation and retained copies are caller work. +Package read scopes, state, meters and qualification observers remain hidden. + +P07 decision: keep the existing source-admission-before-depth/record-validation +precedence. An oversized source can therefore report its admission resource error +before an invalid option. Small-source invalid options report configuration errors. +No error precedence is changed during promotion. N2 sampling configuration has a +separate pre-admission check because it is a new contract. + +Public SwiftPM consumer Debug/Release, isolation negatives, docs, all platform +lanes and Git-free reproduction must qualify the final source before recommending +release readiness. Actual outcomes accompany the return; this document is an API +review decision, not a claim that unfinished qualification has passed. Draft #34 +and the immutable N1 anchor remain untouched. No PR-ready/merge/release transition. diff --git a/Documentation/Architecture/StructuralIntelligence/N1PublicAudit.json b/Documentation/Architecture/StructuralIntelligence/N1PublicAudit.json new file mode 100644 index 0000000..8ed9871 --- /dev/null +++ b/Documentation/Architecture/StructuralIntelligence/N1PublicAudit.json @@ -0,0 +1,500 @@ +{ + "parent": "4403b9ab3b0a1fadc57c12a283cfabb255f6237a", + "authored_declarations": 56, + "source_graph_audit": "fresh Swift6.4 baseline compilation; package/private symbols excluded", + "decisions": [ + { + "path": [ + "JSONScopeOverlapPolicy" + ], + "declaration": "enum JSONScopeOverlapPolicy", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONScopeOverlapPolicy", + "orderedOccurrences" + ], + "declaration": "case orderedOccurrences", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONScopeOverlapPolicy", + "rejectAmbiguous" + ], + "declaration": "case rejectAmbiguous", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONScopeOverlapPolicy", + "uniquePhysicalNodes" + ], + "declaration": "case uniquePhysicalNodes", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversal" + ], + "declaration": "struct JSONTraversal", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversal", + "collect(scope:options:maximumRecords:)" + ], + "declaration": "func collect(scope: JSONTraversalScope = .subtree(at: []), options: JSONTraversalOptions = .init(), maximumRecords: Int = 100_000) throws -> JSONOperationReport", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversal", + "document" + ], + "declaration": "let document: JSONDocument", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversal", + "init(document:limits:)" + ], + "declaration": "init(document: JSONDocument, limits: JSONLimits = .balanced)", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversal", + "limits" + ], + "declaration": "let limits: JSONLimits", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversal", + "visit(scope:options:_:)" + ], + "declaration": "func visit(scope: JSONTraversalScope = .subtree(at: []), options: JSONTraversalOptions = .init(), _ visitor: (JSONTraversalHit, JSON) throws -> JSONTraversalAction) throws -> JSONOperationReport", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalAction" + ], + "declaration": "enum JSONTraversalAction", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalAction", + "continue" + ], + "declaration": "case `continue`", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalAction", + "skipDescendants" + ], + "declaration": "case skipDescendants", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalAction", + "stop" + ], + "declaration": "case stop", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalCollection" + ], + "declaration": "struct JSONTraversalCollection", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalCollection", + "nodes" + ], + "declaration": "let nodes: [JSONTraversalHit]", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalCollection", + "summary" + ], + "declaration": "let summary: JSONTraversalSummary", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalCompletion" + ], + "declaration": "enum JSONTraversalCompletion", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalCompletion", + "complete" + ], + "declaration": "case complete", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalCompletion", + "restricted" + ], + "declaration": "case restricted", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalCompletion", + "visitorStopped" + ], + "declaration": "case visitorStopped", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalFailure" + ], + "declaration": "enum JSONTraversalFailure", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalFailure", + "ambiguousRoots(first:second:)" + ], + "declaration": "case ambiguousRoots(first: Int, second: Int)", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalFailure", + "collectionLimitExceeded(limit:)" + ], + "declaration": "case collectionLimitExceeded(limit: Int)", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalHit" + ], + "declaration": "struct JSONTraversalHit", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalHit", + "absoluteLocation" + ], + "declaration": "let absoluteLocation: [JSONLocationComponent]", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalHit", + "kind" + ], + "declaration": "let kind: JSONTraversalKind", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalHit", + "occurrenceIndex" + ], + "declaration": "let occurrenceIndex: UInt64", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalHit", + "relativeDepth" + ], + "declaration": "let relativeDepth: Int", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalHit", + "scopeRootIndex" + ], + "declaration": "let scopeRootIndex: Int", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalHit", + "sourceSpan" + ], + "declaration": "let sourceSpan: JSONSourceSpan?", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalKind" + ], + "declaration": "enum JSONTraversalKind", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalKind", + "array" + ], + "declaration": "case array", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalKind", + "boolean" + ], + "declaration": "case boolean", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalKind", + "null" + ], + "declaration": "case null", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalKind", + "number" + ], + "declaration": "case number", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalKind", + "object" + ], + "declaration": "case object", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalKind", + "string" + ], + "declaration": "case string", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalOptions" + ], + "declaration": "struct JSONTraversalOptions", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalOptions", + "depthLimit" + ], + "declaration": "var depthLimit: Int?", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalOptions", + "emitKinds" + ], + "declaration": "var emitKinds: Set?", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalOptions", + "includeScopeRoot" + ], + "declaration": "var includeScopeRoot: Bool", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalOptions", + "includeSourceSpans" + ], + "declaration": "var includeSourceSpans: Bool", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalOptions", + "init(depthLimit:includeScopeRoot:emitKinds:includeSourceSpans:)" + ], + "declaration": "init(depthLimit: Int? = nil, includeScopeRoot: Bool = true, emitKinds: Set? = nil, includeSourceSpans: Bool = false)", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalScope" + ], + "declaration": "enum JSONTraversalScope", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalScope", + "subtree(at:)" + ], + "declaration": "case subtree(at: [JSONLocationComponent])", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalScope", + "virtual(roots:overlap:)" + ], + "declaration": "case virtual(roots: [[JSONLocationComponent]], overlap: JSONScopeOverlapPolicy = .rejectAmbiguous)", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalSummary" + ], + "declaration": "struct JSONTraversalSummary", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalSummary", + "completion" + ], + "declaration": "var completion: JSONTraversalCompletion { get }", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalSummary", + "deduplicatedCount" + ], + "declaration": "var deduplicatedCount: UInt64 { get }", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalSummary", + "depthLimitedSubtrees" + ], + "declaration": "var depthLimitedSubtrees: UInt64 { get }", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalSummary", + "emittedCount" + ], + "declaration": "var emittedCount: UInt64 { get }", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalSummary", + "maximumDepthVisited" + ], + "declaration": "var maximumDepthVisited: Int { get }", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalSummary", + "prunedSubtrees" + ], + "declaration": "var prunedSubtrees: UInt64 { get }", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalSummary", + "scopeRootCount" + ], + "declaration": "var scopeRootCount: Int { get }", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + }, + { + "path": [ + "JSONTraversalSummary", + "visitedCount" + ], + "declaration": "var visitedCount: UInt64 { get }", + "decision": "keep", + "reason": "Exact source-bound metadata/coverage or existing single-ledger operation; no competing value/path/cursor authority" + } + ] +} diff --git a/Documentation/Architecture/StructuralIntelligence/SourceReconciliation.md b/Documentation/Architecture/StructuralIntelligence/SourceReconciliation.md new file mode 100644 index 0000000..894365e --- /dev/null +++ b/Documentation/Architecture/StructuralIntelligence/SourceReconciliation.md @@ -0,0 +1,22 @@ +# N1P/N2A source reconciliation + +Research/N1 parent is4403b9ab3b0a1fadc57c12a283cfabb255f6237a, draft PR34. +Fetched main remains037e735dc6224789e4d04d2c18d15b8d27440198. +Successor codex/structural-navigation-n1p-n2a branches from that exact N1 head. +PR34, its history and its worktree are unchanged. PR31 remains64264218dc0073a5738ab557bfa25b3bb9f6fa7a; +PR35 remains73efb65189f3f7e08e878a3b0fb6030f34524e4b at reconciliation. +Both are drafts. Their manifest/CI/docs edits overlap and require a future explicit +integration; none is merged here. Composition's separate owner is not a borrowed +Navigation scope. Core JSONReadScope/CodingState/WorkMeter, exact comparison, +typed selection/path construction and source maps remain unchanged authorities. + +The maintainer-provided NAV-RETURN-1 and independently recorded PR/workflow states +are historical evidence. This wave does not reconstruct or independently certify +the unavailable250MB control-tower bundle. Fresh commands and source-bound receipts +qualify this successor. Private evidence remains under ignored Artifacts. + +Approved: N1 additive product candidate, unchanged56 public declarations and P07 +precedence; package-only borrowing proof; N2 only after its gate. Rejected: opening +composition/read/Pointer meters inside owned callbacks, unmetered String maps and +partial success on errors. Deferred: snapshot/projection/persistence/BFS/CLI/HTML, +DSL/OpenAPI integration, EngineBench and release/merge actions. diff --git a/Documentation/CI/README.md b/Documentation/CI/README.md index 932a9f0..a3e134f 100644 --- a/Documentation/CI/README.md +++ b/Documentation/CI/README.md @@ -1,5 +1,15 @@ # Native CI +## N1 product-candidate increment + +Promotion adds the JSONNavigation library product after a 56-declaration audit, +with a real external SwiftPM consumer in Debug/Release. Two new P07 tests preserve +source-admission-first precedence. Focused discovery is now 39 functions; all37 +N1 identities remain. Exact roots are 585 native/569 Linux and 481 WASI, with the +same325/288 parameter inventories and42/41 shared functions. Seven public DocC +catalogues include Navigation; private borrowed interfaces are never public API. +Actual receipts establish passes. Earlier stage counts below retain their source. + ## Experimental N1 branch The Structural Intelligence branch adds exactly 37 Navigation functions and one diff --git a/Documentation/DocumentationTooling.md b/Documentation/DocumentationTooling.md index b46024c..c3194fb 100644 --- a/Documentation/DocumentationTooling.md +++ b/Documentation/DocumentationTooling.md @@ -1,7 +1,7 @@ # Building and maintaining the DocC catalogs Swift source comments are the API documentation authority. Native compiler symbol -graphs supply the declarations and links for six Swift DocC catalogs. Each catalog +graphs supply the declarations and links for seven Swift DocC catalogs. Each catalog combines the product reference with curated Topics and a focused usage guide. See the [Swift DocC documentation](https://www.swift.org/documentation/docc/). @@ -19,7 +19,7 @@ python3 Scripts/ci.py --lane docs The lane records native preflight, extracts fresh public symbol graphs, requires summaries and named-parameter documentation on every authored public declaration, checks README Swift fences against their executable consumer source, runs that -consumer, and compiles all six DocC catalogs with warnings as errors. Zero public +consumer, and compiles all seven DocC catalogs with warnings as errors. Zero public symbols, missing comments, stale examples or a failed catalog fail the lane. | Output | Purpose | @@ -33,9 +33,9 @@ symbols, missing comments, stale examples or a failed catalog fail the lane. | `.build/handoff/docc/symbols/` | Public compiler symbol graphs grouped by product | | `.build/handoff/docc/coverage.json` | Counts and documentation-coverage failures | | `.build/handoff/docc/receipt.json` | Commands, toolchain, counts, exits and diagnostics | -| `.build/handoff/docc/compiled-catalogs.tar.gz` | All six compiled catalogs with their exact native filenames | +| `.build/handoff/docc/compiled-catalogs.tar.gz` | All seven compiled catalogs with their exact native filenames | | `.build/handoff/docc/compiled-catalogs.MANIFEST.sha256` | Independently verifiable hashes for every archived catalog file | -| `.build/handoff/pages/site/` | Static site, landing page and all six references under the project base path | +| `.build/handoff/pages/site/` | Static site, landing page and all seven references under the project base path | | `.build/handoff/pages/receipt.json` | Native transformations, input/output hashes and route/asset verification | Open a `.doccarchive` in Xcode for the compiled reference. To preview a source @@ -64,7 +64,7 @@ The manifest and receipt preserve file-level and archive-level digests. The docs lane uses native `docc process-archive transform-for-static-hosting` to prepare each qualified archive under `/Swift-JSON/`. A shared landing -page links all six references and guides. The build verifies product/guide routes, +page links all seven references and guides. The build verifies product/guide routes, local HTML links and assets, rejects private-path/credential markers and symlinks, and records a file manifest. Only the generated site is packaged for Pages; source graphs, command logs and private maintainer records are not website content. diff --git a/Documentation/Qualification/TestDiscovery.json b/Documentation/Qualification/TestDiscovery.json index 40b0c2c..017c666 100644 --- a/Documentation/Qualification/TestDiscovery.json +++ b/Documentation/Qualification/TestDiscovery.json @@ -10,7 +10,7 @@ "JSONHTMLTests": 97, "JSONBridgesTests": 10, "JSONCLITests": 88, - "JSONNavigationTests": 37 + "JSONNavigationTests": 39 }, "parameterized_invocations": 325, "qa_functions": { @@ -67,7 +67,7 @@ "JSONHTMLTests": 81, "JSONBridgesTests": 10, "JSONCLITests": 88, - "JSONNavigationTests": 37 + "JSONNavigationTests": 39 }, "wasi_root_functions": { "JSONTests": 190, @@ -78,7 +78,7 @@ "JSONIntegrationTests": 20, "JSONHTMLTests": 81, "JSONBridgesTests": 10, - "JSONNavigationTests": 37 + "JSONNavigationTests": 39 }, "wasi_parameterized_invocations": 288, "portable_shared_state_functions": { diff --git a/Documentation/README.md b/Documentation/README.md index 2c7ee0d..84411d4 100644 --- a/Documentation/README.md +++ b/Documentation/README.md @@ -6,7 +6,7 @@ behavioral contracts and native qualification procedure. ## API references and guided reading -The six native DocC catalogs combine inline API documentation with focused guides: +The seven candidate native DocC catalogs combine inline API documentation with focused guides: | Product | Catalog source | Guide | | --- | --- | --- | @@ -15,6 +15,7 @@ The six native DocC catalogs combine inline API documentation with focused guide | JSONStreaming | [JSONStreaming](../Sources/JSONStreaming/Documentation.docc/JSONStreaming.md) | [Completion and backpressure](../Sources/JSONStreaming/Documentation.docc/CompletionAndBackpressure.md) | | JSONHTML | [JSONHTML](../Sources/JSONHTML/Documentation.docc/JSONHTML.md) | [Formatted rendering](../Sources/JSONHTML/Documentation.docc/FormattedRendering.md) | | JSONBridges | [JSONBridges](../Sources/JSONBridges/Documentation.docc/JSONBridges.md) | [Numeric fidelity](../Sources/JSONBridges/Documentation.docc/NumericFidelity.md) | +| JSONNavigation | [JSONNavigation](../Sources/JSONNavigation/Documentation.docc/JSONNavigation.md) | [Exact traversal](../Sources/JSONNavigation/Documentation.docc/Traversal.md) | | JSONPatch | [JSONPatch](../Sources/JSONPatch/Documentation.docc/JSONPatch.md) | [Choosing and applying patches](../Sources/JSONPatch/Documentation.docc/ApplyingPatches.md) | [Browse the public documentation](https://thorfuchs.github.io/Swift-JSON/) or diff --git a/Package.swift b/Package.swift index 4170c9c..4e78f36 100644 --- a/Package.swift +++ b/Package.swift @@ -12,11 +12,12 @@ let package = Package( .library(name: "JSONPatch", targets: ["JSONPatch"]), .library(name: "JSONHTML", targets: ["JSONHTML"]), .library(name: "JSONBridges", targets: ["JSONBridges"]), + .library(name: "JSONNavigation", targets: ["JSONNavigation"]), .executable(name: "swift-json", targets: ["JSONCLI"]) ], targets: [ .target(name: "JSON"), - // Experimental N1 target. Product promotion requires separate release-gate review. + // Opt-in N1 product candidate; promotion does not change core navigation semantics. .target(name: "JSONNavigation", dependencies: ["JSON"]), .testTarget(name: "JSONNavigationTests", dependencies: ["JSONNavigation", "JSON"], exclude: ["Fixtures"]), .target(name: "JSONBridges", dependencies: ["JSON"]), diff --git a/README.md b/README.md index 4005f31..b14fc75 100644 --- a/README.md +++ b/README.md @@ -17,9 +17,9 @@ Maintained by [Thorsten Fuchs](https://github.com/ThorFuchs). Swift-JSON follows semantic versioning. Use a released version and retain `Package.resolved` for reproducible builds; `main` tracks ongoing development. -This feature branch also contains an [experimental structural traversal target](Documentation/Architecture/StructuralIntelligence/API-DECISIONS.md). -It preserves the seven released products. JSONNavigation product promotion remains -gated; the [compiled traversal guide](Sources/JSONNavigation/Documentation.docc/Traversal.md) +This feature branch also contains an [opt-in structural traversal product candidate](Documentation/Architecture/StructuralIntelligence/N1Promotion.md). +It preserves the seven released products and proposes JSONNavigation as the eighth. +Merge and release remain human-gated; the [compiled traversal guide](Sources/JSONNavigation/Documentation.docc/Traversal.md) describes its many-node scope, exact locations, finite accounting and coverage. Published **1.5.0** provides six libraries and the CLI. This development branch @@ -77,6 +77,7 @@ Choose the products your application needs: | **JSONHTML** | Exact HTML and immutable exports since 1.3.0; structured forms/cards and bounded previews on unreleased main | | **swift-json** | Bounded command-line JSON workflows (available since 1.5.0) | | **JSONBridges** | Opt-in native integer, Double and Foundation Decimal conversions (available in the 1.4.0 tag and 1.5.0 release) | +| **JSONNavigation** | Unreleased candidate: exact many-node DFS, physical/virtual scopes, finite metadata and explicit coverage | | **JSONPatch** | Staged RFC 6902 JSON Patch and RFC 7396 Merge Patch | `JSONSchema`, `JSONStreaming`, `JSONPatch`, `JSONHTML` and opt-in `JSONBridges` build on `JSON`. The package-private @@ -456,7 +457,7 @@ The [documentation index](Documentation/README.md) links the behavior contracts. provide public API references, focused guides, parameter descriptions and failure contracts, compiled from the native Swift public symbol graphs. -Build all six catalogs on a supported native host: +Build all seven candidate catalogs on a supported native host: ```sh python3 Scripts/ci.py --lane docs @@ -564,3 +565,15 @@ cumulative reports. It makes no requests and never rewrites optional properties, Incompatibility exits1; operational errors remain errors. Apple schema/model bridges are separate. See the [provider contract](Documentation/Architecture/Release1.4/Providers.md) and [compiled public consumer](Tools/CLIQualification/Sources/ProviderConsumer/Main.swift). + +## Exact structural navigation (unreleased candidate) + +`JSONNavigation` adds many-node DFS preorder over a captured canonical document, +with insertion-order object members, increasing array indices and exact typed +locations. Physical and virtual scopes, explicit overlap/stop/pruning policies, +bounded metadata collection and coverage share one finite cumulative core budget. +Add the JSONNavigation product and import it explicitly. Existing one-node reads +remain in JSON. Full source admission precedes traversal option validation. +See the [compiled traversal guide](Sources/JSONNavigation/Documentation.docc/Traversal.md) +and [real external SwiftPM consumer](Tools/NavigationQualification). This branch +prepares eight products; published 1.5.0 and its seven-product contract are unchanged. diff --git a/Scripts/README.md b/Scripts/README.md index 26c3e7a..50d07a0 100644 --- a/Scripts/README.md +++ b/Scripts/README.md @@ -9,12 +9,12 @@ separate from the dependency-free library. Native lanes fail on unsupported host | `python3 Scripts/preflight.py` | Actual native OS/compiler/SDK receipt | | `python3 Scripts/ci.py --lane native` | Manifests, builds, Swift Testing, consumers and suites | | `python3 Scripts/ci.py --lane safety` | Address/Thread Sanitizer and strict memory safety | -| `python3 Scripts/ci.py --lane navigation` | Experimental N1 exact discovery, Debug/Release, strict-memory and external compiler/consumer/DocC proof; no product promotion | -| `python3 Scripts/ci.py --lane linux` | Actual Linux preflight, all seven products, exact root/cap/corpus/consumer counts | +| `python3 Scripts/ci.py --lane navigation` | N1 product exact discovery, Debug/Release, strict-memory and real external SwiftPM consumer/compiler/DocC proof; no release action | +| `python3 Scripts/ci.py --lane linux` | Actual Linux preflight, all eight candidate products, exact root/cap/corpus/consumer counts | | `python3 Scripts/ci.py --lane linux-safety` | Linux Address/Thread Sanitizer and strict memory safety | | `python3 Scripts/ci.py --lane wasm` | Matched Swift 6.4 WASI debug/release, exact root/corpus/cap/consumer counts, two-host public parity and structured resource failures | | `python3 Scripts/qualify_linux_reproduction.py --output PATH` | Actual source archive, byte-equal rebuild, clean extraction, build/tests and public consumer | -| `python3 Scripts/ci.py --lane docs` | Six DocC catalogs, authored API/parameter coverage, executed README examples and verified static Pages site | +| `python3 Scripts/ci.py --lane docs` | Seven DocC catalogs, authored API/parameter coverage, executed README examples and verified static Pages site | | `python3 Scripts/build_documentation_site.py` | Transform already-qualified DocC archives and verify static routes/assets | | `python3 Scripts/qualification_watchdog.py --timeout 900 --output PATH -- COMMAND` | Process-group timeout and native receipt | | `python3 Scripts/archive_candidate.py --output PATH` | Public source archive with exact hashes and byte-equal rebuild | diff --git a/Scripts/build_documentation.py b/Scripts/build_documentation.py index 779a5a3..9bdd2ff 100644 --- a/Scripts/build_documentation.py +++ b/Scripts/build_documentation.py @@ -60,7 +60,7 @@ def package_catalogs(output): 'bytes': archive.stat().st_size, 'verified_files': len(records), 'manifest': str(manifest.relative_to(ROOT)), 'manifest_sha256': hashlib.sha256(manifest.read_bytes()).hexdigest(), - 'policy': 'Six native DocC archives; exact internal filenames, sorted entries and normalized tar/gzip metadata.'} + 'policy': 'Seven native DocC archives; exact internal filenames, sorted entries and normalized tar/gzip metadata.'} def main(): diff --git a/Scripts/build_documentation_site.py b/Scripts/build_documentation_site.py index 83f9070..ccc2f03 100644 --- a/Scripts/build_documentation_site.py +++ b/Scripts/build_documentation_site.py @@ -25,14 +25,16 @@ 'JSONStreaming': ('Completion and backpressure', 'completionandbackpressure'), 'JSONPatch': ('Choosing and applying patches', 'applyingpatches'), 'JSONHTML': ('Exact interactive HTML', 'interactiverendering'), - 'JSONBridges': ('Opt-in native conversions', 'numericfidelity')} + 'JSONBridges': ('Opt-in native conversions', 'numericfidelity'), + 'JSONNavigation': ('Exact bounded structural traversal', 'traversal')} DESCRIPTIONS = { 'JSON': 'Exact values, strict UTF-8, native Codable, Pointer, presence and finite resource reports.', 'JSONSchema': 'Draft 2020-12, explicit offline registries, immutable plans, annotations and bounded regex.', 'JSONStreaming': 'Pull events and values, strict NDJSON, root-array completion and awaited output chunks.', 'JSONPatch': 'Transactional RFC 6902 JSON Patch and RFC 7396 Merge Patch with exact value semantics.', 'JSONHTML': 'Exact standalone HTML with offline disclosure/search and native-byte copy/download.', - 'JSONBridges': 'Opt-in trusted integer construction and policy-explicit Double and Foundation Decimal projection.'} + 'JSONBridges': 'Opt-in trusted integer construction and policy-explicit Double and Foundation Decimal projection.', + 'JSONNavigation': 'Exact typed DFS with physical and virtual scopes, explicit coverage and one cumulative budget.'} class Links(HTMLParser): @@ -99,7 +101,7 @@ def landing(commit):
Public Swift documentation

Exact JSON. Clear contracts.

-

Keep decimal values exact, Unicode scalar keys distinct and resource use explicit. Explore six Swift libraries that carry those semantics from input bytes to validated, transformed and encoded output.

+

Keep decimal values exact, Unicode scalar keys distinct and resource use explicit. Explore seven Swift libraries that carry those semantics from input bytes to validated, transformed and encoded output.

Swift 6.4+ · Swift language mode 6 · macOS/SDK 27+ · No package dependencies

{''.join(cards)}

Start with the contract

diff --git a/Scripts/ci.py b/Scripts/ci.py index 8d7c650..0638a02 100644 --- a/Scripts/ci.py +++ b/Scripts/ci.py @@ -191,8 +191,8 @@ def check_result(command, code, log, events=None): passed = data['observed'] == data['passed'] == expected and data['failed'] == data['policy'] == data['blocked'] == 0 if command == ['swift', 'package', 'dump-package'] and passed: d = json.loads(log) - passed = sorted(p['name'] for p in d['products']) == ['JSON', 'JSONBridges', 'JSONHTML', 'JSONPatch', 'JSONSchema', 'JSONStreaming', 'swift-json'] and not d['dependencies'] and d['swiftLanguageVersions'] == ['6'] and d['toolsVersion']['_version'] == '6.4.0' and d['platforms'] == [{'options': [], 'platformName': 'macos', 'version': '27.0'}, {'options': [], 'platformName': 'ios', 'version': '27.0'}] - passed = passed and {p['name']: p['targets'] for p in d['products']} == dict({name: [name] for name in ['JSON', 'JSONSchema', 'JSONStreaming', 'JSONPatch', 'JSONHTML', 'JSONBridges']}, **{'swift-json': ['JSONCLI']}) + passed = sorted(p['name'] for p in d['products']) == ['JSON', 'JSONBridges', 'JSONHTML', 'JSONNavigation', 'JSONPatch', 'JSONSchema', 'JSONStreaming', 'swift-json'] and not d['dependencies'] and d['swiftLanguageVersions'] == ['6'] and d['toolsVersion']['_version'] == '6.4.0' and d['platforms'] == [{'options': [], 'platformName': 'macos', 'version': '27.0'}, {'options': [], 'platformName': 'ios', 'version': '27.0'}] + passed = passed and {p['name']: p['targets'] for p in d['products']} == dict({name: [name] for name in ['JSON', 'JSONSchema', 'JSONStreaming', 'JSONPatch', 'JSONHTML', 'JSONBridges', 'JSONNavigation']}, **{'swift-json': ['JSONCLI']}) targets = {t['name']: t for t in d['targets']} passed = passed and set(targets) == {'JSON', 'JSONNavigation', 'JSONNavigationTests', 'JSONIntegrationTests', 'JSONBridges', 'JSONBridgesTests', 'JSONSchema', 'JSONStreaming', 'JSONPatch', 'JSONHTML', 'JSONRegexRuntime', 'JSONTests', 'JSONSchemaTests', 'JSONStreamingTests', 'JSONPatchTests', 'JSONHTMLTests', 'JSONRegexRuntimeTests', 'JSONFilterRuntime', 'JSONCLIEngine', 'JSONCLI', 'JSONCLITests'} and targets['JSONHTML']['dependencies'] == [{'byName': ['JSON', None]}] and targets['JSONBridges']['dependencies'] == [{'byName': ['JSON', None]}] and targets['JSONNavigation']['dependencies'] == [{'byName': ['JSON', None]}] and targets['JSONNavigationTests']['dependencies'] == [{'byName': ['JSONNavigation', None]}, {'byName': ['JSON', None]}] and targets['JSONFilterRuntime']['dependencies'] == [{'byName': ['JSON', None]}] and targets['JSONCLI']['type'] == 'executable' if command == ['swift', 'package', 'show-dependencies', '--format', 'json'] and passed: diff --git a/Scripts/documentation_catalog.py b/Scripts/documentation_catalog.py index add1f6e..9458193 100644 --- a/Scripts/documentation_catalog.py +++ b/Scripts/documentation_catalog.py @@ -7,7 +7,7 @@ import urllib.parse ROOT = pathlib.Path(__file__).resolve().parents[1] -PRODUCTS = ('JSON', 'JSONSchema', 'JSONStreaming', 'JSONPatch', 'JSONHTML', 'JSONBridges') +PRODUCTS = ('JSON', 'JSONSchema', 'JSONStreaming', 'JSONPatch', 'JSONHTML', 'JSONBridges', 'JSONNavigation') def public_symbols(graph_dir): diff --git a/Scripts/qualify_navigation.py b/Scripts/qualify_navigation.py index f1245ff..4d200fe 100644 --- a/Scripts/qualify_navigation.py +++ b/Scripts/qualify_navigation.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # SPDX-License-Identifier: Apache-2.0 -"""Compile/run the unpublished N1 module as an external consumer, including negative compiler probes.""" +"""Qualify the N1 library product with a real external SwiftPM consumer, including negative compiler probes.""" import argparse import gzip import hashlib @@ -64,7 +64,7 @@ def main(): output = ROOT / args.output output.mkdir(parents=True, exist_ok=True) receipt = {'schema_version': 1, 'status': 'running', 'commands': [], - 'scope': 'External Swift module API proof; JSONNavigation is not a released SwiftPM product', + 'scope': 'External SwiftPM product/API proof; candidate source is not a published release', 'consumer_sha256': hashlib.sha256((ROOT / 'Tools/NavigationQualification/Consumer.swift').read_bytes()).hexdigest()} def run(name, command, expected=None): @@ -95,9 +95,7 @@ def run(name, command, expected=None): raise ValueError('Missing built module objects: ' + module) objects.extend(str(p) for p in selected) common = ['swiftc', '-swift-version', '6', '-warnings-as-errors', '-I', str(modules), '-package-name', 'navigation_external_consumer'] - executable = output / ('consumer-' + config) - run(config + '-consumer-compile', common + ['-parse-as-library', str(ROOT / 'Tools/NavigationQualification/Consumer.swift'), *objects, '-o', str(executable)]) - text = run(config + '-consumer-run', [str(executable)]) + text = run(config + '-swiftpm-consumer', ['swift', 'run', '-c', config, '--package-path', 'Tools/NavigationQualification', 'NavigationConsumer']) observed = re.findall(r'^NAVIGATION_CHECK (\S+) passed$', text, re.M) if len(observed) != 18 or set(observed) != CHECKS or 'NAVIGATION_CONSUMER passed cases=18' not in text: raise ValueError('Missing/duplicate public consumer outcomes') @@ -134,7 +132,7 @@ def run(name, command, expected=None): for path in (ROOT / '.build/out/symbolgraph').glob('JSONNavigation*.symbols.json'): shutil.copyfile(path, graphs / path.name) import documentation_catalog - # This local audit does not promote an experimental module to the public site. + # The public site separately qualifies the complete seven-library inventory. documentation_catalog.PRODUCTS = ('JSONNavigation',) coverage = documentation_catalog.verify_comments(documentation_catalog.public_symbols(graphs)) receipt['experimental_api_coverage'] = coverage @@ -142,7 +140,7 @@ def run(name, command, expected=None): raise ValueError('Undocumented experimental API: ' + str(coverage['errors'])) run('docc', ['xcrun', 'docc', 'convert', str(ROOT / 'Sources/JSONNavigation/Documentation.docc'), '--additional-symbol-graph-dir', str(graphs), '--output-dir', str(output / 'JSONNavigation.doccarchive'), - '--fallback-bundle-identifier', 'org.swift-json.experimental.JSONNavigation', '--warnings-as-errors']) + '--fallback-bundle-identifier', 'org.swift-json.JSONNavigation', '--warnings-as-errors']) receipt['compiled_docc'] = pack_catalog(output / 'JSONNavigation.doccarchive', output) receipt['status'] = 'passed' except (OSError, ValueError, tarfile.TarError, subprocess.TimeoutExpired) as error: diff --git a/Scripts/wasm_support.py b/Scripts/wasm_support.py index 3a068d5..102f0d0 100644 --- a/Scripts/wasm_support.py +++ b/Scripts/wasm_support.py @@ -68,7 +68,7 @@ def binary(scratch, config, name): if preamble and not re.fullmatch(r"Another instance of SwiftPM .*waiting until that process has finished execution\.\.\.", preamble): raise ValueError('Unexpected manifest preamble: ' + preamble) manifest = json.loads(manifest_text[start:]) - if manifest['dependencies'] or sorted(p['name'] for p in manifest['products']) != ['JSON', 'JSONBridges', 'JSONHTML', 'JSONPatch', 'JSONSchema', 'JSONStreaming', 'swift-json']: + if manifest['dependencies'] or sorted(p['name'] for p in manifest['products']) != ['JSON', 'JSONBridges', 'JSONHTML', 'JSONNavigation', 'JSONPatch', 'JSONSchema', 'JSONStreaming', 'swift-json']: raise ValueError('Changed public products/dependencies') def invoke(engine, path, mode='command', arguments=(), repo=True, resources=True): if engine == 'node': diff --git a/Sources/JSONCLIEngine/CLIBuildIdentity.swift b/Sources/JSONCLIEngine/CLIBuildIdentity.swift index 2df1adb..83f03af 100644 --- a/Sources/JSONCLIEngine/CLIBuildIdentity.swift +++ b/Sources/JSONCLIEngine/CLIBuildIdentity.swift @@ -2,6 +2,6 @@ // Generated by Scripts/generate_cli_identity.py; excludes this file. // SHA-256 of the ordered Package.swift + Sources content manifest, not a Git commit. package enum CLIBuildIdentity { - package static let revision = "sha256:4bf62947afb2d30e64351ea20495cc7d6cef296975bfe2e0564c544ae8b6aaf4" + package static let revision = "sha256:fa1d5c9ebb416f5f82a2886d1ea3d1bdb48bf6fa3b9a3c34769eb82a3c81900f" package static let kind = "source-sha256" } diff --git a/Sources/JSONNavigation/Documentation.docc/JSONNavigation.md b/Sources/JSONNavigation/Documentation.docc/JSONNavigation.md index 9e65c2d..f76277c 100644 --- a/Sources/JSONNavigation/Documentation.docc/JSONNavigation.md +++ b/Sources/JSONNavigation/Documentation.docc/JSONNavigation.md @@ -2,9 +2,9 @@ Exact, synchronous, bounded exploration of many nodes in one canonical JSON source. -This is an experimental N1 target, **not a released SwiftPM product**. The package's -seven public products remain unchanged. Product promotion requires the recorded -correctness, resource, compiler, platform and API review gate. +JSONNavigation is an opt-in library product candidate on this development branch. +Add its SwiftPM product and import it explicitly; core JSON does not re-export it. +Product visibility does not establish a published version or approval to merge. The core JSON module continues to own one-node lookup, exact numbers and keys, presence and RFC 6901 Pointer. Use ``JSONTraversal`` for deterministic DFS preorder, diff --git a/Sources/JSONNavigation/Documentation.docc/Traversal.md b/Sources/JSONNavigation/Documentation.docc/Traversal.md index b04f9bc..5f01f24 100644 --- a/Sources/JSONNavigation/Documentation.docc/Traversal.md +++ b/Sources/JSONNavigation/Documentation.docc/Traversal.md @@ -74,3 +74,9 @@ an unqualified hash index. Complete path copies are bounded by the existing read scope; deep frontiers can use quadratic path metadata. No EngineBench speed, linear total-time, zero-copy or fixed-memory claim is made. Classification, snapshots, projections, persistence, async actors, query syntax and rendering are later gates. + +Full captured-source admission precedes validation of depth and collection options. +An oversized source may therefore refuse admission before a negative option is +reported. A valid small source with a negative option throws invalidLimits. +The real external SwiftPM consumer resolves the JSONNavigation product in Debug +and Release; package scopes/meters and the owned context remain inaccessible. diff --git a/Tests/JSONNavigationTests/PromotionTests.swift b/Tests/JSONNavigationTests/PromotionTests.swift new file mode 100644 index 0000000..e6be180 --- /dev/null +++ b/Tests/JSONNavigationTests/PromotionTests.swift @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: Apache-2.0 +import Testing +import JSON +import JSONNavigation + +@Test func navigationPromotionDepthValidationPreservesAdmissionPrecedence() throws { + for oversized in [false, true] { + var limits = JSONLimits.balanced; limits[.nodes] = 1 + let value: JSON = oversized ? .array([.null]) : .null + do { + _ = try JSONTraversal(document: .init(root: value), limits: limits).visit(options: .init(depthLimit: -1)) { _, _ in + Issue.record("Invalid invocation must not call visitor"); return .continue + } + Issue.record("Expected refusal") + } catch let failure as JSONFailure { + #expect(failure.category == (oversized ? .resource : .configuration)) + #expect(failure.code == (oversized ? .limitExceeded : .invalidLimits)) + #expect(failure.resource?.metric == (oversized ? .nodes : nil)) + } + } +} + +@Test func navigationPromotionRecordValidationPreservesAdmissionPrecedence() throws { + for oversized in [false, true] { + var limits = JSONLimits.balanced; limits[.nodes] = 1 + let value: JSON = oversized ? .array([.null]) : .null + do { + _ = try JSONTraversal(document: .init(root: value), limits: limits).collect(maximumRecords: -1) + Issue.record("Expected refusal") + } catch let failure as JSONFailure { + #expect(failure.category == (oversized ? .resource : .configuration)) + #expect(failure.code == (oversized ? .limitExceeded : .invalidLimits)) + #expect(failure.resource?.metric == (oversized ? .nodes : nil)) + } + } +} diff --git a/Tools/NavigationQualification/Package.swift b/Tools/NavigationQualification/Package.swift new file mode 100644 index 0000000..0437236 --- /dev/null +++ b/Tools/NavigationQualification/Package.swift @@ -0,0 +1,9 @@ +// swift-tools-version: 6.4 +// SPDX-License-Identifier: Apache-2.0 +import PackageDescription +let package = Package(name: "NavigationQualification", platforms: [.macOS("27.0"), .iOS("27.0")], + dependencies: [.package(name: "Swift-JSON", path: "../..")], + targets: [.executableTarget(name: "NavigationConsumer", dependencies: [ + .product(name: "JSON", package: "Swift-JSON"), + .product(name: "JSONNavigation", package: "Swift-JSON") + ], path: ".", exclude: ["README.md"], sources: ["Consumer.swift"])], swiftLanguageModes: [.v6]) diff --git a/Tools/NavigationQualification/README.md b/Tools/NavigationQualification/README.md new file mode 100644 index 0000000..f31ab63 --- /dev/null +++ b/Tools/NavigationQualification/README.md @@ -0,0 +1,8 @@ +# External Navigation consumer + +This separate SwiftPM package resolves JSONNavigation through its real library product, +using the exact source checkout as a path dependency. Run `swift run --package-path +Tools/NavigationQualification NavigationConsumer` and repeat with `-c release`. +The executable checks 18 named exact path/value/coverage/resource outcomes. The +repository compiler lane also checks import/package/cursor isolation and executes +the three public DocC guide examples. No package-scoped meter is imported here. From 5cf78972b279f398894dd4afcbc09dd058889371 Mon Sep 17 00:00:00 2001 From: Thorsten Fuchs <76904008+ThorFuchs@users.noreply.github.com> Date: Thu, 15 Oct 2026 22:40:15 +0200 Subject: [PATCH 2/2] Document N1 promotion boundary and separate blocked N2 gate --- CHANGELOG.md | 9 +++++++++ Documentation/Architecture/Linux.md | 8 ++++++++ .../StructuralIntelligence/API-DECISIONS.md | 6 ++++++ .../StructuralIntelligence/N1Promotion.md | 7 +++++++ .../PromotionProgress.json | 17 +++++++++++++++++ Documentation/Architecture/WebAssembly.md | 9 +++++++++ Documentation/DocumentationTooling.md | 1 + Sources/JSONCLIEngine/CLIBuildIdentity.swift | 2 +- .../Documentation.docc/Traversal.md | 2 +- 9 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 Documentation/Architecture/StructuralIntelligence/PromotionProgress.json diff --git a/CHANGELOG.md b/CHANGELOG.md index ed17dc6..12b9cd6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -170,3 +170,12 @@ remain unselected; projection and RFC 7464 framing remain deferred. timing sleeps; retain an invocation-local package-only checkpoint observer. - Qualify twenty frozen explicitly rooted downstream schema vectors and public cumulative budgets in a separate consumer; no protocol/runtime dependency added. + +## Unreleased Navigation candidate + +- Propose opt-in JSONNavigation as an eighth SwiftPM product, preserving its56 + exact traversal declarations and cumulative resource semantics. +- Qualify a real external Debug/Release SwiftPM consumer and preserve source-first + error precedence with two explicit regressions. +- N2 inspection remains unimplemented: its separate borrowed-context compiler + proof is blocked. No version/tag/release or automatic merge is implied. diff --git a/Documentation/Architecture/Linux.md b/Documentation/Architecture/Linux.md index dd787ab..7948ead 100644 --- a/Documentation/Architecture/Linux.md +++ b/Documentation/Architecture/Linux.md @@ -1,3 +1,11 @@ +# N1 candidate platform scope + +This additive candidate proposes JSONNavigation as an eighth product (seven +libraries plus CLI), with no external dependencies. Its public SwiftPM consumer +and39 Navigation functions join the unchanged Linux lanes. Both actual ARM64 and +x86_64 full/safety receipts are required for final qualification. The historical +platform text below describes the original seven-product implementation. + # Linux platform contract The six libraries and swift-json executable are qualified for 64-bit diff --git a/Documentation/Architecture/StructuralIntelligence/API-DECISIONS.md b/Documentation/Architecture/StructuralIntelligence/API-DECISIONS.md index ade93f7..9632899 100644 --- a/Documentation/Architecture/StructuralIntelligence/API-DECISIONS.md +++ b/Documentation/Architecture/StructuralIntelligence/API-DECISIONS.md @@ -1,3 +1,9 @@ +# Historical N0/N1 decision record + +This records the experimental4403b9a anchor. The current public-product candidate +is described in [N1Promotion.md](N1Promotion.md); the original decisions below +retain their historical source context. + # N1 exact traversal decisions Scope is N0/N1 only. JSONNavigation depends exclusively on JSON and currently has diff --git a/Documentation/Architecture/StructuralIntelligence/N1Promotion.md b/Documentation/Architecture/StructuralIntelligence/N1Promotion.md index 850057c..1ca40fe 100644 --- a/Documentation/Architecture/StructuralIntelligence/N1Promotion.md +++ b/Documentation/Architecture/StructuralIntelligence/N1Promotion.md @@ -23,3 +23,10 @@ lanes and Git-free reproduction must qualify the final source before recommendin release readiness. Actual outcomes accompany the return; this document is an API review decision, not a claim that unfinished qualification has passed. Draft #34 and the immutable N1 anchor remain untouched. No PR-ready/merge/release transition. + +A0 is independently blocked in the separate e11f93f borrowing spike: Apple Swift6.4 +accepts an escaping borrowed capture at type checking and aborts in SILGenCleanup +during full compilation. A compiler crash is not a valid negative proof. No borrowed +context or JSONInspection code is included in this product candidate. Its executor +is byte-identical to the reviewed N1 anchor. The return preserves exact reproducer +commands, positive/runtime results and failed diagnostic outcomes. diff --git a/Documentation/Architecture/StructuralIntelligence/PromotionProgress.json b/Documentation/Architecture/StructuralIntelligence/PromotionProgress.json new file mode 100644 index 0000000..1faea89 --- /dev/null +++ b/Documentation/Architecture/StructuralIntelligence/PromotionProgress.json @@ -0,0 +1,17 @@ +{ + "parent": "4403b9ab3b0a1fadc57c12a283cfabb255f6237a", + "initial_product_commit": "7ee2712", + "P1": "56 public declarations preserved; real external SwiftPM Debug/Release18 checks/config,39 regression functions/config passed; full final-source qualification required", + "A0": "separate e11f93f spike: runtime46/config pass; Apple Swift6.4 escape compiler crashes at full code generation; gate BLOCKED", + "A1": "not started per stop condition; JSONInspection target/product absent", + "public_products": 8, + "new_product": "JSONNavigation", + "human_gates": [ + "PR-ready transition", + "merge", + "tag", + "version release", + "publication" + ], + "evidence": "source-bound actual final outcomes accompany the private return; no old250MB bundle reconstructed" +} diff --git a/Documentation/Architecture/WebAssembly.md b/Documentation/Architecture/WebAssembly.md index 5ace53a..c7850af 100644 --- a/Documentation/Architecture/WebAssembly.md +++ b/Documentation/Architecture/WebAssembly.md @@ -1,3 +1,12 @@ +# N1 candidate WASI scope + +The opt-in JSONNavigation product candidate keeps the same full-language Swift6.4 +wasm32-unknown-wasip1 scope and empty dependency graph. Exact discovery is481 +functions/288 parameters, including39 Navigation functions, with all49 core cap +outcomes and existing independent policies. CLI runtime remains a separate scope. +Actual source-bound execution receipts are required; the historical stage counts +below are preserved, not attributed to this candidate. + # WASI command support This additive local branch supports the full-language Swift 6.4 SDK target diff --git a/Documentation/DocumentationTooling.md b/Documentation/DocumentationTooling.md index c3194fb..393047b 100644 --- a/Documentation/DocumentationTooling.md +++ b/Documentation/DocumentationTooling.md @@ -30,6 +30,7 @@ symbols, missing comments, stale examples or a failed catalog fail the lane. | `.build/handoff/docc/JSONHTML.doccarchive` | Exact formatted HTML API and rendering guide | | `.build/handoff/docc/JSONPatch.doccarchive` | Patch API and choosing/applying patches guide | | `.build/handoff/docc/JSONBridges.doccarchive` | Opt-in native numeric conversion and fidelity guide | +| `.build/handoff/docc/JSONNavigation.doccarchive` | Opt-in exact structural traversal and coverage | | `.build/handoff/docc/symbols/` | Public compiler symbol graphs grouped by product | | `.build/handoff/docc/coverage.json` | Counts and documentation-coverage failures | | `.build/handoff/docc/receipt.json` | Commands, toolchain, counts, exits and diagnostics | diff --git a/Sources/JSONCLIEngine/CLIBuildIdentity.swift b/Sources/JSONCLIEngine/CLIBuildIdentity.swift index 83f03af..b4bdb9e 100644 --- a/Sources/JSONCLIEngine/CLIBuildIdentity.swift +++ b/Sources/JSONCLIEngine/CLIBuildIdentity.swift @@ -2,6 +2,6 @@ // Generated by Scripts/generate_cli_identity.py; excludes this file. // SHA-256 of the ordered Package.swift + Sources content manifest, not a Git commit. package enum CLIBuildIdentity { - package static let revision = "sha256:fa1d5c9ebb416f5f82a2886d1ea3d1bdb48bf6fa3b9a3c34769eb82a3c81900f" + package static let revision = "sha256:30b51d51faa74e37b1359b9466fc1fd47a148a09dd08a996da5d93b90fb072f9" package static let kind = "source-sha256" } diff --git a/Sources/JSONNavigation/Documentation.docc/Traversal.md b/Sources/JSONNavigation/Documentation.docc/Traversal.md index 5f01f24..e627a8d 100644 --- a/Sources/JSONNavigation/Documentation.docc/Traversal.md +++ b/Sources/JSONNavigation/Documentation.docc/Traversal.md @@ -79,4 +79,4 @@ Full captured-source admission precedes validation of depth and collection optio An oversized source may therefore refuse admission before a negative option is reported. A valid small source with a negative option throws invalidLimits. The real external SwiftPM consumer resolves the JSONNavigation product in Debug -and Release; package scopes/meters and the owned context remain inaccessible. +and Release; package scopes and meters remain inaccessible.