diff --git a/AGENTS.md b/AGENTS.md index 03c4ab6..63617e4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -4,9 +4,10 @@ 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 six public products: JSON, JSONSchema, JSONStreaming, JSONPatch, JSONHTML and JSONBridges. - JSONHTML depends on JSON only; the maintainer-approved 1.3 addition preserves historical four-product releases. - The E2-approved opt-in JSONBridges depends on JSON only and is never re-exported by core. +- Keep seven public products: JSON, JSONSchema, JSONStreaming, JSONPatch, JSONHTML, + JSONBridges 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. 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/ExtractionManifest.json b/Documentation/Architecture/ExtractionManifest.json index 735d569..66bf9f6 100644 --- a/Documentation/Architecture/ExtractionManifest.json +++ b/Documentation/Architecture/ExtractionManifest.json @@ -196,7 +196,8 @@ "Schema graph, explicit evaluator, exact sets/assertions and scalar format recognizers are original implementations from Draft 2020-12, RFC3986/3987/3339/3492/5321/5891/5892/5893/6531/6570/6901 and fixed Unicode13 data.", "Private FIPS 180-4 SHA-256 is an original Swift implementation with checked cumulative production accounting, bounded scratch and inner cancellation. The separate trusted fixture tool mirrors its primitive core byte-for-byte; public_check verifies parity. No CryptoKit fallback or runtime dependency is introduced.", "JSONHTML formatted rendering, original fixed CSS and shared strict-writer token classification are original Apache-2.0 code. No third-party renderer, browser numeric authority or runtime dependency is adapted.", - "JSONHTML typed annotations, iterative exact-path binding, static/interactive attachment and coherent JSONDocument span presentation are original Apache-2.0 code. No schema engine, third-party renderer, source archive or new dependency is adapted." + "JSONHTML typed annotations, iterative exact-path binding, static/interactive attachment and coherent JSONDocument span presentation are original Apache-2.0 code. No schema engine, third-party renderer, source archive or new dependency is adapted.", + "CLI foundation, argv parser, POSIX adapters, prepaid bounded diagnostics and shared-meter package adapters are original Apache-2.0 Swift code. No legacy filter engine or jq source is copied. See Release1.4/Foundation.md for native test-harness reuse provenance." ], "policy": "Record actual adaptations and retain applicable upstream copyrights and licenses. Reference inputs and comparison experiments are not distributed runtime dependencies.", "jsonhtml_export_original_contributions": { diff --git a/Documentation/Architecture/Release1.4/Acceptance.json b/Documentation/Architecture/Release1.4/Acceptance.json new file mode 100644 index 0000000..e0743ac --- /dev/null +++ b/Documentation/Architecture/Release1.4/Acceptance.json @@ -0,0 +1,1191 @@ +{ + "schema": "swift-json-cli-acceptance/1", + "prepared": "2026-10-14", + "implementation_status": "foundation boundary only; integration unqualified", + "requirements": [ + { + "id": "CL001", + "gate": "C0", + "title": "Live source/prerequisite reconciliation", + "verification": "Record actual main/base/HTML/provider heads and compare pins; preserve active work and dirty state.", + "obligation": "mandatory", + "status": "passed", + "evidence_required": true, + "fixture_ids": [], + "evidence": [ + "Documentation/Architecture/Release1.4/Qualification.md" + ] + }, + { + "id": "CL002", + "gate": "C0", + "title": "Seven public products with correct kinds after E2 reconciliation", + "verification": "Package dump contains six libraries, including merged opt-in JSONBridges, plus swift-json executable; private targets have no products.", + "obligation": "mandatory", + "status": "passed", + "evidence_required": true, + "fixture_ids": [], + "evidence": [ + "Documentation/Architecture/Release1.4/Qualification.md" + ], + "historical_six_product_contract": { + "title": "Six public products with correct kinds", + "verification": "Package dump contains five libraries plus swift-json executable; private targets have no products." + } + }, + { + "id": "CL003", + "gate": "C0", + "title": "Empty root dependency set", + "verification": "Dump/package resolution and clean-source build prove no external dependency was introduced.", + "obligation": "mandatory", + "status": "partial", + "evidence_required": true, + "fixture_ids": [], + "evidence": [ + "Documentation/Architecture/Release1.4/Qualification.md" + ] + }, + { + "id": "CL004", + "gate": "C0", + "title": "Dependency direction and mobile consumers", + "verification": "Selected library consumers have no CLI/filter dependencies; core has no HTML/provider/UI imports.", + "obligation": "mandatory", + "status": "partial", + "evidence_required": true, + "fixture_ids": [], + "evidence": [ + "Documentation/Architecture/Release1.4/Qualification.md" + ] + }, + { + "id": "CL005", + "gate": "C0", + "title": "Forward policy and historical records", + "verification": "Update AGENTS/README/CI prospective inventory; historical releases remain accurate.", + "obligation": "mandatory", + "status": "passed", + "evidence_required": true, + "fixture_ids": [], + "evidence": [ + "Documentation/Architecture/Release1.4/Qualification.md" + ] + }, + { + "id": "CL006", + "gate": "C0", + "title": "Private compiler/IR ownership", + "verification": "Compiler probes prove immutable checked-Sendable plans and invocation-owned noncopyable context.", + "obligation": "mandatory", + "status": "partial", + "evidence_required": true, + "fixture_ids": [], + "evidence": [ + "Documentation/Architecture/Release1.4/Qualification.md" + ] + }, + { + "id": "CL007", + "gate": "C0", + "title": "Attribution and extraction manifest", + "verification": "Every actual adaptation has pinned origin/status/notices; inherited files retain identity.", + "obligation": "mandatory", + "status": "passed", + "evidence_required": true, + "fixture_ids": [], + "evidence": [ + "Documentation/Architecture/Release1.4/Qualification.md" + ] + }, + { + "id": "CL008", + "gate": "C0", + "title": "Prior brief conflict resolution", + "verification": "Record reused HTML/tab/provider APIs and authoritative amendments; no duplicate conformance or restarted portability.", + "obligation": "mandatory", + "status": "passed", + "evidence_required": true, + "fixture_ids": [], + "evidence": [ + "Documentation/Architecture/Release1.4/Qualification.md" + ] + }, + { + "id": "CL009", + "gate": "C1", + "title": "Argv parsing and limits", + "verification": "Exercise long equals, grouped Boolean flags, leading-dash filenames, --, duplicates, unknown/conflicting options and bounded args.", + "obligation": "mandatory", + "status": "partial", + "evidence_required": true, + "fixture_ids": [ + "unknown-option" + ], + "evidence": [ + "Documentation/Architecture/Release1.4/Qualification.md" + ] + }, + { + "id": "CL010", + "gate": "C1", + "title": "Truthful help/version", + "verification": "Only available qualified commands appear; missing command/config/capability is 2; help/version is 0.", + "obligation": "mandatory", + "status": "partial", + "evidence_required": true, + "fixture_ids": [], + "evidence": [ + "Documentation/Architecture/Release1.4/Qualification.md" + ] + }, + { + "id": "CL011", + "gate": "C1", + "title": "Strict native format", + "verification": "Single root, full EOF, native UTF-8/duplicate-key grammar, exact lexemes and default two-space formatting.", + "obligation": "mandatory", + "status": "passed", + "evidence_required": true, + "fixture_ids": [ + "format-preserved-lexemes", + "reject-duplicate-key", + "reject-trailing-root", + "reject-trailing-comma" + ], + "evidence": [ + "Documentation/Architecture/Release1.4/Qualification.md" + ] + }, + { + "id": "CL012", + "gate": "C1", + "title": "Explicit presentation options", + "verification": "Compact/indent/tab/sort/number-style options preserve library defaults and scalar key order.", + "obligation": "mandatory", + "status": "passed", + "evidence_required": true, + "fixture_ids": [ + "conflicting-style-options" + ], + "evidence": [ + "Documentation/Architecture/Release1.4/Qualification.md" + ] + }, + { + "id": "CL013", + "gate": "C1", + "title": "Syntax validation outcomes", + "verification": "Completed valid/invalid result and issues; malformed input 5, resource 6, IO 7 are separate.", + "obligation": "mandatory", + "status": "passed", + "evidence_required": true, + "fixture_ids": [], + "evidence": [ + "Documentation/Architecture/Release1.4/Qualification.md" + ] + }, + { + "id": "CL014", + "gate": "C1", + "title": "Offline schema validation", + "verification": "Compile once per job; explicit immutable resources; instance invalid 1; no fetch/default insertion.", + "obligation": "mandatory", + "status": "partial", + "evidence_required": true, + "fixture_ids": [ + "validate-instance-invalid" + ], + "evidence": [ + "Documentation/Architecture/Release1.4/Qualification.md" + ] + }, + { + "id": "CL015", + "gate": "C1", + "title": "Pointer presence", + "verification": "Present null versus missing, escaped tokens, root pointer, allow-missing exit4 and type/domain errors.", + "obligation": "mandatory", + "status": "passed", + "evidence_required": true, + "fixture_ids": [ + "pointer-present-null", + "pointer-missing-allowed", + "pointer-escaped-key" + ], + "evidence": [ + "Documentation/Architecture/Release1.4/Qualification.md" + ] + }, + { + "id": "CL016", + "gate": "C1", + "title": "Patch transactional candidate", + "verification": "Successful operations emit full result; failed test/path never emits staged mutation or changes source.", + "obligation": "mandatory", + "status": "passed", + "evidence_required": true, + "fixture_ids": [ + "patch-success", + "patch-failed-test" + ], + "evidence": [ + "Documentation/Architecture/Release1.4/Qualification.md" + ] + }, + { + "id": "CL017", + "gate": "C1", + "title": "Incremental local IO", + "verification": "Owned chunk reads, explicit closure, split UTF-8 and partial/no-progress writes; no read-to-end job arrays.", + "obligation": "mandatory", + "status": "partial", + "evidence_required": true, + "fixture_ids": [], + "evidence": [ + "Documentation/Architecture/Release1.4/Qualification.md" + ] + }, + { + "id": "CL018", + "gate": "C1", + "title": "Stdout/stderr separation", + "verification": "All data is clean; JSON diagnostics/reports are tagged stderr lines with no ANSI/banner.", + "obligation": "mandatory", + "status": "passed", + "evidence_required": true, + "fixture_ids": [], + "evidence": [ + "Documentation/Architecture/Release1.4/Qualification.md" + ] + }, + { + "id": "CL019", + "gate": "C1", + "title": "Shared compound accounting", + "verification": "Nested parse/validate/patch/write and multiple records cannot reset work or retained overlap; failure latches.", + "obligation": "mandatory", + "status": "partial", + "evidence_required": true, + "fixture_ids": [], + "evidence": [ + "Documentation/Architecture/Release1.4/Qualification.md" + ] + }, + { + "id": "CL020", + "gate": "C1", + "title": "Every CLI cap boundary", + "verification": "Inclusive-cap and cap+1 sweeps for all 16 CLI caps; checked counters and conversion overflow.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [] + }, + { + "id": "CL021", + "gate": "C1", + "title": "Existing native limits preserved", + "verification": "49 metric inventory/meaning and existing independent boundary tests remain intact.", + "obligation": "mandatory", + "status": "passed", + "evidence_required": true, + "fixture_ids": [], + "evidence": [ + "Documentation/Architecture/Release1.4/Qualification.md" + ] + }, + { + "id": "CL022", + "gate": "C1", + "title": "Actual in-loop cancellation", + "verification": "Checkpoint rendezvous inside long owned work and source/sink suspend; no further output after terminal failure.", + "obligation": "mandatory", + "status": "partial", + "evidence_required": true, + "fixture_ids": [], + "evidence": [ + "Documentation/Architecture/Release1.4/Qualification.md" + ] + }, + { + "id": "CL023", + "gate": "C1", + "title": "Atomic file success", + "verification": "Owned same-directory stage installed only after EOF/flush/close; report committed completion.", + "obligation": "mandatory", + "status": "passed", + "evidence_required": true, + "fixture_ids": [], + "evidence": [ + "Documentation/Architecture/Release1.4/Qualification.md" + ] + }, + { + "id": "CL024", + "gate": "C1", + "title": "Atomic file failure", + "verification": "Late invalid tail/resource/cancel/IO preserves destination and removes only owned stage.", + "obligation": "mandatory", + "status": "passed", + "evidence_required": true, + "fixture_ids": [], + "evidence": [ + "Documentation/Architecture/Release1.4/Qualification.md" + ] + }, + { + "id": "CL025", + "gate": "C1", + "title": "Overwrite/path policy", + "verification": "Existing file requires --overwrite; input/output alias and output symlink reject; no silent cross-FS fallback.", + "obligation": "mandatory", + "status": "passed", + "evidence_required": true, + "fixture_ids": [], + "evidence": [ + "Documentation/Architecture/Release1.4/Qualification.md" + ] + }, + { + "id": "CL026", + "gate": "C1", + "title": "Exit precedence", + "verification": "Codes0/1/2/3/4/5/6/7/130 and completed-result precedence verified in actual subprocesses.", + "obligation": "mandatory", + "status": "partial", + "evidence_required": true, + "fixture_ids": [], + "evidence": [ + "Documentation/Architecture/Release1.4/Qualification.md" + ] + }, + { + "id": "CL027", + "gate": "C2", + "title": "Native query lexer/literals", + "verification": "Exact numbers and scalar text/keys with source byte ranges; malformed source compiles to exit3.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [] + }, + { + "id": "CL028", + "gate": "C2", + "title": "Grammar precedence", + "verification": "Pipeline/comma/default/assignment/operator precedence and delimiters tested beyond old parser goldens.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "pipeline-comma-precedence" + ] + }, + { + "id": "CL029", + "gate": "C2", + "title": "Pull VM cardinality", + "verification": "Empty/one/many outputs without whole-job array; next() demand limits observable reads/retention.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [] + }, + { + "id": "CL030", + "gate": "C2", + "title": "Pipeline and comma order", + "verification": "Every upstream result is evaluated and ordered; late errors do not resume a failed branch.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [] + }, + { + "id": "CL031", + "gate": "C2", + "title": "Cartesian operators/constructors", + "verification": "No .first collapse; object versus arithmetic nesting orders and shared input effects are tested.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "object-product-order" + ] + }, + { + "id": "CL032", + "gate": "C2", + "title": "Navigation and wrong-type", + "verification": "Missing/null convention, has, wrong-type error, optional catch and checked indices/slices.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "missing-field-null", + "wrong-type-field", + "optional-wrong-type-empty", + "has-present-null", + "negative-index" + ] + }, + { + "id": "CL033", + "gate": "C2", + "title": "Exact Unicode identity", + "verification": "Scalar-distinct strings/keys, scalar length/slicing/order and non-BMP behavior.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "scalar-key-lookup", + "scalar-string-inequality", + "scalar-length", + "utf8-length", + "scalar-slice" + ] + }, + { + "id": "CL034", + "gate": "C2", + "title": "Truth/default/Boolean generators", + "verification": "Only false/null falsey; // handles full streams; left-driven short-circuit and if generators.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "truthiness", + "fallback-whole-generator", + "fallback-empty", + "Boolean-short-circuit", + "if-condition-stream" + ] + }, + { + "id": "CL035", + "gate": "C2", + "title": "Constructed duplicate keys", + "verification": "Explicit replace-preserve-position policy; parsed exact duplicate keys still reject.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "constructed-key-replacement" + ] + }, + { + "id": "CL036", + "gate": "C2", + "title": "Exact comparison/order", + "verification": "Metered decimal/string/array/object equality and total order with stable ties.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [] + }, + { + "id": "CL037", + "gate": "C2", + "title": "Common builtin inventory", + "verification": "All C2 builtins and type/domain/empty cases; map collects and map_values updates/deletes correctly.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "empty-array-collector", + "map-all-results", + "map-values-first", + "map-values-delete", + "normals-nonzero-native" + ] + }, + { + "id": "CL038", + "gate": "C2", + "title": "Lexical bindings/arguments", + "verification": "as, --arg/argjson/rawfile/slurpfile, $ARGS, duplicate/reserved names, strict auxiliary-file admission.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "binding-original-input", + "argjson-exact" + ] + }, + { + "id": "CL039", + "gate": "C2", + "title": "Shared input cursor", + "verification": "Driver/input/inputs share consumption; EOF catchable only for input; malformed tails/IO remain fatal.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "null-input-once", + "shared-inputs" + ] + }, + { + "id": "CL040", + "gate": "C2", + "title": "JSON/raw framing", + "verification": "values/document/NDJSON and strict raw UTF-8 lines/slurp; files have independent boundaries.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "values-framing", + "adjacent-roots-rejected", + "ndjson-blank-line-rejected", + "raw-line-crlf" + ] + }, + { + "id": "CL041", + "gate": "C2", + "title": "Raw output/NUL/join", + "verification": "Correct string bytes and nonstring JSON; embedded NUL rejected; delimiters/errors/counts tested.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "raw-lf", + "raw-nul-delimiter", + "raw-nul-value-rejected", + "join-no-delimiter" + ] + }, + { + "id": "CL042", + "gate": "C2", + "title": "ASCII output and sort keys", + "verification": "Owned escaping, surrogate pairs and exact scalar order; option conflicts tested.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "ascii-surrogate-pair" + ] + }, + { + "id": "CL043", + "gate": "C2", + "title": "Query exit-status", + "verification": "Final semantic value only after completion; truthy0/empty string/collections; false/null1 and noresult4.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "exit-status-truthy-zero", + "exit-status-false", + "exit-status-empty" + ] + }, + { + "id": "CL044", + "gate": "C2", + "title": "Plan reuse and isolation", + "verification": "Concurrent independent invocations share immutable plan only; mutable iterator not concurrently accessed.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [] + }, + { + "id": "CL045", + "gate": "C3", + "title": "Exact add/subtract/multiply", + "verification": "Carry/borrow/sign/zero/large integer cases against independent exact expectations.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "Cartesian-add-order", + "exact-large-integer", + "exact-decimal-add", + "exact-borrow", + "exact-multiply" + ] + }, + { + "id": "CL046", + "gate": "C3", + "title": "Numeric admission and lexemes", + "verification": "Computed values normalized with no false originalLexeme; untouched inputs preserve spelling.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [] + }, + { + "id": "CL047", + "gate": "C3", + "title": "Terminating exact division", + "verification": "Reduced denominators containing only2/5, large common factors and mixed signs.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "terminating-division" + ] + }, + { + "id": "CL048", + "gate": "C3", + "title": "Repeating division default", + "verification": "1/3 and repeating values give language inexactDivision; no floating fallback.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "repeating-division-error" + ] + }, + { + "id": "CL049", + "gate": "C3", + "title": "Explicit scale/half-even", + "verification": "Required option pair, decimal places, finite caps, signed ties and report rounding counts.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "rounded-third", + "half-even-ties", + "scale-pair-required" + ] + }, + { + "id": "CL050", + "gate": "C3", + "title": "Zero division and integral remainder", + "verification": "Typed catchable domain errors; signed truncated remainder; fractional remainder rejected.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "negative-remainder", + "fractional-remainder-rejected" + ] + }, + { + "id": "CL051", + "gate": "C3", + "title": "Exact numeric builtins", + "verification": "abs/floor/ceil/trunc/round/range/add with negative and empty/domain cases; round ties away from zero.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "round-away-from-zero", + "range-negative-step", + "range-zero-step" + ] + }, + { + "id": "CL052", + "gate": "C3", + "title": "Exponent/growth preflight", + "verification": "Large sparse exponent operations fail finite caps before dense allocation; exact zero shortcut allowed.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "exponent-gap-cap" + ] + }, + { + "id": "CL053", + "gate": "C3", + "title": "Numeric work and cancellation", + "verification": "Charged GCD/division/carry inner loops; boundaries and checkpoint cancellation; terminal errors not catchable.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [] + }, + { + "id": "CL054", + "gate": "C3", + "title": "32-bit arithmetic safety", + "verification": "No Int/UInt64 negation/narrowing/product overflow traps; wasm32 kernel tests or explicit gate blocker.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [] + }, + { + "id": "CL055", + "gate": "C3", + "title": "No Decimal/Double authority", + "verification": "Source audit plus precision cases prove no foreign arithmetic/fallback authority.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [] + }, + { + "id": "CL056", + "gate": "C4", + "title": "Reduce/foreach streams", + "verification": "Last-update state, every foreach extraction, multiple inits, empty updates and actual evaluation order.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "reduce-last-update", + "reduce-empty-update", + "foreach-every-update", + "reduce-multiple-inits" + ] + }, + { + "id": "CL057", + "gate": "C4", + "title": "Lexical filter functions", + "verification": "Filter/value parameters, arity/scopes, self-recursion, no forward refs and finite explicit frames.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "filter-parameter-code", + "forward-definition-rejected", + "recursive-definition" + ] + }, + { + "id": "CL058", + "gate": "C4", + "title": "Loops/recurse/walk", + "verification": "Correct order/null handling/parent-after-child behavior with bounded frames/work and no fixed hidden10k cap.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "walk-child-before-parent", + "recurse-null-leaves" + ] + }, + { + "id": "CL059", + "gate": "C4", + "title": "Typed try/catch/optional", + "verification": "Catch only language errors; prior yields/handler streams correct; syntax/resource/cancel/IO never suppressed.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "input-eof-catch", + "malformed-input-cannot-catch", + "repeating-division-caught", + "division-zero-caught", + "try-prior-yield" + ] + }, + { + "id": "CL060", + "gate": "C4", + "title": "Collection builtin inventory", + "verification": "sort/group/unique/min/max/by forms, stable ties, multi-key generator lists, finite materialization.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "sort-exact-integers", + "total-order", + "group-scalar-distinct" + ] + }, + { + "id": "CL061", + "gate": "C4", + "title": "Generator first/last/nth", + "verification": "Correct pull/empty behavior and completion of remaining input; no hidden job early success.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "first-generator" + ] + }, + { + "id": "CL062", + "gate": "C4", + "title": "Flatten/any/all", + "verification": "Depth bounds, empty identities, short circuit and explicit deep traversal.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "all-any-empty" + ] + }, + { + "id": "CL063", + "gate": "C4", + "title": "Literal string helpers", + "verification": "Scalar contains/search/split/join/ASCII trim/case; empty patterns/type errors and bounded scan.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "split-empty-scalars", + "index-empty-pattern" + ] + }, + { + "id": "CL064", + "gate": "C4", + "title": "Conversions/explode/implode", + "verification": "Strict tonumber, preserved tostring, non-BMP scalar ints, invalid surrogate/range/type rejection.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "explode-non-BMP", + "implode-surrogate-rejected", + "tonumber-exact", + "tonumber-whitespace-rejected" + ] + }, + { + "id": "CL065", + "gate": "C4", + "title": "Path enumeration/admission", + "verification": "Exact segments, missing paths, generated paths, shape/domain restrictions and no Pointer conflation.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "setpath-created-array" + ] + }, + { + "id": "CL066", + "gate": "C4", + "title": "Assignment = versus |=", + "verification": "Original versus current-value RHS input; generator output, first update/empty delete semantics.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "assignment-set-generator", + "assignment-update-first", + "assignment-update-delete" + ] + }, + { + "id": "CL067", + "gate": "C4", + "title": "Transactional mutation/deletion", + "verification": "Stable array removals, deduplicated targets, overlap rejection and input unchanged on failure.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "assignment-overlap-rejected" + ] + }, + { + "id": "CL068", + "gate": "C4", + "title": "Sparse path growth", + "verification": "setpath container creation/null fill bounded before allocation and overflow.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "sparse-growth-fails" + ] + }, + { + "id": "CL069", + "gate": "C4", + "title": "String interpolation streams", + "verification": "Cartesian holes/literal identity/empty hole; formatter holes only with no eager unbounded strings.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "interpolation-generators", + "interpolation-empty" + ] + }, + { + "id": "CL070", + "gate": "C4", + "title": "Bounded format encoders", + "verification": "All C4 formatters, strict base64/UTF8, flat CSV/TSV, percent/HTML/POSIX quoting; no shell execution.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "format-html", + "format-base64" + ] + }, + { + "id": "CL071", + "gate": "C4", + "title": "Regex deferral", + "verification": "Compile-time unavailable diagnostics; no ICU/ECMA substitutions or compatibility claim.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "regex-not-advertised" + ] + }, + { + "id": "CL072", + "gate": "C4", + "title": "Other exclusions", + "verification": "Modules/seq/jq-stream/dates/env/halt/remote/server/converters rejected or absent from truthful help.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "numeric-transcendental-deferred", + "env-not-available" + ] + }, + { + "id": "CL073", + "gate": "C4", + "title": "Every inherited fixture disposition", + "verification": "119+49 originals retained, actual per-row status/reason/gate/claim, exclusions separated from successes.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [] + }, + { + "id": "CL074", + "gate": "C5", + "title": "Stream completion commands", + "verification": "Check/cat/root-array reader, strict line/tail behavior and completed summary exactly once.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "stream-root-array", + "stream-root-array-bad-tail" + ] + }, + { + "id": "CL075", + "gate": "C5", + "title": "Static HTML rendering", + "verification": "JSONHTML integration with no script, expanded nodes, exact values/keys, escaping and finite shared accounting.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "render-static-inert" + ] + }, + { + "id": "CL076", + "gate": "C5", + "title": "Interactive HTML rendering", + "verification": "Approved fixed CSS/JS self-contained document with inert payloads; no server or external assets.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [] + }, + { + "id": "CL077", + "gate": "C5", + "title": "Text/Markdown output", + "verification": "Tab pretty body, safe JSON fence and exact tokens; shared qualified writer options/defaults unchanged.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "render-markdown" + ] + }, + { + "id": "CL078", + "gate": "C5", + "title": "Offline schema/provider commands", + "verification": "Native schema check plus qualified local OpenAI helpers; schema object not quoted string, no network/key.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "schema-provider-object-envelope" + ] + }, + { + "id": "CL079", + "gate": "C5", + "title": "Provider incompatibility and availability", + "verification": "No constraint loss/lowering; compatibility false exit1; Apple signatures guarded and advertised only when qualified.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [ + "schema-provider-optionality-reject" + ] + }, + { + "id": "CL080", + "gate": "C5", + "title": "Native macOS executable qualification", + "verification": "Actual SDK27/Swift6.4 build/run/subprocess tests at final head.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [] + }, + { + "id": "CL081", + "gate": "C5", + "title": "Linux x86_64 executable qualification", + "verification": "Actual Ubuntu24.04 x86_64 runtime and Linux/linux-safety receipts; not crosscompile-only.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [] + }, + { + "id": "CL082", + "gate": "C5", + "title": "Linux ARM64 executable qualification", + "verification": "Actual Ubuntu24.04 ARM64 runtime and Linux/linux-safety receipts.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [] + }, + { + "id": "CL083", + "gate": "C5", + "title": "Mobile library compatibility", + "verification": "Selected-product iOS/iPadOS consumers and existing mobile qualification preserved; no CLI process support claim.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [] + }, + { + "id": "CL084", + "gate": "C5", + "title": "WASI CLI disposition", + "verification": "Explicit final supported/blocked/limited evidence with resources/argv/preopen/counters; no inherited CLI pass.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [] + }, + { + "id": "CL085", + "gate": "C5", + "title": "Baseline WASI/core preservation", + "verification": "Existing all-four-product resource/integrity/49metrics/platform lanes retain exact truthful evidence.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [] + }, + { + "id": "CL086", + "gate": "C5", + "title": "Installed resources/clean extraction", + "verification": "Source archive rebuilt, executable run outside repo cwd, sibling schema bundle and missing/tampered resource tests.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [] + }, + { + "id": "CL087", + "gate": "C5", + "title": "Fresh oracle and comparisons", + "verification": "Pinned jq1.8.2 build/hash; native exact comparison plus byte/exit modes; missing oracle blocks that lane.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [] + }, + { + "id": "CL088", + "gate": "C5", + "title": "Independent exact expectations", + "verification": "Integer/rational/Unicode/cardinality expectations separate from native self-comparison and jq floats.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [] + }, + { + "id": "CL089", + "gate": "C5", + "title": "Streaming retention/performance", + "verification": "Generated chunks/slow sink/large record counts and bounded collectors; release-mode identities/variance, no blanket speedup.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [] + }, + { + "id": "CL090", + "gate": "C5", + "title": "Combined E2/CLI product CI and documentation", + "verification": "Existing native/safety/docs plus affected Linux lanes, exact product kinds and public CLI help/docs/examples.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [] + }, + { + "id": "CL091", + "gate": "C5", + "title": "Final-head review/return evidence", + "verification": "Actual PR/base/head topology, nonzero counts, immutable IDs/log hashes/fixture results, blockers and release recommendation.", + "obligation": "mandatory", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [] + }, + { + "id": "CL092", + "gate": "C5", + "title": "Optional parallel evaluator", + "verification": "Only independent record filters; reserved bounded tasks/reorder buffers, preserved order/errors and measured material gain.", + "obligation": "optional-extension", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [] + }, + { + "id": "CL093", + "gate": "C5", + "title": "Optional Apple PDF/RTF CLI export", + "verification": "Only after existing export backend qualification; actual host, explicit async preparation/page capabilities and unsupported-host errors.", + "obligation": "optional-extension", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [] + }, + { + "id": "CL094", + "gate": "C5", + "title": "Optional native binary distribution", + "verification": "Explicit packaging policy, architecture/resource/signature receipts; no publication/tag performed by this task.", + "obligation": "optional-extension", + "status": "not_run", + "evidence_required": true, + "fixture_ids": [] + } + ], + "notes": [ + "Package integrity is separate from native qualification.", + "Optional extensions do not block the scoped candidate when not claimed.", + "WASI CLI supported/blocked/limited disposition is mandatory; full CLI support is separately earned.", + "Main e8c3e4b added the approved JSONBridges product before CLI merge. Current integration preserves six libraries plus the CLI; original briefing/product evidence remains historical." + ] +} diff --git a/Documentation/Architecture/Release1.4/Foundation.md b/Documentation/Architecture/Release1.4/Foundation.md new file mode 100644 index 0000000..9d5f7ac --- /dev/null +++ b/Documentation/Architecture/Release1.4/Foundation.md @@ -0,0 +1,103 @@ +# CLI foundation + +This feature boundary implements format, strict validation, RFC 6901 selection, +staged RFC 6902 application and HTML/text/Markdown rendering. It does not advertise +the query engine, stream/schema command adapters or provider helpers before their +own increments are qualified. The target release is 1.4.0; this is development source. + +## Composition and ownership + +`CLIJobContext: ~Copyable` lives in the private runtime target. Argv, native parsing, +number projection, registry/plan admission, validation, Patch, rendering and writing +borrow its one `JSONWorkMeter`. Package-only borrowed entry points introduce no new +public library signatures. Switching the operation domain changes subsystem work +accounting without replacing health or counters. Only per-value shape capacities +reset; consumed work never resets. Patch refunds its local staging reservation and +preserves ownership that preceded its invocation. + +CLI policy has 16 additional finite quotas. Core policy keeps exactly 49 metric +identifiers. Effective work and logical-retention ceilings are the intersection of +CLI and core ceilings. Configuration bootstraps under the finite offline profile, +then validates requested caps against already consumed work and admitted capacities. +Explicit finite overrides reuse the ledger. They cannot erase bootstrap input. + +Error/cancellation latches terminal health. Data paths cannot resume after failure. +Diagnostics reserve finite work and buffer ownership before command execution; +the bounded terminal serializer spends that reservation and cannot reopen the job. +Reports distinguish provisional results from fully accepted stdout results and +atomically installed file results. Logical retained bytes are not process RSS. + +## Native I/O + +The adapters poll nonblocking POSIX descriptors, check cancellation between polls, +and handle short reads/writes, EINTR, EAGAIN, EOF and broken pipes explicitly. +Filesystem/kernel work is foreign work; cancellation does not claim to interrupt +a filesystem operation already executing in the kernel. Borrowed stdio flags are +restored. The signal callback is explicitly `@Sendable`; a real subprocess test +caught and fixed an inferred-actor dispatch assertion on SIGINT. + +File output uses an exclusive owned temporary in the destination directory. +Installation happens after parsing, command evaluation, writing and close succeed. +No-overwrite installation uses link/unlink; explicit overwrite uses rename. +Existing destinations, final symlinks and input aliases/hard links are checked. +Failures remove only the invocation's temporary and preserve the destination. +Concurrent pathname replacement by another process is outside this adapter's +transactional guarantee. There is no cross-filesystem fallback, mkdir, fsync or +power-loss durability claim. Previously accepted stdout bytes cannot be recalled. + +## Checks + +Twelve meaningful Swift Testing functions include four parameter cases. The executable +subprocess harness has 53 cases covering exact lexemes/scalar keys, strict errors, +schema invalidity versus operational failure, bounded issues, Pointer null/absence, +root removal, failed Patch staging, renderer selection, limits/reports, filesystem +aliases, atomic cleanup and SIGINT while stdin is idle. The initial failure receipts +are retained; the corrected subprocess lane passes all 53. + +The event receipt reader is reused from the separately qualified 1.3 export work +at `1e0b86d2580bb9678039597523aa3b99d2905abf`. No export/PDF feature source is copied. +The six-product checks retain exact target/dependency/toolchain/platform assertions, +all baseline test bundle counts, 173 inherited parameter cases plus four CLI cases, +and all 49 cap probe outcomes. Native/safety/docs qualification remains required +for the committed source. + +## Compiler probes and review corrections + +The supported native compiler accepts an inout job borrow, rejects consuming the +same job twice with the expected ownership diagnostic, and rejects access from an +external package. The noncopyable initializer constructs its meter before the +other stored assignments; this follows actual Swift 6.4 initialization rules. +An initial default-CLT/cache attempt is unqualified and retained as blocked evidence; +its negative exits are not ownership passes. + +Strict memory-safety compilation marks individual synchronous POSIX pointer and +CString expressions `unsafe`. Byte pointers stay within `withUnsafeBytes` scopes; +counts are checked against the array slice, poll/stat pointers address live local +structures, and C strings are borrowed only for a synchronous syscall. No pointer +escapes, suspension crosses a borrow, unsafe compiler option or blanket annotation +is introduced. + +The SIGINT acceptance test waits for its exclusive staging file as a readiness +signal and holds stdin open until exit. Closing stdin through `communicate()` +immediately after SIGINT introduced a competing EOF and was corrected. The test +still requires exit 130, no output, and complete staging cleanup. + +The final argument adapter reads process-owned C argv under the finite bootstrap +ledger, rejects invalid UTF-8 instead of accepting replacement characters, and +checks each byte before copying. Structured diagnostic preferences survive usage +errors. Malformed/overflowing limit configuration is usage failure; exhaustion, +cancellation and I/O remain operational. Missing array Pointer targets use a +package-only presence adapter over the shared strict index decoder; malformed +indices and wrong kinds stay errors. Existing public Pointer resolution retains +its previous error contract. These review findings have dedicated regressions. + +Named inputs open with O_NONBLOCK from the initial syscall, so FIFO open does not +wait indefinitely before cancellation handling begins. Subprocess cancellation +covers both idle borrowed stdin and an owned named FIFO. Reports include actual +enforced native caps, remaining cumulative work and profile/override origin. + +The terminal diagnostic builder checks each append before growth and discards an +incomplete report before handoff. Zero forbids diagnostic output; small diagnostic +quotas cannot produce broken JSONL. HTML-specific quotas map to resource exit 6; +renderer configuration maps to usage exit 2. Typed schema compile/evaluation errors +stay operational exit 5, with stable subsystem codes. These have explicit regressions. diff --git a/Documentation/Architecture/Release1.4/Plan.md b/Documentation/Architecture/Release1.4/Plan.md new file mode 100644 index 0000000..0beabd8 --- /dev/null +++ b/Documentation/Architecture/Release1.4/Plan.md @@ -0,0 +1,42 @@ +# CLI release plan + +The maintainer-approved 1.4.0 train adds `swift-json` as an executable beside the +six libraries, including the independently merged opt-in JSONBridges. JSONFilterRuntime and JSONCLIEngine are package-private targets; +JSONRegexRuntime remains private. Root external dependencies remain empty. +Historical four/five-product releases and their evidence are unchanged. + +The CLI stack starts at the qualified JSONHTML renderer commit +`3c1e8a1a1bc8d03699665b8ab98f5ece7962aff7`, PR #21. Its native, safety, docs and +Linux x86_64/arm64 lanes passed. Main at orientation was +`25fb04f747e583209b4c4511abf39e11ef5b4f80`. This train uses dependent feature +branches and draft PRs; it does not change the parallel transfer/PDF or 1.2 work. + +| Gate | Cohesive implementation and acceptance | +| --- | --- | +| C0 | Source/protection/prerequisite audit, executable/private target shapes, one noncopyable job ledger | +| C1 | Bounded argv/stdio/files, diagnostics/exits, atomic output, format/validate/Pointer/Patch, seven-product inventory | +| C2 | Original flat filter IR and pull VM, input framing, generators/paths/control/bindings/common builtins | +| C3 | Private exact decimal arithmetic; explicit scale plus half-even division policy | +| C4 | Qualified richer filters, lexical functions/reductions/path updates; explicit unsupported features | +| C5 | Qualified renderer/schema/provider adapters, consumers, independent corpus/oracle, platform/distribution and final candidate | + +The planned stack is foundation, query-core, arithmetic, richer filters and +integration. Each has a compiling boundary, exact acceptance receipts and a draft +PR against its actual dependency. No public query library, eager legacy evaluator, +remote resolver, shell executor, daemon or release action is introduced. + +The input briefing SHA-256 is +`43f8819c57e3d93bc6f7cf561d2d111442e089f2973cb7c62e16e3bd3fd73d0d`. +Its structural verifier counted 94 requirements, 111 new cases and 168 inherited +cases; those are inventory counts, not execution successes. The jq 1.7 observations +are historical references; differential claims require an actual pinned jq 1.8.2 +runner. Missing provider APIs/platform runners remain explicit blockers. + +Swift 6.4, language 6 and macOS/SDK 27 remain the native baseline. Mobile libraries +must continue to compile independently of the executable. Linux is a process +host; WASI executable feasibility is separate from the already qualified libraries. +Native and sanitizer receipts, subprocess outcomes, commands, toolchain, source and +binary identities accompany every qualified milestone. All 49 baseline probes and +independent-suite exclusions remain required and separate from CLI additions. + +Main reconciliation for merging PR23–PR27 preserves E2 main e8c3e4b and its public bridges, ergonomics behavior, six DocC catalogs and compiler consumers. Only the CLI executable is added to those six libraries. Exact combined module inventories and all 49 baseline probes remain mandatory. diff --git a/Documentation/Architecture/Release1.4/Progress.json b/Documentation/Architecture/Release1.4/Progress.json new file mode 100644 index 0000000..176a9e8 --- /dev/null +++ b/Documentation/Architecture/Release1.4/Progress.json @@ -0,0 +1,41 @@ +{ + "schema_version": 1, + "target_release": "1.4.0", + "renderer_base": "3c1e8a1a1bc8d03699665b8ab98f5ece7962aff7", + "main_at_orientation": "25fb04f747e583209b4c4511abf39e11ef5b4f80", + "branch": "codex/1.4-json-cli-foundation", + "status": "Compiling foundation boundary qualified on native macOS; C0/C1 complete closure and C2-C5 remain pending", + "gates": { + "C0": "partial", + "C1": "partial", + "C2": "not_run", + "C3": "not_run", + "C4": "not_run", + "C5": "not_run" + }, + "foundation_functions": 12, + "foundation_parameter_cases": 4, + "subprocess_cases": 53, + "subprocess_passed": 53, + "baseline_parameter_cases": 173, + "core_metrics": 49, + "cli_metrics": 16, + "publication_performed": false, + "root_test_functions": 232, + "root_parameter_cases": 177, + "native_source_manifest_sha256": "864d9b3dd8e1d79a0a6cbec862476843ddca2ff8a1582471b80fba54b863459e", + "qualified_lanes": [ + "native", + "safety", + "docs" + ], + "remaining_foundation_requirements": [ + "clean-source reproduction", + "selected mobile SDK consumers", + "immutable filter-plan compiler probe and implemented IR", + "all 16 CLI cap boundaries", + "multi-record shared accounting", + "slow/partial/no-progress sink probes", + "query compile exit 3 and full exit precedence" + ] +} diff --git a/Documentation/Architecture/Release1.4/Qualification.md b/Documentation/Architecture/Release1.4/Qualification.md new file mode 100644 index 0000000..460214c --- /dev/null +++ b/Documentation/Architecture/Release1.4/Qualification.md @@ -0,0 +1,50 @@ +# Foundation qualification boundary + +The foundation code and harness were qualified together under source manifest +`864d9b3dd8e1d79a0a6cbec862476843ddca2ff8a1582471b80fba54b863459e`. +The receipts identify the renderer base HEAD plus the actual edited-file hashes; +this is pre-commit evidence, not a claim that the parent commit contains the CLI. +Only this ledger, progress and qualification prose were subsequently updated. +Production Swift, the package manifest and executed scripts match those receipts. + +Native environment: arm64 macOS 27.0; Swift 6.4 +(swiftlang-6.4.0.34.1), language mode 6, Xcode 27.2 (27B5019j), SDK 27.2. +The configured beta Xcode is required on this host; the default CLT attempt was +unqualified and is retained separately. No baseline or compiler check was lowered. + +| Command | Actual outcome | +| --- | --- | +| `python3 Scripts/ci.py --lane native --output .build/ci/cli-c1-reviewed-native` | Exit 0; all 18 commands passed; debug/release each 232 functions, 177 parameter invocations | +| `python3 Scripts/ci.py --lane safety --output .build/ci/cli-c1-reviewed-safety` | Exit 0; ASan 232 functions/177 parameter invocations; TSan seven shared-state functions; strict-memory-safety build with warnings as errors | +| `python3 Scripts/ci.py --lane docs --output .build/ci/cli-c1-reviewed-docs` | Exit 0; five DocC catalogues, coverage checks and compiled examples | +| `python3 Scripts/qualify_cli.py --binary .build/release/swift-json --output …` | Exit 0; 53 real subprocess cases, no exclusions | +| `python3 Scripts/qualify_cli_ownership.py --output …` | Exit 0; three compiler probes: borrow compiles; double consume and cross-package access fail with required diagnostics | + +The inherited 173 parameter cases remain unchanged; four CLI parameter cases are +additional. All 49 baseline cap probes keep their recorded outcomes. Independent +syntax qualification observes 318 cases: 287 evaluated successes and 31 policy +cases. Schema qualification observes 2,337: 2,300 evaluated successes and 37 policy +cases. Authored suites retain 82 public semantics, nine budget/counter cases and +4,396 deterministic malformed-input replays. The downstream consumer retains 20 +explicitly rooted outcomes: eight positive, twelve negative, with two operational +error outcomes distinguished from ordinary invalidity. These do not establish MCP +server conformance. + +The three final lane receipts report unchanged source inputs while running. Earlier +failed compiler, SIGINT actor-isolation, EOF-race, normalized-spelling expectation +and strict-pointer-annotation attempts are retained alongside successful corrections. +The expected normalized `1e-1` spelling follows the existing coefficient/exponent +contract; no existing test was weakened. + +This is a reviewable foundation milestone. All 94 acceptance IDs remain in +Acceptance.json. Partial/not_run rows are not successes: complete filter IR/VM, +arithmetic/richer filters, all 16 CLI cap boundaries, split/slow/no-progress I/O, +selected mobile/portable consumers and clean candidate reproduction remain pending. +The renderer prerequisite is PR #21 at `3c1e8a1`; transfer/PDF work and the parallel +1.2 train are unchanged. Provider bridge APIs are absent at this base; qualification +and integration must precede their advertisement. No tag, merge or publication is +performed by this boundary. + +Materialized receipts and their exact source-input records are in the local +foundation evidence bundle. Run the listed commands to regenerate evidence; local +build outputs and private input packets are excluded from public Git/source archives. diff --git a/Documentation/README.md b/Documentation/README.md index 44892ae..9e022d6 100644 --- a/Documentation/README.md +++ b/Documentation/README.md @@ -33,6 +33,8 @@ Compiled archives and public symbol graphs remain available in CI artifacts. - [Linux platform and portable schema integrity](Architecture/Linux.md) - [WebAssembly audit and unresolved qualification boundary](Architecture/WebAssemblyAudit.md) +- [Prospective 1.4 CLI plan](Architecture/Release1.4/Plan.md) and [foundation contract](Architecture/Release1.4/Foundation.md) + ## Consumers, qualification and maintenance - [Five-product compiled example](../Examples/Consumer/README.md) diff --git a/Package.swift b/Package.swift index e8a0209..2f888f3 100644 --- a/Package.swift +++ b/Package.swift @@ -11,7 +11,8 @@ let package = Package( .library(name: "JSONStreaming", targets: ["JSONStreaming"]), .library(name: "JSONPatch", targets: ["JSONPatch"]), .library(name: "JSONHTML", targets: ["JSONHTML"]), - .library(name: "JSONBridges", targets: ["JSONBridges"]) + .library(name: "JSONBridges", targets: ["JSONBridges"]), + .executable(name: "swift-json", targets: ["JSONCLI"]) ], targets: [ .target(name: "JSON"), @@ -22,6 +23,10 @@ let package = Package( .target(name: "JSONStreaming", dependencies: ["JSON"]), .target(name: "JSONPatch", dependencies: ["JSON"]), .target(name: "JSONHTML", dependencies: ["JSON"], exclude: ["Assets"]), + .target(name: "JSONFilterRuntime", dependencies: ["JSON"]), + .target(name: "JSONCLIEngine", dependencies: ["JSON", "JSONSchema", "JSONStreaming", "JSONPatch", "JSONHTML", "JSONFilterRuntime"]), + .executableTarget(name: "JSONCLI", dependencies: ["JSONCLIEngine"]), + .testTarget(name: "JSONCLITests", dependencies: ["JSONCLIEngine", "JSONFilterRuntime", "JSON", "JSONPatch", "JSONSchema", "JSONHTML"]), .testTarget(name: "JSONHTMLTests", dependencies: ["JSONHTML", "JSON"]), .testTarget(name: "JSONTests", dependencies: ["JSON"], exclude: ["ImplementationPlan.md"]), .testTarget(name: "JSONSchemaTests", dependencies: ["JSONSchema"], exclude: ["ImplementationPlan.md"]), diff --git a/README.md b/README.md index 5c37627..39c545a 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,7 @@ Choose the products your application needs: | **JSONSchema** | Draft 2020-12 compilation/evaluation, offline registries, bounded regex, annotations and raw declaration inspection | | **JSONStreaming** | Pull syntax events and values, strict NDJSON, root-array elements and awaited output chunks | | **JSONHTML** | Exact HTML, offline exploration and immutable native transfer/export (1.3 development) | +| **swift-json** | Bounded command-line JSON workflows (1.4 development) | | **JSONBridges** | Opt-in native integer, Double and Foundation Decimal conversions (E2 development) | | **JSONPatch** | Staged RFC 6902 JSON Patch and RFC 7396 Merge Patch | @@ -454,11 +455,11 @@ Browse the [public documentation site](https://thorfuchs.github.io/Swift-JSON/): [JSONPatch](https://thorfuchs.github.io/Swift-JSON/JSONPatch/documentation/jsonpatch/). The site tracks `main` and publishes only after all three native CI lanes pass. -The [documentation index](Documentation/README.md) links the behavior contracts. The five DocC catalogs +The [documentation index](Documentation/README.md) links the behavior contracts. The six DocC catalogs provide public API references, focused guides, parameter descriptions and failure contracts, compiled from the native Swift public symbol graphs. -Build all five catalogs on a supported native host: +Build all six catalogs on a supported native host: ```sh python3 Scripts/ci.py --lane docs @@ -508,3 +509,19 @@ following [SECURITY](SECURITY.md); see [SUPPORT](SUPPORT.md) for maintenance and Original code is licensed under [Apache-2.0](LICENSE). Adapted code and qualification inputs retain their applicable [notices](NOTICE), [third-party notices](THIRD_PARTY_NOTICES.md), [licenses](Licenses) and [extraction provenance](Documentation/Architecture/ExtractionManifest.json). + +## Prospective 1.4 command-line tool + +This feature train adds `swift-json` beside the six libraries. Its compiling +foundation provides strict formatting, validation, Pointer selection, staged +Patch and qualified HTML/text/Markdown rendering. See the [CLI plan](Documentation/Architecture/Release1.4/Plan.md) +and [foundation contract](Documentation/Architecture/Release1.4/Foundation.md) +for command semantics, cumulative budgets and qualification boundaries. Query and +provider commands are advertised only after their separate gates pass. + +```sh +swift build -c release --product swift-json +.build/release/swift-json format --compact input.json +.build/release/swift-json validate --schema schema.json input.json +.build/release/swift-json render input.json --output inspection.html +``` diff --git a/RELEASING.md b/RELEASING.md index 6cb011b..2d9692c 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -6,7 +6,7 @@ or releases. Published version tags are protected against updates and deletion. 1. Require passed native, safety and documentation lanes for the exact candidate commit on macOS/SDK 27+ and Swift 6.4+ with language mode 6. -2. Review six public products (including JSONHTML and opt-in JSONBridges), the empty root dependency graph, compiled external +2. Review seven public products (six libraries, including opt-in JSONBridges, plus swift-json), the empty root dependency graph, compiled external consumers, populated pinned suites, policy exclusions, all 49 finite caps, schema/regex behavior and cancellation boundaries. 3. Review licenses, provenance, public file inventory and documentation links. diff --git a/Scripts/build_documentation_site.py b/Scripts/build_documentation_site.py index fa1c658..83f9070 100644 --- a/Scripts/build_documentation_site.py +++ b/Scripts/build_documentation_site.py @@ -99,7 +99,7 @@ def landing(commit):
Public Swift documentation

Exact JSON. Clear contracts.

-

Keep decimal values exact, Unicode scalar keys distinct and resource use explicit. Explore five 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 six 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 d1e1d03..632ff34 100644 --- a/Scripts/ci.py +++ b/Scripts/ci.py @@ -25,7 +25,7 @@ def commands(lane, output): # Root behavior/corpora remain required. SwiftData and Apple SDK/lifetime # probes are separate Apple acceptance; they never become Linux passes. return [c for c in commands('native', ROOT / output) - if not any(x in c for x in ['Tools/MobileQualification', '--mode'])] + [ + if not any(x in c for x in ['Tools/MobileQualification', '--mode', 'Scripts/qualify_cli_ownership.py'])] + [ ['python3', '-B', 'Scripts/qualify_linux_reproduction.py', '--output', str(output / 'reproduction')]] if lane == 'linux-safety': # Every behavior case uses Swift Testing. Do not start the generated @@ -53,6 +53,8 @@ def commands(lane, output): ['swift', 'run', '-c', 'release', '--package-path', 'Tools/JSONHTMLBrowser', 'BrowserFixtures', str(output / 'fixtures')], ['python3', '-B', 'Scripts/qualify_html_browser.py', '--fixtures', str(output / 'fixtures'), '--output', str(output / 'browser')], ] + if lane == 'cli': + return [['swift', 'build', '-c', 'release', '--product', 'swift-json'], ['swift', 'test', '--filter', 'cli'], ['python3', '-B', 'Scripts/qualify_cli.py', '--binary', '.build/release/swift-json', '--output', str(output / 'subprocess.json')]] if lane == 'native': return [ ['python3', '-B', 'Scripts/public_check.py'], @@ -61,6 +63,8 @@ def commands(lane, output): ['swift', 'build', '-c', 'release'], ['python3', '-B', 'Scripts/verify_testing_events.py'], ['swift', 'test'], ['swift', 'test', '-c', 'release'], + ['python3', '-B', 'Scripts/qualify_cli.py', '--binary', '.build/release/swift-json', '--output', str(output / 'subprocess.json')], + ['python3', '-B', 'Scripts/qualify_cli_ownership.py', '--output', str(output / 'cli-ownership')], ['python3', '-B', 'Scripts/qualify_release_1_1.py', '--mode', 'ownership', '--output', str(output / 'ownership.json')], ['python3', '-B', 'Scripts/qualify_release_1_1.py', '--mode', 'reader', '--output', str(output / 'reader.json')], ['swift', 'run', '-c', 'release', '--package-path', 'Examples/Consumer', 'Consumer'], @@ -113,10 +117,12 @@ def check_result(command, code, log, events=None): if events is not None: counts = events['bundle_counts'] if command[:2] == ['swift', 'test']: - expected = [38] if 'export|Export|apple' in command else [14] if 'Tools/WasmAudit' in command else [2, 3, 3, 11] if 'qa' in command else [7] if R0_TESTS in command else [3] if 'Tools/MCPReadiness' in command or 'Tools/MobileQualification' in command else [1] if 'Tools/Qualification' in command else [1, 1, 2, 3 if sys.platform == 'linux' else 4, 4] if 'thread' in command else sorted([10, 11, 12, 14, 61 if sys.platform == 'linux' else 75, 55, 119]) + expected = [12] if 'cli' in command else [38] if 'export|Export|apple' in command else [14] if 'Tools/WasmAudit' in command else [2, 3, 3, 11] if 'qa' in command else [7] if R0_TESTS in command else [3] if 'Tools/MCPReadiness' in command or 'Tools/MobileQualification' in command else [1] if 'Tools/Qualification' in command else [1, 1, 2, 3 if sys.platform == 'linux' else 4, 4] if 'thread' in command else sorted([10, 11, 12, 12, 14, 61 if sys.platform == 'linux' else 75, 55, 119]) passed = passed and sorted(counts) == expected if '--filter' not in command and not any(x.startswith('Tools/') for x in command): - passed = passed and (events['parameterized_functions'] == ROOT_PARAMETER_CASES if events is not None else sum(int(n) for n in re.findall(r'with (\d+) test cases passed', log)) == 173) + if events is not None: + passed = passed and events['module_function_counts'] == {'JSONTests':119,'JSONBridgesTests':10,'JSONSchemaTests':55,'JSONStreamingTests':14,'JSONPatchTests':11,'JSONRegexRuntimeTests':12,'JSONHTMLTests':61 if sys.platform == 'linux' else 75,'JSONCLITests':12} + passed = passed and (events['parameterized_functions'] == ROOT_PARAMETER_CASES if events is not None else sum(int(n) for n in re.findall(r'with (\d+) test cases passed', log)) == 177) if 'Tools/Qualification' in command: probes = re.findall(r'^CAP_PROBE (\w+) (\S+)$', log, re.MULTILINE) matrix = json.loads((ROOT / 'Documentation/Qualification/LimitsMatrix.json').read_text()) @@ -124,10 +130,10 @@ def check_result(command, code, log, events=None): passed = passed and len(probes) == 49 and dict(probes) == expected_probes 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'] 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']} == {name: [name] for name in ['JSON', 'JSONSchema', 'JSONStreaming', 'JSONPatch', 'JSONHTML', 'JSONBridges']} + 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']}) targets = {t['name']: t for t in d['targets']} - passed = passed and set(targets) == {'JSON', 'JSONBridges', 'JSONSchema', 'JSONStreaming', 'JSONPatch', 'JSONHTML', 'JSONRegexRuntime', 'JSONTests', 'JSONBridgesTests', 'JSONSchemaTests', 'JSONStreamingTests', 'JSONPatchTests', 'JSONHTMLTests', 'JSONRegexRuntimeTests'} and targets['JSONHTML']['dependencies'] == [{'byName': ['JSON', None]}] and targets['JSONBridges']['dependencies'] == [{'byName': ['JSON', None]}] + passed = passed and set(targets) == {'JSON', '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['JSONFilterRuntime']['dependencies'] == [{'byName': ['JSON', None]}] and targets['JSONCLI']['type'] == 'executable' if command == ['swift', 'package', 'show-dependencies', '--format', 'json'] and passed: passed = json.loads(log)['dependencies'] == [] if command[:2] == ['swift', 'run'] and 'Tools/MobileQualification' in command: @@ -146,7 +152,7 @@ def check_result(command, code, log, events=None): def main(): parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument('--lane', choices=['native', 'safety', 'docs', 'r0', 'qa', 'linux', 'linux-safety', 'wasm', 'browser', 'export'], required=True) + parser.add_argument('--lane', choices=['native', 'safety', 'docs', 'r0', 'qa', 'linux', 'linux-safety', 'wasm', 'browser', 'export', 'cli'], required=True) parser.add_argument('--output') args = parser.parse_args() output = ROOT / (args.output or '.build/ci/' + args.lane) diff --git a/Scripts/qualify_cli.py b/Scripts/qualify_cli.py new file mode 100644 index 0000000..8ce7f81 --- /dev/null +++ b/Scripts/qualify_cli.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: Apache-2.0 +"""Exercise the real CLI subprocess, exact bytes, exits, stderr and atomic files.""" +import argparse, hashlib, json, os, pathlib, signal, subprocess, tempfile, time + +ROOT = pathlib.Path(__file__).resolve().parents[1] + +def main(): + parser = argparse.ArgumentParser(); parser.add_argument('--binary', required=True); parser.add_argument('--output', required=True) + args = parser.parse_args(); binary = (ROOT / args.binary).resolve(); rows = [] + def run(name, argv, data=b'', exit=0, expected=None, check=None): + command = [str(binary), *argv]; process = subprocess.run(command, input=data, capture_output=True, timeout=30) + ok = process.returncode == exit and (expected is None or process.stdout == expected) + if check: ok = ok and check(process) + rows.append({'id': name, 'command': ['swift-json', *[a if isinstance(a,str) else {'bytes_hex':a.hex()} for a in argv]], 'exit_code': process.returncode, 'expected_exit': exit, + 'stdout_sha256': hashlib.sha256(process.stdout).hexdigest(), 'stdout_bytes': len(process.stdout), + 'stderr_sha256': hashlib.sha256(process.stderr).hexdigest(), 'stderr_bytes': len(process.stderr), 'status': 'passed' if ok else 'failed'}) + if not ok: print(name, process.returncode, repr(process.stdout[:250]), repr(process.stderr[:500]), flush=True) + return process + with tempfile.TemporaryDirectory(prefix='swift-json-cli-') as temp: + temp = pathlib.Path(temp) + def file(name, data): + path = temp / name; path.write_bytes(data); return str(path) + def limit(**caps): return file('limits.json', json.dumps({'version':1,'cli':caps}).encode()) + run('help', ['--help'], check=lambda p: b'format' in p.stdout and not p.stderr) + run('invalid-argv-utf8', ['format', b'\xff'], exit=2, expected=b'', check=lambda p: b'invalidArgvUTF8' in p.stderr) + run('version', ['--version'], expected=b'swift-json 1.4.0-dev\n') + run('version-json', ['--version','--json'], check=lambda p: json.loads(p.stdout)['revision'] == 'unknown') + run('missing-command', [], exit=2, expected=b'') + run('unknown-option', ['format','--unknown'], exit=2, expected=b'') + run('usage-json-diagnostic', ['format','--diagnostics=json','--unknown'], exit=2, expected=b'', check=lambda p: json.loads(p.stderr)['kind'] == 'diagnostic' and json.loads(p.stderr)['category'] == 'usage') + run('duplicate-option', ['format','--compact','--compact'], exit=2, expected=b'') + run('indent-conflict', ['format','--compact','--tab'], exit=2, expected=b'') + run('preserved-numbers', ['format','--compact'], b'[9007199254740993,0.10,-0,1e1000]', expected=b'[9007199254740993,0.10,-0,1e1000]\n') + run('normalized-numbers', ['format','--compact','--number-style=normalized'], b'[0.10,-0]', expected=b'[1e-1,0]\n') + run('tab-indentation', ['format','--tab'], b'{"a":[1]}', expected=b'{\n\t"a": [\n\t\t1\n\t]\n}\n') + scalar = '{"é":1,"é":2}'.encode() + run('scalar-distinct-keys', ['format','-cS'], scalar, expected='{"é":2,"é":1}\n'.encode()) + run('duplicate-decoded-key', ['format','--compact'], b'{"a":1,"\\u0061":2}', exit=5, expected=b'') + run('malformed-utf8', ['format'], b'"\xff"', exit=5, expected=b'') + run('trailing-root', ['format'], b'{} []', exit=5, expected=b'') + run('validation-syntax', ['validate'], b'{}', check=lambda p: json.loads(p.stdout) == {'valid':True,'issues':[],'truncated':False}) + run('validation-malformed', ['validate'], b'{', exit=5, expected=b'') + schema = file('schema.json', b'{"type":"integer","minimum":3}') + run('schema-valid', ['validate','--schema',schema], b'4', check=lambda p: json.loads(p.stdout)['valid'] is True) + run('schema-invalid', ['validate','--schema',schema], b'2', exit=1, check=lambda p: json.loads(p.stdout)['valid'] is False and len(json.loads(p.stdout)['issues']) > 0) + run('schema-bounded-issues', ['validate','--schema',schema,'--max-issues','0'], b'2', exit=1, check=lambda p: json.loads(p.stdout) == {'valid':False,'issues':[],'truncated':True}) + run('pointer-null', ['pointer','/a'], b'{"a":null}', expected=b'null\n') + run('pointer-missing', ['pointer','/a'], b'{}', exit=5, expected=b'') + run('pointer-allow-missing', ['pointer','/a','--allow-missing'], b'{}', exit=4, expected=b'') + run('pointer-array-absence', ['pointer','/0','--allow-missing'], b'[]', exit=4, expected=b'') + run('pointer-malformed-index-stays-error', ['pointer','/01','--allow-missing'], b'[]', exit=5, expected=b'') + run('pointer-wrong-type', ['pointer','/a','--allow-missing'], b'[]', exit=5, expected=b'') + run('pointer-escaped-key', ['pointer','/a~1b~0c'], b'{"a/b~c":1}', expected=b'1\n') + patch = file('patch.json', b'[{"op":"remove","path":""}]') + run('patch-root-absence', ['patch','--patch',patch], b'null', expected=b'') + patch = file('patch.json', b'[{"op":"add","path":"/b","value":9007199254740993}]') + run('patch-exact-value', ['patch','--patch',patch], b'{"a":1}', check=lambda p: b'9007199254740993' in p.stdout) + patch = file('patch.json', b'[{"op":"add","path":"/b","value":2},{"op":"test","path":"/a","value":0}]') + run('patch-failure-no-candidate', ['patch','--patch',patch], b'{"a":1}', exit=5, expected=b'') + run('html-invalid-title-is-usage', ['render','--title','\x01'], b'{}', exit=2, expected=b'') + run('static-html', ['render'], b'{"x":"