Replace the custom encrypted container with AgeSwift 0.1.0 so standard
age tools can inspect sensitive configuration independently of the app.
Use independent Keychain X25519 identities for catalog.age and
proxy-listening.age. Preserve atomic commits and confirmed recovery;
reject historical NG2 formats without migration or cleanup.
Six sites re-asserted the predicate waitUntilRuntimeSettles already checks,
with no suspension point in between, so they could never fail; their intent
messages are folded into comments where one was not already stated.
Two commit-failure cases asserted the fake's bookkeeping (updateCalls stays
empty) which the fake guarantees by throwing before recording; the outcome
and committed-snapshot assertions already prove the real behavior.
Also drop a no-op loop that mutated a discarded struct copy, a duplicated
isWellFormed line, two WorkspaceRoute cases subsumed by the constructor and
the publish-count case, a duplicated presentation-message assertion, and the
round-trip halves of two payload-shape cases already covered case-by-case.
Co-Authored-By: DeepSeek Harness <noreply@deepseek.com>
Each removed assertion holds by construction and can never fail:
- jsonData() compared with itself cannot detect cross-run byte stability;
bindAddress and mode are literal-returning computed properties
- RuleAction/RuleSourceKind allCases assertions pin synthesized enum order
(neither allCases list is used in production); the persisted action tokens
stay pinned by the kept rawValue assertions and source-kind tokens by
fixture decoding through RuleSnapshotStore
- memberwise-constructor echo in RuleSourceIdentity, fixture-guaranteed
name == id rows, a share draft field pair built from one string, and a
local struct compared to its own assignment
- the synthesized-Codable round trip through literal JSONEncoder/JSONDecoder
The duplicate-import assertion becomes a real check: Set of node ids instead
of a count that restated roots.count, which is what its comment claims.
Co-Authored-By: DeepSeek Harness <noreply@deepseek.com>
Every case here restates a rule another test already pins with the same or a
wider input class:
- the activation group case is byte-identical to its neighbour, minus an extra
assertion; the rule snapshot version guard is re-driven with a second value
of the same schemaVersion check; the global-mode deployment-failure case is
a mode-literal copy of the strictly stronger direct-mode one; the clear-
failure case duplicates the deferred-retry sibling
- two RuntimeDocument projection cases only re-map locals, already asserted as
full array equality; the IPv6-LAN endpoint case repeats the direct-mode case
(the derivation reads only ports)
- the three HTTP export cases varied only listenerMode while the derivation
ignores it and one name contradicted its own expectation; one loop over all
listener modes now states the real rule
- the 0700/0600 permission baseline is one AtomicFileWriter behavior and stays
pinned through RuntimeFileStoreTests, which also covers self-heal and atomic
replace
The command-boundary case keeps its mixed-scenario isolation check (four
commands, four independent adapter counters) and drops only its unfalsifiable
queriedTargetIDs claim.
Co-Authored-By: DeepSeek Harness <noreply@deepseek.com>
Three tests claimed coverage they could not deliver:
- subscription URL credential cleanup asserted a lookup derived from the
already-empty subscription list, so it held even on a leak; production has
no separate URL credential store (SubscriptionRecord.url is a plain field)
- the runtime log event sweep planted no secret values, so its secret half
could never fail; keep the live JSON-dump check and rename the test to match
- clipboard and QR saver tests exercised only in-memory doubles that live in
production source and have no other caller; delete the six tests and the
three doubles (AppKit adapters stay untested, as before)
Co-Authored-By: DeepSeek Harness <noreply@deepseek.com>
Ancestor groups of the active target now show a hollow bolt beside the
existing filled bolt on the target itself, in the servers tree, the
favorites table and the home target browser; the node detail subtitle
shows "含活动目标". The derivation lives in
CatalogTreeSnapshot.ancestors(of:) so every surface shares one rule
while activeTargetID stays a runtime fact outside the catalog
projection. Groups activated directly keep the filled bolt and leave
their member rows unmarked.
Use native Table row and insertion callbacks instead of an outer drop
receiver. Resolve server rows and insertion lines to their containing
group, and root insertion points to the catalog root.
Verify insertion and server-row targets with regression tests.
CatalogEntry gains createdAt/updatedAt and the catalog document moves to
v5 (reads v1-v5, writes v5). Modification time is structure-sensitive:
editing a node's own fields bumps the node, a group's direct child set
or order changes bump the group, and a moved node keeps its timestamps.
No-op writes and unchanged subscription refreshes bump nothing; the
refresh rebuild compares per node, so surviving leaves keep theirs. All
times are passed in by callers as now: Date - one moment per logical
commit, the domain layer stays clock-free. Legacy documents load with
nil (unknown, never backfilled); duplicates and imports stamp fresh
times at the moment of the operation.
Semantics are recorded as glossary term 节点时间戳 and ADR 0031. No UI
in this change.