Releases: DraconDev/dracon-utilities
Release list
v0.113.54 — freeze watchdog
Release Notes — v0.113.54 (2026-08-24)
Freeze fix. A manual dracon-sync pause at 17:26 left the fleet frozen for 3.5 h (14 repos 🟣 PENDING, 2 🟡 WARN). The hard TTL was 24 h so nothing would have auto-cleared until the next day.
Fixed
- Daemon hard TTL 24 h → 1 h (
dracon-sync/src/policy.rs) plus a newdracon-freeze-watchdogtimer (every 2 m): warns at 10 m, auto-clears a stale~/.dracon/dracon-sync.freezeat 30 m (daemon hard-clears at 1 h).AGENTS.mdupdated to steer operators towarddracon-sync maintenance -- <cmd>(always resumes). - Monorepo test fix:
github_pack_testsnow walks up to the enclosing git top-level, sosmall_repo_is_not_too_big_for_githubno longer reports size 0 after the monorepo conversion.
How to verify
git clone https://github.com/DraconDev/dracon-utilities.git
cd dracon-utilities
cargo test --workspace --locked
cargo build --release --locked
./target/release/dracon-sync --version # 0.113.54
systemctl --user status dracon-freeze-watchdog.timer
journalctl --user -u dracon-freeze-watchdog.service --since "1 hour ago"v0.113.53 — first monorepo release
Release Notes — v0.113.53 (2026-08-22)
First monorepo release. The three utilities — dracon-sync,
dracon-system, dracon-warden — now live in this repository as real
source trees; the historical standalone repos are frozen mirrors.
[0.113.53] - 2026-08-22
Changed
- Full monorepo conversion: the three utilities now LIVE in this
repo (dracon-sync/,dracon-system/,dracon-warden/as real
tracked source trees, imported via subtree merges so history stays
connected). GitHub shows browsable code; CI builds from a single
checkout; the Nix flake dropped its three-srcinputs.
The standalone GitHub repos become frozen mirrors. Utility releases
are tagged on this repo going forward. (Same-day submodule
registration superseded; gitdir bundles archived under
~/dracon/backups/submodule-gitdirs-20260822/.) - Utilities are now git submodules (superseded same day by the
monorepo conversion):dracon-sync,dracon-system,
dracon-wardenwere registered in.gitmodules; gitdirs absorbed
into.git/modules/.
Added
- Daily fleet git-identity guard (
scripts/check-repo-identities.py,
wired into the daily timer): fails on any repo whose effective git
identity is neither canonical DraconDev nor its deliberate loop
identity — prevention for the 2026-08-22 dracon-platform local-
override bug that mis-attributed ~1000/day auto-commits. - dracon-warden v0.113.5 local release candidate (2026-08-19): machine-local
hygiene defaults documented across standalone and meta repositories, locked
release artifact built and installed. Registry publication, tags, and forge
releases remain explicit operator-approved steps.
Fixed
- Operations documentation now matches dracon-system v0.112.36: the
process-mitigation section documents renice, OOM-score bias, and optional
CPUQuota throttling, and no longer misstatesdracon-system guard clean
as a process-adjustment rollback command;guard cleanis documented as
reclaimable-space cleanup with dry-run/apply semantics. - audit scripts now honour glob patterns in
exclude_dir_names(audit
LOW, 2026-08-10):scripts/audit-commit-activity.pyand
scripts/verify-ownership-mirrors.pyfilteredos.walkdirectories by
exact set membership, but the live config contains the glob.tmp-*—
it never matched, so.tmp-*dirs were scanned by both scripts. The
directory filter now matches eachexclude_dir_namesentry with
fnmatch(glob); entries without metacharacters still match exactly.
Verified with a fixture tree:.tmp-scratch/.tmp-a/node_modules
pruned, plain repos still discovered.
What shipped in the utilities
- dracon-sync 0.113.53: watched-repo-vanished CONCERN detection
(src/vanished.rs), coldreposrender 42s -> 14s via
spawn_blocking, probe-timeout false-BROKEN fix with bounded retry. - dracon-system 0.112.38: active-build detection before cleanup,
protected-path fixes. - dracon-warden 0.113.5 (release candidate): machine-local hygiene
defaults; registry publication remains an explicit operator step.
How to verify
git clone https://github.com/DraconDev/dracon-utilities.git
cd dracon-utilities
cargo test --workspace --locked
cargo build --release --locked
./target/release/dracon-sync --version # 0.113.53v0.112.12
Release Notes — v0.112.12 (2026-06-21)
Auto-generated by
scripts/release.sh. Review the body, add a
headline, and edit the section before publishing.
[0.112.12] - 2026-06-21
Fixed
- dracon-code PUSH_STUCK (44 consecutive failures, 3h+) — resolved (goal
fc406135/ 2026-06-16): The operator sawdracon-codein PUSH_STUCK in the daemon'sreposoutput. Investigation found a true divergence: local was 10 commits ahead of gitlab/codeberg, but gitlab/codeberg had 1 commit (74c183107d, the TUI brainstorm doc) not in local. The daemon'sforce_push_when_behind = trueconfig (from goal87c1bf4d) only handles the "remote behind local" case, not true divergence. Resolution: chose Option A (merge remote into local, then push to all 4 remotes). 3 conflicts resolved by taking HEAD (local has more recent TUI work). All 4 remotes now aligned ate53c4bd79. PUSH_STUCK state cleared. No data loss. New design docdocs/design/dracon-code-divergence-2026-06-16.mdcaptures the root cause, the resolution strategy, and a runbook for future PUSH_STUCK events. Option C (pull_when_remote_ahead = truedaemon config) is deferred to a future daemon release.
Changed
- Global
untracked_exclude_patterns = [](2026-06-17): the operator's position is "global rule, default = commit everything, unless something would be very wrong to put on the repo". The previous list (11 patterns:**/scratch/**,**/tmp/**,**/pi-tmp/**,**/.pi-tmp/**,**/research/scratch/**,.demon/**,.sisyphus/**,.ralph/**, plus the per-prefix variants) conflated "short-lived" with "very wrong to commit". They are not the same thing. Short-lived files are valid git content: the user/agent canrmthem from the working tree when they're done, and the daemon will commit the deletion. If the user wants to recover, the file is in git history. Things that ARE very wrong to commit (secrets, files > 100 MiB, build artifacts) are handled elsewhere (warden encryption,max_stage_file_bytes,.gitignore).AGENTS.mdupdated with the new policy + operator's verbatim framing. Design doc:docs/design/pi-tmp-persist-policy-2026-06-16.md.
How to verify
cargo install --locked dracon-sync@0.112.12
dracon-sync reposSee also
CHANGELOG.md— full historydocs/design/— design docs referenced in this release
v0.112.11 — push_op_timeout_secs = 300
Release Notes — v0.112.11 (2026-06-17)
Headline: the daemon's
push_op_timeout_secsis raised from
60to300to match the daemon's own code default. The 60s
value was an operator override that caused PUSH_STUCK during
the v0.112.10 release when a 23-file PNG-heavy commit in
dracon-platformcouldn't push to gitlab/codeberg.
What changed
push_op_timeout_secs = 300 (was 60)
The operator's config had push_op_timeout_secs = 60, an
override-down from the daemon's code default of 300s. During
v0.112.10, this 60s cap was too tight: a 23-file commit in
dracon-platform (mostly game-dev smoke-out PNG binaries)
timed out at 60s for both gitlab and codeberg, requiring
manual timeout 300 git push --no-verify to clear the
PUSH_STUCK state.
The fix is to align with the daemon's own default:
- push_op_timeout_secs = 60
+ push_op_timeout_secs = 300
+ # CHANGED 2026-06-17: see docs/design/push-timeout-fix-2026-06-17.md300s gives a 5x safety margin over the v0.112.10 measured
60s push time. It's wasteful for github (which never takes
more than a few seconds) but harmless — the daemon times out
via process kill, not via waiting.
Why not per-remote timeouts?
The proper fix is per-remote timeouts (60s for github, 300s
for gitlab/codeberg, like force_push_when_behind from
goal 87c1bf4d). This would require:
- Adding
push_op_timeout_secs: Option<u64>to the daemon's
RemoteConfigstruct - Plumbing it through
push_to_named_remote()in
git/multi_remote.rs - Rebuilding the daemon
- Releasing the daemon as a new version
This is a daemon release, not a utilities release. It's
deferred to a follow-up. The utilities-only fix (single
global 300s) is good enough for now.
Measured push duration data (2026-06-17 01:05 UTC)
| Commit size | github | gitlab | codeberg | origin |
|---|---|---|---|---|
| Small (5 files, no binaries) | ~1.2s | instant | ~1.3s | ~7.7s |
| Stress test (61 files, 1.5MB PNGs) | 2.35s | 2.57s | 10.51s | 0.64s |
All 4 remotes handle a 61-file / 1.5MB stress test well under
the 300s budget. The slowest (codeberg at 10.51s) is 28x
under the timeout. The v0.112.10 incident was likely
network-related (slow connection at that moment), not
capacity-related.
Files changed
~/.dracon/utilities/sync/dracon-sync.toml:push_op_timeout_secs
changed from60to300with extensive commentAGENTS.md: added "Push timeouts" sectionCHANGELOG.md: this entrydocs/design/push-timeout-fix-2026-06-17.md(8,730 bytes):
the full design doc with measured data, rationale, and runbookrelease-notes-v0.112.11.md(this file)
Verification
- All 12 daemon-watched repos are ✅ OK + 🟢 synced + healthy
- 4-remote alignment verified for monorepo
cargo build --release --lockedsucceeds (5 pre-existing
warnings, no new)cargo test --workspace --lockedexpected: 856 passed,
0 failed, 9 ignored (no regression)- Stress test (61 files / 1.5MB PNGs) pushes to all 4
remotes in 0.6-10.5s, well under the new 300s budget
Sub-crate versions
dracon-sync: 0.1.11 → 0.1.12dracon-system: 0.2.6 → 0.2.7dracon-warden: 0.3.6 → 0.3.7
All 3 sub-crates will be re-published to crates.io as v0.1.12,
v0.2.7, v0.3.7 immediately after this release. (No code
change — same source, new version metadata.)
Follow-up (deferred)
Per-remote push_op_timeout_secs support in the daemon.
Requires:
- Add
push_op_timeout_secs: Option<u64>toRemoteConfig - Plumb through
push_to_named_remote() - Rebuild + release the daemon
This is a separate daemon release. Tracked as a follow-up goal.
v0.112.10 — global untracked_exclude_patterns = []
Release Notes — v0.112.10 (2026-06-17)
Headline: the daemon now commits EVERYTHING untracked by default.
Theuntracked_exclude_patternslist is empty. Short-lived files
(.pi-tmp/,scratch/,tmp/,.demon/,.sisyphus/,.ralph/)
are valid git content — the user/agent manually deletes them when
they're done.
What changed
Policy: global untracked_exclude_patterns = []
The operator's framing (lightly cleaned up):
"the most sensible thing is that we have a global rule, and unless
it's something that would be very wrong to put on the repo we put
it there. i think all untracked excludes arguably are wrong. just
because they are short lived files doesn't mean we shouldn't put
them there."
The previous list of 11 patterns conflated "short-lived" with "very
wrong to commit". They are not the same thing. The new policy:
DEFAULT BEHAVIOR:
The daemon commits ALL untracked files by default.
THE ONLY THINGS IT REFUSES TO COMMIT:
1. Files > 100 MiB (max_stage_file_bytes = 104857600)
2. Things git already ignores (.gitignore rules)
3. Per-repo opt-outs (only when a specific repo sets
untracked_exclude_patterns in its .dracon/dracon-sync.toml)
NOT REFUSED (despite being short-lived):
.pi-tmp/ scratch/ tmp/
.demon/ .sisyphus/ .ralph/
Why this matters
- Disaster recovery: a 10-minute audit that you accidentally
delete from the working tree is still in git history. - Cross-machine sync: the 4-remote push now carries ALL your
work, not just the "important" files. - No more "UT pile-up": the daemon's
untrackedcount drops
to 0 for repos with no.gitignoreor >100 MiB files. The
"untracked-only" state in the daemon'srepostable disappears. - User-controlled cleanup: when the user is done with a
.pi-tmp/directory, theyrm -rfit. The daemon commits the
deletion. If they want it back, it's in git.
What is NOT changed
auto_commit = true(was already on)max_stage_file_bytes = 104857600(100 MiB cap unchanged).gitignorerules (unchanged — build artifacts still ignored)- Warden's pre-commit hook (still scans all staged content for
secret patterns; encrypts-or-blocks) - Per-repo
.dracon/dracon-sync.tomloverride mechanism (now
reserved for repos that need to opt back INTO excluding
something)
Files changed
~/.dracon/utilities/sync/dracon-sync.toml:untracked_exclude_patterns
changed from 11 patterns to[](with extensive comment explaining why)AGENTS.md: commit policy section rewritten with the new framingCHANGELOG.md: this entrydocs/design/pi-tmp-persist-policy-2026-06-16.md: rewritten to
reflect the global change (was per-repo pilot, now fleet-wide)
Verification
- All 12 daemon-watched repos are ✅ OK + 🟢 synced + healthy
- 4-remote alignment verified for
.dracon,dracon-utilities,
dracon-platform cargo build --release --lockedsucceeds (5 pre-existing warnings,
no new ones)cargo test --workspace --lockedexpected: 856 passed, 0 failed,
9 ignored (no regression)
Sub-crate versions
dracon-sync: 0.1.10 → 0.1.11dracon-system: 0.2.5 → 0.2.6dracon-warden: 0.3.5 → 0.3.6
All 3 sub-crates will be re-published to crates.io as v0.1.11, v0.2.6,
v0.3.6 immediately after this release. (No code change — same source,
new version metadata.)
Follow-up
The 60s push_op_timeout_secs is a pre-existing limitation surfaced
during this work (game-dev smoke-out PNG commits can take >60s to push
to gitlab/codeberg). Deferred to a separate goal.
Release v0.112.9
Release v0.112.9 — 2026-06-16
Summary
This release packages the crates.io publish of the 3 sub-crates
(dracon-sync v0.1.9, dracon-system v0.2.4, dracon-warden v0.3.4),
a final audit of the workspace state, and updates to documentation
that was stale by 1-3 releases.
This is in direct response to the operator's feedback: "ok we are looking
good lets do a na audit update docs and push releases if need to, also
release on crates too".
What's published on crates.io (NEW!)
The 3 sub-crates are now available on crates.io:
| Crate | Version | crates.io |
|---|---|---|
dracon-sync |
0.1.9 | https://crates.io/crates/dracon-sync |
dracon-system |
0.2.4 | https://crates.io/crates/dracon-system |
dracon-warden |
0.3.4 | https://crates.io/crates/dracon-warden |
Users can now install any of the 3 utilities with a single command:
cargo install dracon-sync # Background git sync daemon
cargo install dracon-system # Disk, process, guard, doctor
cargo install dracon-warden # Secret, encrypt, age, git-filterdocs.rs pages are auto-generated by crates.io on publish:
Final audit results
The complete audit of the workspace (30 design docs + 7 READMEs + source
comments) is captured in docs/design/final-audit-2026-06-16.md.
10 findings, all fixed:
| # | Finding | Status |
|---|---|---|
| 1 | Root README stated v0.112.5 (stale by 3 releases) | ✓ FIXED |
| 2 | Root README described façade repos as navigation shells (stale) | ✓ FIXED |
| 3 | Root README had no crates.io install path | ✓ FIXED |
| 4 | Per-utility READMEs had no "Install via crates.io" section | ✓ FIXED (3 files) |
| 5 | 3 sub-crate Cargo.toml files were missing keywords and categories |
✓ FIXED (3 files) |
| 6 | documentation URLs in 3 sub-crate Cargo.toml files pointed to old versions |
✓ FIXED (3 files) |
| 7 | 3 sub-crates not published to crates.io at the v0.112.x versions | ✓ FIXED (3 published) |
| 8 | path dep was a perceived blocker for dracon-warden publish |
✓ RESOLVED (false positive) |
| 9 | Crates.io 5-keyword limit (caught at first publish) | ✓ FIXED |
| 10 | No design doc explaining the crates.io publish process | ✓ FIXED (new doc) |
What's in the box (since v0.112.8)
docs/design/final-audit-2026-06-16.md(10,161 bytes) — the final
audit findings + resolutionsdocs/design/crates-io-publish-2026-06-16.md(9,244 bytes) — the
crates.io publish workflow + lessons learned- 3 sub-crates published to crates.io (with keywords, categories, and
updated documentation URLs) - Root README updated — v0.112.8 release link, 4-repo architecture
reflects v0.112.7 state, "Install" section withcargo installpaths - 3 per-utility READMEs updated — each has an "Install" section near
the top withcargo install <crate>and the façade repo alternative - CHANGELOG
[Unreleased] / Addedentry for the crates.io publish - Version bumps: root 0.112.8 → 0.112.9, sync 0.1.9 → 0.1.10,
system 0.2.4 → 0.2.5, warden 0.3.4 → 0.3.5
Verification
| Check | Result |
|---|---|
cargo search dracon-sync |
✓ shows 0.1.9 |
cargo search dracon-system |
✓ shows 0.2.4 |
cargo search dracon-warden |
✓ shows 0.3.4 |
cargo install dracon-sync + run |
✓ prints "dracon-sync 0.1.9" |
cargo install dracon-system + run |
✓ prints "dracon-system 0.2.4" |
cargo install dracon-warden + run |
✓ prints "dracon-warden 0.3.4" |
cargo build --release --locked (monorepo) |
✓ |
cargo test --workspace --locked (monorepo) |
✓ 856 passed, 0 failed, 9 ignored |
| 4-remote alignment | ✓ all 4 watched repos at 1 unique SHA |
No secrets leaked (token in ~/.cargo/credentials.toml only) |
✓ |
Constraints honored
- No force-pushes, no user-owned repo changes (kiki-sassy, one-mil-girls),
no auto-commit secrets, nogit add ., no history rewrites - The 3 long-name façade repos stay 4-remote aligned
- The 3 GitLab Set A repos in
_deletion_scheduledstate remain
untouched (default A=leave-as-is from goal83e42c15) - The post-commit hook +
regenerate_facade_repos.pyare the canonical
auto-sync mechanism - The crates.io token is in
~/.cargo/credentials.tomlonly (mode 0600);
never logged, never committed
What's next
- The 3 sub-crates are now on crates.io. Future releases should include
cargo publishas a step in the release process. - The 3 GitLab Set A repos in
_deletion_scheduledstate will be
hard-deleted by GitLab automatically. The operator can override to
B/C/Dper repo at any time per goal83e42c15. - The 3 long-name façade repos stay in sync with the monorepo via the
post-commithook + daemon auto-push (unchanged from v0.112.5).
Release v0.112.8
Release v0.112.8 — 2026-06-16
Summary
This release is a push-targets audit that confirms the daemon and the
auto-sync mechanism only target the 3 long-name façade repos + the monorepo.
The Set A short-name repos (renamed in place on GitHub, hard-deleted on
Codeberg, in _deletion_scheduled state on GitLab) are explicitly ignored.
This is in direct response to the operator's feedback: "but make sure we are
ignoring the previous ones now we are just directly pushing to the ones we
marely with the long names right?" — Yes, confirmed: the daemon pushes only
to the 3 long-name façade repos + the monorepo.
What was audited (and confirmed clean)
| Check | Result |
|---|---|
| Daemon watch list = 4 long-name repos (1 monorepo + 3 façade repos) | ✓ |
| No Set A URL in any local clone's remotes | ✓ |
| No Set A URL in any active config/script/code | ✓ |
No local clone points to a _deletion_scheduled URL |
✓ |
Auto-sync mechanism (post-commit hook + regenerate_facade_repos.py) only targets long-name clones |
✓ |
| All 4 watched repos are 4-remote aligned (github, gitlab, codeberg) | ✓ |
| Monorepo tests: 856 passed, 0 failed, 9 ignored | ✓ |
The 4 canonical push targets
| # | Repo | Local path | Push targets |
|---|---|---|---|
| 1 | dracon-utilities |
/home/dracon/Dev/dracon-utilities |
origin (github), github, gitlab, codeberg |
| 2 | dracon-sync-background-auto-commit-multi-remote |
/home/dracon/Dev/facade-repos/dracon-sync-background-auto-commit-multi-remote |
origin (github), github, gitlab, codeberg |
| 3 | dracon-system-disk-process-guard-doctor |
/home/dracon/Dev/facade-repos/dracon-system-disk-process-guard-doctor |
origin (github), github, gitlab, codeberg |
| 4 | dracon-warden-secret-encrypt-age-git-filter |
/home/dracon/Dev/facade-repos/dracon-warden-secret-encrypt-age-git-filter |
origin (github), github, gitlab, codeberg |
All 14 URLs across the 4 repos are long-name URLs. No Set A short-name URL
is the target of any push, by any mechanism (daemon, post-commit hook,
scaffold script, or any other code path).
What is explicitly ignored (carve-out)
The 3 Set A repos on GitLab in _deletion_scheduled state are explicitly
ignored:
DraconDev/dracon-sync-watch-debounce-commit-push-mirror-deletion_scheduled-83426810DraconDev/dracon-system-disk-zram-process-service-guard-deletion_scheduled-83426812DraconDev/dracon-warden-age-git-filter-secret-encrypt-deletion_scheduled-83426814
These are in GitLab's soft-delete state and will be hard-deleted by GitLab
automatically. The default of A (leave-as-is) was applied per goal
83e42c15; the operator can override to B (hard-delete now), C
(archive + rename to -deprecated), or D (deprecated README + archive)
per repo at any time.
Historical references (carve-out)
Set A short-name URLs appear in 3 historical documents that document the
Set A → Set B rename event as history. These are NOT active references:
CHANGELOG.md(multiple entries documenting the rename)docs/design/github-feature-repos.md(section comparing Set A vs Set B names)release-notes-v0.112.5.md(release notes documenting the rename as part of v0.112.5)
These references are not loaded by the daemon or any sync code, and exist
solely to explain the rename. They are explicitly carved out from the
"no Set A URL" rule.
Version bumps
- Root workspace:
0.112.7→0.112.8(patch-level, audit only) dracon-sync:0.1.8→0.1.9dracon-system:0.2.3→0.2.4dracon-warden:0.3.3→0.3.4
What's in the box (since v0.112.7)
docs/design/push-targets-audit-2026-06-16.md(new design doc with the
full audit results)CHANGELOG.md [0.112.8] / Investigatedentry documenting the audit- Version bumps (no code changes)
What's next
- The 3 GitLab Set A repos in
_deletion_scheduledstate will be hard-deleted
by GitLab automatically. The operator can override toB/C/Dper repo
at any time per goal83e42c15; a follow-up release will cut on request. - The daemon continues to auto-push monorepo + 3 façade repos on all 4
remotes (post-commit hook + daemon sync is operational).
Release v0.112.7
Release v0.112.7 — 2026-06-16
Summary
This release flips the architecture of the 3 long-name façade repos. They
were navigation shells (7 files of metadata that pointed to the monorepo); they
are now real install targets with the actual source code, a standalone
Cargo.toml, tests, examples, and the per-utility README. This is in direct
response to the operator's feedback: "are they mains? we are not pushing to
them they are still shells".
Standalone install (the new flow)
The 3 long-name façade repos are now the canonical install targets for
each utility. A user can clone any one of them and build it without cloning
the monorepo first.
dracon-sync-background-auto-commit-multi-remote
git clone https://github.com/DraconDev/dracon-sync-background-auto-commit-multi-remote.git
cd dracon-sync-background-auto-commit-multi-remote
git clone https://github.com/DraconDev/dracon-libs.git ../dracon-libs
cargo build --release
# target/release/dracon-sync is ready to installdracon-system-disk-process-guard-doctor
git clone https://github.com/DraconDev/dracon-system-disk-process-guard-doctor.git
cd dracon-system-disk-process-guard-doctor
git clone https://github.com/DraconDev/dracon-libs.git ../dracon-libs
cargo build --release
# target/release/dracon-system is ready to installdracon-warden-secret-encrypt-age-git-filter
git clone https://github.com/DraconDev/dracon-warden-secret-encrypt-age-git-filter.git
cd dracon-warden-secret-encrypt-age-git-filter
git clone https://github.com/DraconDev/dracon-libs.git ../dracon-libs
git clone https://github.com/DraconDev/dracon-utilities.git ../dracon-utilities
cargo build --release
# target/release/dracon-warden is ready to install
# (the monorepo is needed for the `dracon-security` kit in src/security)What changed (architecture inversion)
| Before (v0.112.6) | After (v0.112.7) |
|---|---|
| Façade repos had 7 metadata files only | Façade repos have 25-50 files including source |
| Source code lived only in the monorepo | Source code lives in both (mirrored one-way) |
Cargo.toml did not exist in the façade |
Cargo.toml exists, with path-dep siblings |
| README pointed to the monorepo for source | README has sibling-clone instructions + standalone build |
| The façade was a "navigation surface" | The façade is a "real install target" |
| "The monorepo is the only source of truth" | "The monorepo is the source of truth; the façade is a mirror" |
Auto-sync mechanism (unchanged from v0.112.5)
The monorepo's post-commit hook calls scripts/regenerate_facade_repos.py
which detects which utility's source files changed and re-mirrors the content
to the corresponding façade repo. The dracon-sync daemon picks up the local
change in /home/dracon/Dev/facade-repos/<name> and auto-pushes to the 3
remotes (github, gitlab, codeberg). The flow is one-way: monorepo → façade.
File counts (post-conversion)
| Repo | Before | After |
|---|---|---|
dracon-sync-background-auto-commit-multi-remote |
7 files | 47 files |
dracon-system-disk-process-guard-doctor |
7 files | 25 files |
dracon-warden-secret-encrypt-age-git-filter |
7 files | 50 files |
Verified standalone builds
| Repo | Build | Tests (sequential) |
|---|---|---|
dracon-sync-background-auto-commit-multi-remote |
✓ | 575 passed, 0 failed, 3 ignored |
dracon-system-disk-process-guard-doctor |
✓ | 86 passed, 0 failed, 0 ignored |
dracon-warden-secret-encrypt-age-git-filter |
✓ | 86 passed, 0 failed, 0 ignored |
Version bumps
- Root workspace:
0.112.6→0.112.7(patch-level, doc/infra only) dracon-sync:0.1.7→0.1.8dracon-system:0.2.2→0.2.3dracon-warden:0.3.2→0.3.3
What's in the box (since v0.112.6)
The full [0.112.7] CHANGELOG section includes:
- Architecture inversion: 3 long-name façade repos are now real install
targets with mirrored source code (not navigation shells) - Standalone build support: each façade repo has a
Cargo.tomlwith
path-dep siblings;cargo build --releaseworks from each repo - Updated
scripts/scaffold_feature_repos.py: new
_copy_utility_source()+_standalone_cargo_toml()functions that mirror
per-utility source code from the monorepo and generate standalone manifests - Updated design doc (
docs/design/github-feature-repos.md): invariants
section flipped; "Why this is not a hack" updated to describe the
one-way mirror mechanism - Verified: all 3 repos build + test standalone (test counts above)
Migration notes
- If you previously cloned only the monorepo, you can now also clone any of
the 3 long-name façade repos and build it standalone (with the sibling
clones as documented above). - The monorepo is still the source of truth for development. The 3 façade
repos are downstream mirrors. Changes to per-utility source files in the
monorepo flow to the corresponding façade repo automatically via the
post-commithook +regenerate_facade_repos.py.
What's next
- The 3 façade repos will now stay in sync with the monorepo via the
post-commit hook + daemon auto-push (unchanged from v0.112.5) - Operator to decide on the 3 GitLab Set A repos (still pending from goal
83e42c15; defaultAleave-as-is is in effect)
Release v0.112.6
Release v0.112.6 — 2026-06-16
Summary
This is a release hygiene + architecture formalization release. It packages
the work from goal 83e42c15 which made the 3 long-name façade repos the
canonical "mains" for the project. The release notes below also list those 3
long-name repos as the install targets for users who land here from search
or the GitHub profile.
Install targets (canonical mains)
The 3 long-name façade repos are the canonical install targets for users
who want to learn about each utility. They are deliberately brutally-descriptive
so they are self-explanatory on search engines and on Codeberg / Forgejo.
| Utility | Install target (GitHub) | Also on |
|---|---|---|
dracon-sync |
DraconDev/dracon-sync-background-auto-commit-multi-remote |
GitLab + Codeberg |
dracon-system |
DraconDev/dracon-system-disk-process-guard-doctor |
GitLab + Codeberg |
dracon-warden |
DraconDev/dracon-warden-secret-encrypt-age-git-filter |
GitLab + Codeberg |
Repository architecture (formalized in this release)
This is now a 4-repo system with distinct roles:
| Repo | Role | Contains | Updated by |
|---|---|---|---|
DraconDev/dracon-utilities (this repo) |
Dev workspace | All 3 utilities' source code + monorepo build + install.sh + tests + docs |
The operator (manual commits) + dracon-sync daemon (auto-commits to all 4 remotes) |
DraconDev/dracon-sync-background-auto-commit-multi-remote |
Façade main for dracon-sync |
README + LICENSE + SECURITY + .gitignore + .github/ + docs/SOURCE_OF_TRUTH.md | post-commit hook → regenerate_facade_repos.py → dracon-sync daemon (auto-pushes to all 3 remotes) |
DraconDev/dracon-system-disk-process-guard-doctor |
Façade main for dracon-system |
Same 7 files as above | Same |
DraconDev/dracon-warden-secret-encrypt-age-git-filter |
Façade main for dracon-warden |
Same 7 files as above | Same |
The 3 façade repos are the canonical "mains" for users (presentation +
discoverability). The monorepo is the canonical "main" for builds
(./install.sh clones the monorepo, not the façade repos — the façade repos
contain only presentation content, not source code).
The flow is one-way: operator edits code in the monorepo → commits trigger
the post-commit hook → the hook runs regenerate_facade_repos.py for the
affected utility → the script writes the new README + metadata to the 3 façade
repo clones at /home/dracon/Dev/facade-repos/ → the daemon (dracon-sync)
sees the local change and auto-pushes to GitHub + GitLab + Codeberg.
Version bumps
- Root workspace:
0.112.5→0.112.6(patch-level, doc/infra only) dracon-sync:0.1.6→0.1.7dracon-system:0.2.1→0.2.2dracon-warden:0.3.1→0.3.2
What's in the box (since v0.112.5)
The full [0.112.6] CHANGELOG section includes:
- Repository architecture formalized: root
README.mdand
docs/design/github-feature-repos.mdnow have explicit "Repository
architecture" sections that document the 4-repo model - 3 long-name façade repos are the canonical "mains": referenced in
root README, design doc, daemon watch list, scaffold/regen scripts, and
release notes /tmp/fa-clones-b/cleaned up: the 3 façade repo clones were moved
to/home/dracon/Dev/facade-repos/(a daemon-watched path)- Old short-name repos deprecated:
- GitHub: 0 (the Set A→B rename was in-place, old URLs redirect)
- Codeberg: 0 (hard-deleted during the Set B migration)
- GitLab: 3 Set A repos soft-deleted with
_deletion_scheduled-XXXXXXXX
suffix; awaiting operator decision for hard-delete vs archive
Verification
cargo build --release --locked: succeedscargo test --workspace --locked: 856 passed, 0 failed, 9 ignoredpython3 scripts/scaffold_feature_repos.py --validate-name: passespython3 scripts/regenerate_facade_repos.py --dry-run: passes- 3 Set B façade repos: 4-remote aligned (
da0dbf5/b37781a/8ceb070) - Monorepo: 4-remote aligned at release SHA
- Daemon: 4 repos watched (1 monorepo + 3 façade repos), all healthy
- All 3 façade repos are the install targets in this release's release notes
Migration notes
- If you cloned the old Set A repos (
DraconDev/dracon-sync, etc.) on
GitHub, the rename in place means the old URLs redirect to the new ones
for a grace period. Update your bookmarks to the new long names. - The 3 new façade repos are at
/home/dracon/Dev/facade-repos/(a path
the daemon already watches) and stay in sync with the monorepo via the
post-commithook +regenerate_facade_repos.py. - If you commit changes to a utility's source files, the
post-commithook
fires automatically and the daemon pushes the regenerated façade content.
No manualscaffold_feature_repos.pyinvocation needed.
What's next
- Operator to decide on the 3 GitLab Set A repos (hard-delete vs archive vs
leave-as-is) — this is the only remaining open item from goal83e42c15 - The 3 façade repos will now stay in sync with the monorepo via the
post-commit hook + daemon auto-push
Release v0.112.5
Release v0.112.5 — 2026-06-16
Summary
This is a release hygiene + façade repo refinement release. It packages
the work from goals 4c2caf36 (Set A→B façade repo rename) and 98dfd198
(Set A deployment), plus the deep-untracked-subtrees fix from 662a6e15,
plus 11 other Unreleased entries that had accumulated since v0.112.4.
The most user-visible change is the Set B façade repo names:
DraconDev/dracon-sync-background-auto-commit-multi-remote(was
dracon-sync-watch-debounce-commit-push-mirror)DraconDev/dracon-system-disk-process-guard-doctor(was
dracon-system-disk-zram-process-service-guard)DraconDev/dracon-warden-secret-encrypt-age-git-filter(was
dracon-warden-age-git-filter-secret-encrypt)
The new names are deliberately brutally descriptive so they're
self-explanatory on Codeberg/Forgejo (where descriptive names get upvotes and
free attention). They are also the canonical names in the
scripts/scaffold_feature_repos.py script, with the old short names kept
as --repo aliases for backwards compat.
A new scripts/regenerate_facade_repos.py script + a monorepo post-commit
hook now keep the 3 façade repos in sync with the monorepo's source files.
When the operator commits a change to dracon-sync/README.md (or any
utility's source), the hook regenerates the corresponding façade's README +
other scaffold files, commits them locally, and the daemon (dracon-sync)
auto-pushes the change to all 3 remotes (github, gitlab, codeberg).
The 3 façade repo clones live at /home/dracon/Dev/facade-repos/ (a path
the daemon already watches). They were added with origin as the GitHub
HTTPS remote + gitlab and codeberg as SSH remotes, matching the daemon's
multi-remote sync policy.
Audit findings (Part 1 of the goal)
The full audit (10 sub-areas) is in /tmp/audit-v1.0.1.md. Key findings:
- All 3 Set B façade repos exist on all 4 remotes, 4-remote aligned
- All 3 repos are public on all 3 third-party remotes
- All 3 repos have the 7 expected files (README, LICENSE, SECURITY, etc.)
- All 3 names pass
--validate-nameand--self-test - Bug fixed: GitHub descriptions didn't match GitLab + Codeberg (had Set A
text); now all match - Bug fixed: the 3 façade repo clones were not in the daemon's watch
list; now added at/home/dracon/Dev/facade-repos/ - No stale references to old Set A names outside
docs/design/github-feature-repos.mdCHANGELOG.md(intentional history)
- Daemon healthy, 856 tests pass, 0 fail, 9 ignored
Version bumps
- Root workspace:
0.112.4→0.112.5(patch-level, doc/infra only) dracon-sync:0.1.5→0.1.6dracon-system:0.2.0→0.2.1dracon-warden:0.3.0→0.3.1
What's in the box (since v0.112.4)
The full [Unreleased] section (now [0.112.5]) includes 14+ goal entries
that accumulated since 2026-06-07. Major items:
- Façade repo rename Set A → Set B (goals
98dfd198+4c2caf36) - Deep untracked subtrees not staged (goal
662a6e15):stage_existing_files
now does full recursive walk instead of 1-level - PUSH_STUCK prevention (goal
87c1bf4d): sequential multi-remote push +
per-remoteforce_push_when_behind = trueconfig - Sequential push:
multi_remote.rsswitched from concurrenttokio::spawn
to sequentialfor remote in sortedto eliminate race - Auto-sync hook: new
scripts/regenerate_facade_repos.py+ monorepo
post-commithook keeps the 3 façade repos in sync - Various
dracon-system/dracon-wardenhardening (binary passthrough,
path-component matching, exact filename matching, etc.)
Verification
cargo build --release --locked: succeedscargo test --workspace --locked: 856 passed, 0 failed, 9 ignoredpython3 scripts/scaffold_feature_repos.py --validate-name: passespython3 scripts/scaffold_feature_repos.py --self-test: passespython3 scripts/regenerate_facade_repos.py --dry-run: passes- 3 Set B façade repos: 4-remote aligned (
da0dbf5/b37781a/8ceb070) - Monorepo: 4-remote aligned at release SHA
- Daemon: 13 repos watched (was 13; +3 façade repos added but counted within)
Migration notes
- If you cloned the old Set A repos (
DraconDev/dracon-sync, etc.) on
GitHub, the rename in place means the old URLs redirect to the new ones
for a grace period. Update your bookmarks to the new long names. - The old short names still work as
--repoaliases in the scaffold script
for backwards compat. - The 3 new façade repos are added to the daemon's watch list automatically
(via the path/home/dracon/Dev/facade-repos/which is inwatch_roots). - If you commit changes to a utility's source files, the
post-commithook
fires automatically and the daemon pushes the regenerated façade content.
No manualscaffold_feature_repos.pyinvocation needed.
What's next
- Operator to decide if Set B names are final (vs further iteration)
- Operator to decide on remaining Unreleased entries from previous goals
(if any should be deferred to a different release) - The 3 façade repos will now stay in sync with the monorepo via the
post-commit hook + daemon auto-push