Commit Graph

105 Commits

Author SHA1 Message Date
8d30010e0d docs: align stale figures with code and the enforced XSTS gate
- README, roadmap: XSTS status quad and gates table now read the enforced
  0/43/0/31 (Tests/XSTSSuiteTests.swift); test count 986/169 to 1448/258;
  encoding list and the remaining-work section reflect shipped reality;
  check-all expansion lists the validation and changelog gates
- GEMINI.md, onboarding-antigravity.md: valid-schemas-rejected 1 to 0 and the
  pinned baselines updated to current
- SECURITY.md: complete the reporting address
- Parsing.InputEncoding: doc comment lists the full shipped encoding set
- Schema.XSDParserUnion: guard the localName interpolation with ?? "" to match
  the same line and silence an optional-interpolation warning (internal dedup
  key, behavior preserving)
- CHANGELOG: Unreleased entries for the above
2026-06-19 23:32:04 +02:00
b73384bc2e fix(schema): count content-model occurrences 2026-06-19 23:32:04 +02:00
47c3a230e4 docs(schema): design counted content automaton 2026-06-19 09:23:05 +02:00
f8fd865456 fix(schema): carry global ref metadata into restrictions 2026-06-19 09:03:49 +02:00
55713bbbc0 fix(schema): stop blocked substitution chaining 2026-06-19 08:37:19 +02:00
f04ab8afa1 Reject complex substitutions for anySimpleType heads 2026-06-18 23:04:11 +02:00
00995071b0 Reject mixedness-changing complexContent extensions 2026-06-18 22:37:49 +02:00
ed38a76acd Reject invalid simpleContent inline restrictions 2026-06-18 22:01:01 +02:00
54a731e190 Mirror mandatory Swift rules 2026-06-18 22:00:41 +02:00
d0805f21bb docs: analyze the release hurdles to 1.0 (false-negative tail, proven bounds)
Companion to production-readiness.md and roadmap.md. Characterizes, with code
evidence, the two biggest hurdles. (1) The invalid-accepted tail concentrates in
ParticleRestriction.violation's deliberately under-approximated clauses (MapAndSum,
RecurseAsIfGroup, NameAndTypeOK): a single high-fan-in oracle where tightening
risks a false positive. (2) ContentMatcher unrolls occurrence values into NFA
states, so the occursUnrollCap/totalStateCap/positionCap caps are band-aids that
silently degrade to star; a counting automaton is what turns the cap into a proven
bound.
2026-06-18 20:46:12 +02:00
c6f305357c chore(rules): align lint config and pointer with canonical rules-swift
Make public/rules-swift the canonical source (per project direction) and adopt
its opt-in lint rules that PureXML lacked: empty_count, explicit_init, first_where,
sorted_first_last, unused_import, plus its todo disable. All pass with zero
violations on the existing sources.

