1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
# Dracon Sync Policy
# Path: ~/.dracon/utilities/sync/dracon-sync.toml
#
# This controls how dracon-sync watches and syncs your repos.
#
# ⚠️ TOML FIELD ORDERING: Top-level fields (like standard_files) must appear
# BEFORE any section headers ([...] or [[...]]). Fields after a section header
# are silently parsed as belonging to that section and will be ignored by the
# policy loader.
# =============================================================================
# SECTION 1: THE SOVEREIGN CORE
# =============================================================================
# [system_repo]
# The primary repository for your machine laws and state (~/.dracon).
# The daemon ensures this repo is ALWAYS healthy and synchronized.
# This must be a git repository (or a directory that will be turned into one).
# Defaults to ~/.dracon when unset.
# system_repo = "/home/dracon/.dracon"
# =============================================================================
# SECTION 2: THE RHYTHM (Sync Logic)
# =============================================================================
# How often (seconds) to scan repos for activity while daemon is running.
= 1
# Push only after this many quiet seconds since last detected repo change.
= 5
# [auto_commit] - Automatically stage and commit local changes.
= true
# If true, bump patch versions before auto-commits (best-effort).
# Applies when these files exist at repo root:
# - Rust: Cargo.toml (+ keep Cargo.lock aligned for root package)
# - Node/TS: package.json (+ align package-lock.json root version when applicable)
# - Generic: VERSION
= true
# [auto_pull] - Pull remote changes before committing (uses merge, not rebase).
= true
# [auto_push] - Propagate local commits to all configured remotes.
= true
# [auto_repair_concerns] - Run concern repair logic after each sync pass.
= true
# [auto_repair_warns] - Run dirty-only warn triage after each sync pass.
= true
# [auto_rewrite_large_blobs] - Aggressive rewrite when large blobs are detected.
# Keep false for safe default behavior.
= false
# Git operation idle timeouts (seconds). Git push/pull commands are progress-aware:
# a stalled operation is killed after this idle window, while active pack
# transfer progress extends the deadline so large repos are not aborted early.
# repo_sync_timeout_secs is retained for status/compatibility; per-operation
# timeouts now enforce push/pull safety.
= 30
= 60
= 120
# Retry count for push operations before fallback transport logic.
= 3
# Cooldown between failed auto-repair attempts on the same repo.
= 60
# Hard push guardrail for blob size; keep <= 100 MiB host limit.
= 52428800
# Incident ledger retention policy.
= 10000
= 30
# =============================================================================
# SECTION 3: THE VAULT (Backup Strategy)
# =============================================================================
# 'Bundle' creates air-gapped git-bundle files in the backup_dir before every
# sync attempt. This is your insurance against failed rebases or data loss.
= "Bundle"
= "/home/dracon/dracon/backups"
# =============================================================================
# SECTION 4: THE SCOPE
# =============================================================================
# Roots recursively patrolled for .git repositories to sync.
= ["/home/dracon/Dev"]
# Exclude heavy/generated trees from repo discovery and auto-staging.
= [
"target",
"node_modules",
".cache",
".direnv",
".venv",
"dist",
"build",
"archives",
".tmp-*"
]
# Exclude specific file patterns from auto-staging.
= [
"*.log",
"nohup.out"
]
# Skip staging files larger than 50 MiB during auto-commit.
= 52428800
# =============================================================================
# SECTION 5: SAFETY
# =============================================================================
# Mass-deletion prevention: if >= 85% of tracked files are missing from the
# working tree, dracon-sync will refuse to auto-commit. This guards against
# accidental wipes from filesystem issues or destructive operations.
#
# To bypass for intentional total wipes:
# dracon-sync sync-now --force <repo>
# =============================================================================
# SECTION 6: REMOTES
# =============================================================================
# Origin remote is always pushed first. Mirror remotes are pushed after.
# The {repo} placeholder is replaced with the repo directory name.
# GitHub (origin)
[[]]
= "github"
= "https://github.com/DraconDev/{repo}.git"
= true
# GitLab (with PAT-based HTTPS fallback)
[[]]
= "gitlab"
= "git@gitlab.com:dracondev/{repo}.git"
= true
# Codeberg (push-to-create disabled in Forgejo)
[[]]
= "codeberg"
= "git@codeberg.org:dracondev/{repo}.git"
= false
# Per-remote repo name mapping (e.g. for dot-prefixed dirs on GitLab)
# [[remotes]]
# name = "gitlab"
# push_url = "git@gitlab.com:myorg/{repo}.git"
# auto_create = true
# [remotes.repo_name_map]
# ".dracon" = "dracon-home"
# =============================================================================
# SECTION 7: MIRROR VISIBILITY & METADATA
# =============================================================================
# When true, mirrors (GitLab, Codeberg) match GitHub's public/private status.
# When false (default), all auto-created mirrors are private.
# Checked at most once per repo per sync_visibility_interval_hours.
# sync_visibility = false
# sync_visibility_interval_hours = 24
# When true, mirror repos also inherit the GitHub repo's description and topics.
# This makes mirrors discoverable via topic search on GitLab/Codeberg.
# Uses the same interval cache as visibility sync.
# sync_metadata = false
# =============================================================================
# SECTION 8: RELEASE PIPELINE (Tags, Releases, Publishing)
# =============================================================================
# Three separate toggles control the release pipeline per repo.
# All three default to "off" at the repo level — nothing happens unless
# the repo explicitly opts in via .dracon/dracon-sync.toml.
#
# ┌──────────────┬─────────────┬──────────┬────────────────────────────────┐
# │ Toggle │ Default │ Risk │ Purpose │
# ├──────────────┼─────────────┼──────────┼────────────────────────────────┤
# │ auto_tag │ true │ Low │ Git tag on every version bump │
# │ auto_release │ false │ Medium │ GitHub Release on major bumps │
# │ auto_publish │ [] (empty) │ High │ Publish to package registries │
# └──────────────┴─────────────┴──────────┴────────────────────────────────┘
#
# Tags are cheap, reversible, and universally useful — on by default.
# Releases are public milestones — opt-in per repo.
# Publishing is IRREVERSIBLE (crates.io/npm/PyPI are immutable) — explicit list.
#
# auto_publish = false # global master toggle (default: off)
#
# Each publish target needs a token_secret — the env var name that holds the
# registry API key. Store the actual token in ~/.dracon/utilities/sync/secrets/*.env.
# See that directory's README for how to create each token.
#
# [[publish_targets]]
# name = "crates-io"
# registry = "crates-io" # crates-io | npm | pypi
# token_secret = "CARGO_REGISTRY_TOKEN" # env var name (token in secrets/cratesio.env)
# publish_timeout_secs = 300
#
# [[publish_targets]]
# name = "npm"
# registry = "npm"
# token_secret = "NPM_TOKEN" # env var name (token in secrets/npm.env)
# Create npm token at: https://www.npmjs.com/settings/tokens/create
# Use "Automation" type (never expires, bypasses 2FA for CI/CD)
# Note: `npm token create --automation` is deprecated in npm v11+
# publish_timeout_secs = 120
#
# [[publish_targets]]
# name = "pypi"
# registry = "pypi"
# token_secret = "TWINE_PASSWORD" # env var name (token in secrets/pypi.env)
# publish_timeout_secs = 120
#
# PER-REPO OPT-IN (required even when auto_publish = true globally):
# Create .dracon/dracon-sync.toml in the repo root:
#
# # Tag every bump (default: true, safe to omit)
# auto_tag = true
#
# # Create GitHub Releases for major bumps (default: false)
# auto_release = true
#
# # Publish to specific registries (default: empty = no publishing)
# auto_publish = ["crates-io"]
#
# Example configurations for different project types:
#
# Rust library:
# auto_tag = true
# auto_release = true
# auto_publish = ["crates-io"]
#
# CLI binary (app, not a library):
# auto_tag = true
# auto_release = false
# auto_publish = []
#
# Mixed Rust+JS library:
# auto_tag = true
# auto_release = true
# auto_publish = ["crates-io", "npm"]
#
# Internal daemon (private, no publish):
# auto_tag = true
# auto_release = false
# auto_publish = []
#
# Without auto_publish targets, no publishing happens.
# Without auto_release = true, no GitHub Releases are created.
# Tags are created by default for every version bump unless auto_tag = false.
# nix_auto_update = false # global master toggle (default: off)
#
# When true and a version bump occurs in a repo with flake.nix, dracon-sync:
# 1. Updates the version field in flake.nix (inside [package] block)
# 2. Creates a PR via `gh` with the flake.nix change
#
# This is independent of tagging and publishing — it only applies to repos
# that have a flake.nix file AND are connected to GitHub (gh CLI required).
#
# Per-repo opt-in (via .dracon/dracon-sync.toml):
# nix_auto_update = true
#
# Nix flake version update (if enabled globally and repo has flake.nix):
# auto_tag = true
# nix_auto_update = true
#
# Without nix_auto_update, flake.nix version fields are NOT updated automatically.
#
# =============================================================================
# SECTION 9: STANDARD FILES
# =============================================================================
# AGPL v3 LICENSE is auto-copied to every new repo during sync.
# This ensures all Dracon repos carry the same copyleft license.
# You own the copyright → you're the only one who can sell commercial licenses.
# Templates live in ~/.dracon/utilities/sync/templates/ (auto-resolved from short form).
# Files are only copied if the target does not exist (overwrite = false, the default).
#
# Short form — filename only (resolves to templates/{name}):
# This is the generic starter for external users: only AGPL LICENSE is added.
# standard_files = ["LICENSE"]
#
# Auto-copy during sync (default: true — ensures new repos always get AGPL):
# standard_files_auto = true
#
# Dracon-specific optional file: FUNDING.yml is not part of the generic
# dracon-sync default. Only add this if you intentionally want GitHub Sponsors
# configuration scaffolded into your repos.
#
# GitHub discovers FUNDING.yml at .github/FUNDING.yml (not the repo root).
# To scaffold it there, use the long form:
# [[standard_files]]
# source = "templates/FUNDING.yml"
# target = ".github/FUNDING.yml"
# overwrite = false
#
# Long form — for explicit source path or overwrite behavior:
# [[standard_files]]
# source = "templates/CUSTOM"
# target = "CUSTOM_NOTICE"
# overwrite = false # default: false (never overwrites existing files)
#
# Per-repo opt-out (via .dracon/dracon-sync.toml in repo root):
# skip_standard_files = ["LICENSE", ".github/FUNDING.yml"]
#
# Template path resolution:
# - Absolute paths: used as-is
# - ~/ paths: expanded to home directory
# - Relative paths: resolved relative to sync config dir (~/.dracon/utilities/sync/)
#
# If a template file is missing, a warning is printed but sync continues.
#
# FUNDING.yml is the GitHub Sponsors / community funding configuration file.
# It is Dracon-specific in this policy: external users of dracon-sync do not
# receive it unless they explicitly add the long-form standard_files entry
# above. The default template ships with no funding destinations (github: [],
# etc.) so a freshly-scaffolded repo advertises nothing until the operator
# fills it in. The file is public and version-controlled; never place API keys,
# tokens, or any other secret material in it. The Warden key management layer
# treats it as plain text.
# =============================================================================
# SECTION 10: WEBHOOK
# =============================================================================
# On push failures (origin or mirror remotes), dracon-sync can send a
# fire-and-forget HTTP POST to a configured webhook URL:
# webhook_url = "https://your-webhook-endpoint.example/notify"