Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .agents/skills/enigmatic-codable/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
name: enigmatic-codable
description: Change or review Enigma encoder/decoder containers, coding paths, serialization, and Swift/Foundation object bridging.
---

# Enigma Codable and bridging

Paths here are relative to the repository root. For containers, inspect only the
affected keyed, unkeyed, or single files in
`Sources/Enigmatic/Internal/EnigmaEncoder` or `EnigmaDecoder`. For serialization
or casting, locate the method in `Public/Enigma/Enigma.swift`,
`Public/Enigma/Capabilities/Enigma+Conversion.swift`, `Internal/Extensions`, or
`Internal/Primitives/EnigmaConvertible*.swift`, all under `Sources/Enigmatic`.

Preserve these contracts unless the user requests a behavior change:

- Keep codingPath keys and userInfo through nested and super containers.
Distinguish missing, null, mismatched values, and array exhaustion. Failed
unkeyed reads do not advance; `decodeNil()` advances only for null.
- Keyed handles share storage; reopening unkeyed or occupied child containers
records a conflict. Completion throws the first recorded acquisition error.
Direct duplicate value writes can be caught without invalidating encoding;
successful partial writes are not rolled back.
- Date/Data retain native nodes through Enigma containers. External tree encoding
calls Foundation Codable directly, bypassing external date/data strategies.
- Object bridge keys normalize to strings; reject collisions and unsupported
keys with their paths. JSON objects reject Date/Data, non-finite numbers, and
128-bit integers; plist objects reject null and 128-bit integers.

Select `ContainerContractTests`, `CodingPathContractTests`,
`EnigmaEncodingContractTests`, or `SerializationContractTests` by behavior.
Run the affected class, then `AGENTS.md` checks. Read the relevant section of
[Serialization.md](../../../Sources/Enigmatic/Enigmatic.docc/Serialization.md)
for recovery or bridge details.
34 changes: 34 additions & 0 deletions .agents/skills/enigmatic-codecs/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
name: enigmatic-codecs
description: Add, change, or review Enigmatic Codec strategies, Box/OptionalBox wrappers, collection composition, Either, and Each.
---

# Codec strategies and wrappers

Paths here are relative to the repository root. Locate the strategy in
`Sources/Enigmatic/Public/Codec`; read `Codec.swift` only when protocol
relationships matter. Optional keyed behavior also lives in
`Sources/Enigmatic/Public/Extensions/Keyed{Encoding,Decoding}Container.swift`.

Preserve these contracts unless the user requests a behavior change:

- Keep decoding and encoding capabilities separate. Optional strategies expose
distinct present-payload operations; keyed optional boxes omit nil keys and
decode missing or null as nil. Test wrappers through synthesized Codable.
- `Either` tries Right first, then Left; both failures remain in CompositeError
in attempt order. Test fallback after a partial read.
- `Each` writes components to the same encoder. Disjoint keyed components
combine; overlapping keys, repeated scalars, and repeated unkeyed containers
conflict, including empty containers. It does not recursively merge.
- Collection strategies transform elements. Set output order is unspecified.
`Id<Date/Data>` calls Foundation Codable directly rather than handling native
Enigma date/data nodes.
- Integer date strategies truncate toward zero and can lose round-trip precision.
Reject non-finite arithmetic, invalid scale factors, and integer overflow.
Preserve availability on generic Unix strategies and older named alternatives.

Extend `StrategyContractTests`; product composition also uses `ProductTests.swift`
(test class `ContainersTests`). Run the affected class, then `AGENTS.md` checks.
Consult [CodingStrategies.md](../../../Sources/Enigmatic/Enigmatic.docc/CodingStrategies.md)
for representation choices and compatibility. Keep user-facing examples aligned
with `DocumentationExamplesTests`.
34 changes: 34 additions & 0 deletions .agents/skills/enigmatic-numbers/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
name: enigmatic-numbers
description: Change or review Enigma numeric identity, typed number accessors, Float/Double conversion, and Int128/UInt128 support.
---

# Enigma numeric contracts

Paths here are relative to the repository root. Start with the affected accessor
in `Sources/Enigmatic/Public/Enigma/Capabilities/Enigma+Conversion.swift` or
equality in `Sources/Enigmatic/Public/Enigma/Enigma.swift`. Follow numeric helpers
in `Sources/Enigmatic/Internal/Extensions/Enigma+Comparison.swift` and
`Double.swift`; inspect `Public/Enigma/Primitives/Enigma+*128Box.swift` under the
same library root only for 128-bit work.

Preserve these contracts unless the user requests a behavior change:

- Integer storage widths do not change numeric equality. Compare exact values
without routing large integers through lossy Double conversion. Enigma treats
NaNs as equal and signed zeros as equal; it has no Hashable conformance.
- Float inputs widen to Double with their binary value intact; Float(0.1) is not
the same stored value as Double(0.1).
- Integer accessors require exact, in-range values. `asDouble` requires exact
integer representability. `asFloat` first requires that same Double conversion
for integer inputs, then rounds; reject finite overflow and nonzero underflow
to zero, while preserving NaN and infinity.
- Keep 128-bit availability guards and box value semantics. Copy mutation must
not affect the original box.

Extend `NumericContractTests` or `EquatableTests` with the relevant range or
identity boundary. For box bridging, also inspect `SerializationContractTests`.
Run the affected class with `swift test --filter <TestClass>`, then `AGENTS.md`
checks. Consult the numeric section of
[Serialization.md](../../../Sources/Enigmatic/Enigmatic.docc/Serialization.md)
for conversion examples.
33 changes: 33 additions & 0 deletions .agents/skills/enigmatic-tree/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
name: enigmatic-tree
description: Change or review Enigma path lookup, tree mutation, allPaths traversal, and merge behavior in Enigmatic.
---