PureXML keeps its coherent, stricter tuning where the canon is a self-described
'starting point': force_unwrapping/force_try/force_cast = error (safety), and
trailing commas mandated in both swiftformat (--commas always) and swiftlint
(mandatory_comma) to resolve the canon's formatter-adds vs linter-flags mismatch.
docs/rules/README.md now points at public/rules-swift and documents the tuning.
2026-06-18 20:30:46 +02:00
24a9299975 docs(xsts): account for the remaining invalid-schemas-accepted tail (74)
Adds a dated accounting to the XSTS deviation worklist: the labelled-suite
ratchet stands at 0/74/0/133 with false positives held at 0 across the campaign.
Partitions the remaining 74 into fixable-but-intricate debt (redefine
restriction, NameAndTypeOK union membership, wildcard UPA, chameleon/cross-ns
composition, heterogeneous particle edges) and irreducible-by-design or disclosed
items (RecurseAsIfGroup spec ambiguities, the deliberate regex-tolerance), with
the root cause and false-positive risk for each so the burndown is driven by
understanding. Records that the adversarial critic loop caught three genuine
false positives this session that the suite and differential both missed.
2026-06-18 01:19:38 +02:00
be8a39394d fix(schema): advance XSTS valid-instances-rejected to 4 (#146)
Consolidates the in-progress #146 work; valid-instances-rejected reaches 4
on the 2006-11-06 XSTS archive (buckets now 1/262/4/147).

Regex: match Unicode scalars rather than grapheme clusters; the empty
pattern matches only the empty string; pin the category repertoire to
Unicode 3.2, the version the corpus is consistent at, so code points added
in 3.2 (Tagalog, Cyrillic Komi) are word characters while later additions
(the Tamil digit zero) stay unassigned and match \D. New XSDCategory and a
3.2 assignment table derived from DerivedAge, replacing the old Unicode31
files.

Content model: assess each child against the particle the content automaton
matched, not a by-name lookup (#180). Two same-named particles keep their
own fixed values, and an element matching a skip wildcard is no longer
validated against its global declaration. Selection is made reproducible
when an ambiguous schema slips past the UPA check.

XSTS runner: compile and merge every schemaDocument in a schemaTest, not
just the first; this also surfaced one previously-masked invalid-instance
acceptance (recorded in the baselines).

Also folds in attribute-group anyAttribute inheritance, extension wildcard
union, namespace-qualified type tables for multi-document
xsi:schemaLocation, per-container elementFormDefault, strict and lax
attribute wildcard validation, built-in type resolution, and xs:redefine
simpleType overrides.
2026-06-16 22:22:05 +02:00
229d7df3d0 feat(validation,schema): composable validation framework and cross-document composition
Ship the OpenAPIKit-style validation layer (builtin rules, warnings channel,
Validator tiers, coverage gates) and wire XSD compile checks through it. Advance
#161 with chameleon include validation, multi-container reference resolution,
and include targetNamespace composition rules so merged schema sets compile
correctly when a schemaLoader is provided.
2026-06-16 09:57:43 +02:00
5f6170a57a docs(roadmap): add living roadmap index and README focus link
Document the restructured GitHub issue hierarchy (epic #167, gates,
milestones M1-M5, task labels) and point README Status at the current
production-readiness focus and v0.2.0 XSTS baselines.
2026-06-16 01:30:37 +02:00
baa90cfcaa chore(release): prepare 0.2.0
Cut the second pre-release: schema-validity burn-down to XSTS baselines
1/266/171/155, component child-content shape checks, and synced conformance
docs. CHANGELOG updated for v0.2.0.
2026-06-16 01:27:10 +02:00
55daca46be fix(schema): implement facet applicability and validation constraints 2026-06-16 00:02:04 +02:00
5cdcde9055 fix(schema): enforce element order and import constraints 2026-06-15 23:29:47 +02:00
434bfc85ea fix(schema): validate duplicate names across separate files with identical content 2026-06-15 22:57:00 +02:00
926ff99b5a fix(schema): validate xml:lang and xml:space on documentation elements 2026-06-15 22:36:51 +02:00
20b97d1d62 fix(schema): validate notation declarations and enumeration restrictions 2026-06-15 22:27:04 +02:00
4a7e23186d fix(schema): check component name and identity constraint uniqueness across all containers 2026-06-15 22:08:14 +02:00
d0e0b96de9 fix(schema): support inline element types in substitution group exclusions 2026-06-15 21:40:01 +02:00
ec4b2aa80c fix(schema): enforce substitution group exclusions based on final 2026-06-15 20:51:43 +02:00
5a2e2f3a40 fix(schema): enforce targetNamespace matching on local references 2026-06-15 20:08:39 +02:00
614209e9c1 fix(schema): enforce variety constraints on list itemType and union memberTypes 2026-06-15 20:01:51 +02:00
0496c6948a fix(schema): implement namespace-aware reference resolution checks 2026-06-15 19:44:32 +02:00
ffff13da57 fix(schema): enforce simpleType restriction structure and QName prefix bindings 2026-06-15 19:22:10 +02:00
1dcff00874 fix(schema): reject local-use attributes on top-level group and attributeGroup definitions 2026-06-15 19:03:38 +02:00
9004efe400 fix(schema): inherit and prohibit attributes under complexContent restriction 2026-06-15 18:52:23 +02:00
80064be6b8 feat(schema): validate identity constraint keyref field arity mismatch 2026-06-15 18:23:45 +02:00
31fe3e7c22 feat(schema): enforce particle element type restriction and bypass prohibited attributes 2026-06-15 18:10:21 +02:00
b6575150e8 feat(schema): enforce attribute restriction type derivation (derivation-ok-restriction.1)
Require that any restricted attribute has a type validly derived by restriction from its base counterpart. Validates atomic built-in derivation, list item type restrictions, and union member/subset relationships recursively. Updates baseline to 362 accepted invalid schemas.
2026-06-15 17:46:15 +02:00
a7c007e969 chore(schema): update baseline count for schemaInvalidAccepted to 367
Update invalid schemas accepted baseline to 367 following correction of xs:anySimpleType restriction rule.
2026-06-15 17:09:16 +02:00
ef80934ff8 feat(schema): enforce top level names, restrict xs:anySimpleType, and validate simpleType facets
Reject top level declarations that omit a name attribute. Disallow derivation by restriction of xs:anySimpleType inside simpleType definitions. Require restriction facets length, minLength, maxLength, totalDigits, and fractionDigits to restrict or equal the base type facets. Updates the conformance baseline to 383 accepted invalid schemas.
2026-06-15 17:06:09 +02:00
f86a7c9ade feat(schema): enforce attribute fixed value constraint under restriction 2026-06-15 16:24:32 +02:00
b102503d29 docs(agents): refresh onboarding with value-space comparison lesson and current baseline 2026-06-15 16:11:13 +02:00
b80e31d562 feat(schema): a restriction may not relax a required base attribute (cos-ct-derived-ok)
In a complexContent restriction, an attribute the restriction redeclares that the
base type marks use="required" may not be made optional or prohibited. Only
attributes explicitly redeclared that also exist in the base are checked; an
omitted attribute is inherited unchanged. The base reference must resolve to the
schema's own target namespace, and the check stands down for a schema that
composes other documents.

The matching fixed-value clause is deliberately not enforced: it requires
comparing the two fixed values in the attribute type's value space, not lexically
(a list-typed fixed value differing only in whitespace is the same value), so a
string comparison wrongly rejects valid schemas. That clause is left for a later
change (a disclosed under-rejection).

XSTS: invalid schemas accepted 394 to 390, no other bucket raised.
2026-06-15 16:09:02 +02:00
c4485ad6b5 docs(agents): add contributor onboarding guide and editor rules file 2026-06-15 15:50:10 +02:00
282ceb57fc feat(schema): a nested simpleType or attributeGroup may not be named (localSimpleType)
A simpleType nested inside a restriction/list/union/element/attribute is the
anonymous localSimpleType (no name), and a nested attributeGroup is always a
reference; named simpleType and attributeGroup definitions are top-level only (a
direct child of schema or redefine). A nested definition declaring a name was
accepted; it is now rejected. A nested anonymous simpleType, an attributeGroup
reference, and a top-level named definition are unaffected.

XSTS: invalid schemas accepted 403 to 394, no other bucket raised.
2026-06-15 15:41:48 +02:00
c4679acfd8 feat(schema): reject an all group extending a base with content (cos-all-limited.1.2)
An xs:all group in a complexContent extension of a base that already has element
content was accepted. The effective content model of such an extension is
sequence(base content, extension content), which nests the all and violates the
rule that an all group must be the whole content model. The base type is read
from the compiled model: rejected only when the base resolves, in the schema's
own target namespace, to a complex type with element-only or mixed content. An
explicitly-empty base (an empty model group with mixed=false) has effectively
empty content and may still be extended by an all (the all becomes the whole
content); a simple-content, empty, foreign, or unresolved base is left alone.
Checked for a self-contained schema.

XSTS: invalid schemas accepted 411 to 403, no other bucket raised.
2026-06-15 15:31:01 +02:00
ca1a7bdf3f feat(schema): enforce simpleType final for list and union derivation (st-props-correct)
A simple type whose final contains list (or #all) may not be a list itemType,
and one whose final contains union (or #all) may not be a union memberType.
finalRespected already covered restriction and extension; the list and union
directions were unchecked because the derivation-method set does not model
final="list"/"union", so the final attribute is read directly. The itemType /
memberTypes reference is matched only when it resolves to the schema's own target
namespace, so a list or union of a built-in (whose final is empty) is not
confused with a user type of the same local name. Checked for a self-contained
schema.

XSTS: invalid schemas accepted 413 to 411, no other bucket raised.
2026-06-15 15:12:11 +02:00
fbcfe758a5 feat(schema): whiteSpace facet may only strengthen the base (Part 2 4.3.6)
A whiteSpace facet that relaxed its base type's effective whiteSpace was
accepted; XSD Part 2 4.3.6 permits only strengthening, ordered
preserve < replace < collapse. A base fixed to collapse admits only collapse,
and a replace base admits replace or collapse; relaxing it (e.g. replace over a
collapse base, or restricting xs:token to replace) is now rejected. The base's
effective whiteSpace is its own facet falling back to its built-in intrinsic;
the check is atomic-only and, when a base's own whiteSpace has not yet resolved,
can only under-detect (an unresolved base defaults to preserve, the weakest), so
it never rejects a valid restriction.

XSTS: invalid schemas accepted 422 to 413, no other bucket raised.
2026-06-15 14:54:47 +02:00
44d37a1a5f feat(schema): top-level element may not have ref/form/minOccurs/maxOccurs (topLevelElement)
A top-level xs:element declaration (a direct child of schema, or of redefine) was
accepted with ref, form, minOccurs, or maxOccurs. A global element is a
declaration, never a particle or a reference, so those local-use attributes are
prohibited by the schema-for-schemas topLevelElement. The top-level-attribute
applicability scan is generalized into topLevelDeclarationErrors, driven by a
per-kind forbidden-attribute map, covering both attribute and element. A local
element particle inside a content model is unaffected.

XSTS: invalid schemas accepted 424 to 422, no other bucket raised.
2026-06-15 14:39:54 +02:00
7ed7059134 feat(schema): element ref excludes declaration-only attributes and inline type (src-element.2.2)
An element ref carrying nillable/default/fixed/form/block, or an element or
attribute ref carrying an inline type definition, was accepted. A ref is a use
of a global declaration, not a declaration, so beyond ref it admits only
minOccurs, maxOccurs, and id (src-element.2.2). The applicability check already
excluded name and type from a ref; this extends the exclusion to the remaining
declaration-only properties and to an inline simpleType/complexType child.
minOccurs/maxOccurs, a group/attributeGroup ref, and an attribute ref's
use/default/fixed (which override on the use) are unaffected.

XSTS: invalid schemas accepted 439 to 424, no other bucket raised. Disclosed
under-detection: a key/unique/keyref child under a ref is not yet flagged.
2026-06-15 14:29:13 +02:00
be5d260b52 feat(schema): top-level attribute may not have use/form/ref (topLevelAttribute)
A top-level xs:attribute declaration (a direct child of schema, or of redefine)
was accepted with use, form, or ref. Those belong to a local attribute use, not
a global declaration: the schema-for-schemas topLevelAttribute marks ref, form,
and use as prohibited, allowing only default, fixed, id, name, type and an inline
simpleType. The per-component applicability table is the permissive global/local
union, so it could not draw the distinction; a focused scan of the direct
attribute children of schema and redefine supplies the global-only constraint. A
local attribute use inside a complex type or attribute group is unaffected.

The existing test_validAttributeValues asserted a top-level attribute with use
compiles, which is itself invalid; corrected to a local attribute use.

XSTS: invalid schemas accepted 454 to 439, no other bucket raised.
2026-06-15 14:18:25 +02:00
aa6e76da88 feat(schema): validate value constraints against user types; fix inline restriction base
A default/fixed value on an element or attribute whose type names a user-declared
type in the schema's own target namespace must be a valid value of that type
(XSD 1.0 e-props-correct.2 / a-props-correct.2). The check runs after the named
types are compiled and validates with the compiled SimpleType validator (the one
instance validation uses), so whitespace and facet handling match. Built-ins are
handled at structure time; imported, foreign, and inline anonymous types are left
alone via a namespace gate.

This exposed a pre-existing compile defect: a simpleType restriction read its base
only from the base attribute, so an inline anonymous <simpleType> base (a list or
union with no base attribute) was dropped and the type collapsed to an atomic
string, making a length facet count characters instead of list items. The
restriction branch now resolves the inline child as its base, preserving list and
union variety. This corrects both schema-time value checking and instance
validation.

XSTS: invalid schemas accepted 462 to 454; invalid instances accepted 160 to 158;
no other bucket raised.
2026-06-15 14:06:26 +02:00
a087c022e9 feat(schema): attribute default requires use=optional (src-attribute.2)
An xs:attribute declaration carrying a default value constraint was accepted
alongside use="required" or use="prohibited"; XSD 1.0 src-attribute.2 requires
use to be optional when default is present (a default makes the attribute
optional). The check rides the existing value-constraint walk, gated to
XSD-namespace attribute declarations reading the unprefixed default/use, and is
per declaration. Only fixed (not default) may pair with use="required".

XSTS: invalid schemas accepted 469 to 462, no other bucket raised. Disclosed
under-rejection: a whitespace-padded use=" required " (NMTOKEN actual value
"required") is not flagged.
2026-06-15 13:44:21 +02:00
de82800525 feat(schema): reject both default and fixed on one declaration (src-element.1/src-attribute.1)
An xs:element or xs:attribute declaration carrying both a default and a fixed
value constraint was accepted; XSD 1.0 src-element.1 / src-attribute.1 make the
two mutually exclusive. The check rides the existing value-constraint structure
walk, gated to XSD-namespace declarations and reading the unprefixed
default/fixed (a foreign same-local-name attribute is not the value
constraint). It is per declaration, so a default on a global declaration and a
fixed on a reference to it (two separate items) remains valid.

XSTS: invalid schemas accepted 479 to 469, no other bucket raised.
2026-06-15 13:25:14 +02:00
d2f18a2685 feat(schema): substitution member type must derive from head (e-props-correct.4)
An element declaring substitutionGroup="head" whose own type is unrelated to
the head's type was accepted; XSD 1.0 e-props-correct.4 requires the member's
type be validly derived from the head's. The check runs after named types
resolve and reuses the restriction/extension + built-in-lattice derivation
oracle (an ur-type head admits any member).

It is conservative so it never rejects a valid member: it runs only for a
self-contained schema (no import/include/redefine, where the derivation table
is complete and single-namespace names are unambiguous), reads the member's
type from its own type attribute and the head's from the top-level element
declarations only (so a local element of the same name supplies neither), and
stands down when either type is a list or union (cos-st-derived-ok clauses
2.3/2.4 union-member derivation is not modelled).

The post-namedTypes consistency calls move into a postNamedTypeErrors
aggregator alongside consistencyErrors. XSTS: invalid schemas accepted
480 to 479, no other bucket raised.
2026-06-15 13:08:38 +02:00