# Enigma tree operations

Paths here are relative to the repository root. Locate the affected method in
`Sources/Enigmatic/Public/Enigma/Capabilities/Enigma+Modification.swift` or
`Enigma+Inspection.swift`; follow it into
`Sources/Enigmatic/Internal/Extensions/Enigma+Utility.swift` or
`Sources/Enigmatic/Internal/Primitives/Enigma+*MergeStrategy.swift` as needed.

Preserve these contracts unless the user requests a behavior change:

- An empty path selects the root: it can replace but cannot delete it. Child
assignment of nil deletes; `.null` stores null. Reads never coerce containers.
- Non-nil writes create or replace containers to match pins. Array writes append
only at count. Any invalid index makes the entire write an atomic no-op;
deletion never creates containers. Preserve independent copies.
- `or:` evaluates its fallback only for a missing read, including read-modify-write;
stored null and simple assignment do not evaluate it.
- `allPaths` excludes the root, includes empty descendants, and walks depth first
with sorted dictionary keys and ascending array indices.
- Dictionary pairs merge recursively. Policy merges handle array pairs using
`arrayAction`; `.zip` recurses by index and retains the longer tail. Throwing
merges pass other pairs whole to the resolver; new keys bypass it. Failures
leave the original intact. Dictionary resolver order is unspecified.

Extend `TreeContractTests` for the affected boundary; `OperationsTests` covers
basic usage. Run `swift test --filter TreeContractTests`, then the shared checks
in `AGENTS.md`. For detailed semantics, read
[TreeOperations.md](../../../Sources/Enigmatic/Enigmatic.docc/TreeOperations.md).
32 changes: 32 additions & 0 deletions .github/workflows/benchmarks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Benchmarks

on:
workflow_dispatch:

permissions:
contents: read

concurrency:
group: benchmarks-${{ github.ref }}
cancel-in-progress: true

jobs:
benchmarks:
runs-on: macos-26
env:
DEVELOPER_DIR: /Applications/Xcode_26.6.app/Contents/Developer
steps:
- uses: actions/checkout@v6
- name: Verify Swift 6.3.3
run: |
swift --version
swift --version | grep -Eq 'Swift version 6\.3\.3([[:space:]]|$)'
- name: Release benchmarks without instrumentation
shell: bash
run: |
set -o pipefail
swift test -c release --filter PerformanceTests 2>&1 | tee benchmarks.log
- uses: actions/upload-artifact@v6
with:
name: benchmarks
path: benchmarks.log
82 changes: 82 additions & 0 deletions .github/workflows/checks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
name: Checks

on:
push:
branches: [main]
workflow_dispatch:

permissions:
contents: read

concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
tests:
name: ${{ matrix.os }} / ${{ matrix.configuration }}
runs-on: ${{ matrix.os }}
container: ${{ matrix.container }}
strategy:
fail-fast: false
matrix:
os: [macos-26, ubuntu-24.04]
configuration: [debug, release]
include:
- os: ubuntu-24.04
container: swift:6.3.3
steps:
- uses: actions/checkout@v6
- name: Select Xcode 26.6
if: runner.os == 'macOS'
run: echo 'DEVELOPER_DIR=/Applications/Xcode_26.6.app/Contents/Developer' >> "$GITHUB_ENV"
- name: Verify Swift 6.3.3
run: |
swift --version
swift --version | grep -Eq 'Swift version 6\.3\.3([[:space:]]|$)'
- name: Functional tests
run: swift test -c ${{ matrix.configuration }} --skip PerformanceTests
- name: Coverage gate tests
if: matrix.os == 'macos-26' && matrix.configuration == 'debug'
run: python3 -m unittest discover -s Scripts/tests
- name: Coverage
if: matrix.os == 'macos-26' && matrix.configuration == 'debug'
run: |
swift test --enable-code-coverage --skip PerformanceTests
cp "$(swift test --show-codecov-path)" coverage.json
python3 Scripts/check-coverage.py coverage.json --minimum 95
- name: Upload coverage
if: always() && matrix.os == 'macos-26' && matrix.configuration == 'debug' && hashFiles('coverage.json') != ''
uses: actions/upload-artifact@v6
with:
name: coverage
path: coverage.json
if-no-files-found: error
- name: Build documentation
if: matrix.os == 'macos-26' && matrix.configuration == 'debug'
run: |
swift package dump-symbol-graph --minimum-access-level public
enigmatic_symbols="$(dirname "$(swift build --show-bin-path)")/symbolgraph"
mkdir -p .build/Enigmatic.symbolgraph
cp "$enigmatic_symbols/Enigmatic.symbols.json" .build/Enigmatic.symbolgraph/
for graph in "$enigmatic_symbols"/Enigmatic@*.symbols.json; do
[ -f "$graph" ] || continue
cp "$graph" .build/Enigmatic.symbolgraph/
done
xcrun docc convert Sources/Enigmatic/Enigmatic.docc \
--additional-symbol-graph-dir .build/Enigmatic.symbolgraph \
--output-path .build/Enigmatic.doccarchive \
--transform-for-static-hosting \
--hosting-base-path Enigmatic \
--warnings-as-errors
- name: Pack documentation
if: matrix.os == 'macos-26' && matrix.configuration == 'debug'
run: tar -czf Enigmatic.doccarchive.tar.gz -C .build Enigmatic.doccarchive
- name: Upload documentation
if: matrix.os == 'macos-26' && matrix.configuration == 'debug'
uses: actions/upload-artifact@v6
with:
name: documentation
path: Enigmatic.doccarchive.tar.gz
compression-level: 0
if-no-files-found: error
Loading