cfgit 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,744 @@
1
+ Metadata-Version: 2.4
2
+ Name: cfgit
3
+ Version: 0.1.0
4
+ Summary: Git-style history, diff, drift detection, and rollback for live database records without migrating or owning your datastore
5
+ Project-URL: Homepage, https://github.com/AusafMo/cfgit
6
+ Project-URL: Repository, https://github.com/AusafMo/cfgit
7
+ Project-URL: Issues, https://github.com/AusafMo/cfgit/issues
8
+ Project-URL: Documentation, https://github.com/AusafMo/cfgit#readme
9
+ Author: Mohammad Ausaf
10
+ License: Apache License
11
+ Version 2.0, January 2004
12
+ http://www.apache.org/licenses/
13
+
14
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
15
+
16
+ 1. Definitions.
17
+
18
+ "License" shall mean the terms and conditions for use, reproduction,
19
+ and distribution as defined by Sections 1 through 9 of this document.
20
+
21
+ "Licensor" shall mean the copyright owner or entity authorized by
22
+ the copyright owner that is granting the License.
23
+
24
+ "Legal Entity" shall mean the union of the acting entity and all
25
+ other entities that control, are controlled by, or are under common
26
+ control with that entity. For the purposes of this definition,
27
+ "control" means (i) the power, direct or indirect, to cause the
28
+ direction or management of such entity, whether by contract or
29
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
30
+ outstanding shares, or (iii) beneficial ownership of such entity.
31
+
32
+ "You" (or "Your") shall mean an individual or Legal Entity
33
+ exercising permissions granted by this License.
34
+
35
+ "Source" form shall mean the preferred form for making modifications,
36
+ including but not limited to software source code, documentation
37
+ source, and configuration files.
38
+
39
+ "Object" form shall mean any form resulting from mechanical
40
+ transformation or translation of a Source form, including but
41
+ not limited to compiled object code, generated documentation,
42
+ and conversions to other media types.
43
+
44
+ "Work" shall mean the work of authorship, whether in Source or
45
+ Object form, made available under the License, as indicated by a
46
+ copyright notice that is included in or attached to the work
47
+ (an example is provided in the Appendix below).
48
+
49
+ "Derivative Works" shall mean any work, whether in Source or Object
50
+ form, that is based on (or derived from) the Work and for which the
51
+ editorial revisions, annotations, elaborations, or other modifications
52
+ represent, as a whole, an original work of authorship. For the purposes
53
+ of this License, Derivative Works shall not include works that remain
54
+ separable from, or merely link (or bind by name) to the interfaces of,
55
+ the Work and Derivative Works thereof.
56
+
57
+ "Contribution" shall mean any work of authorship, including
58
+ the original version of the Work and any modifications or additions
59
+ to that Work or Derivative Works thereof, that is intentionally
60
+ submitted to Licensor for inclusion in the Work by the copyright owner
61
+ or by an individual or Legal Entity authorized to submit on behalf of
62
+ the copyright owner. For the purposes of this definition, "submitted"
63
+ means any form of electronic, verbal, or written communication sent
64
+ to the Licensor or its representatives, including but not limited to
65
+ communication on electronic mailing lists, source code control systems,
66
+ and issue tracking systems that are managed by, or on behalf of, the
67
+ Licensor for the purpose of discussing and improving the Work, but
68
+ excluding communication that is conspicuously marked or otherwise
69
+ designated in writing by the copyright owner as "Not a Contribution."
70
+
71
+ "Contributor" shall mean Licensor and any individual or Legal Entity
72
+ on behalf of whom a Contribution has been received by Licensor and
73
+ subsequently incorporated within the Work.
74
+
75
+ 2. Grant of Copyright License. Subject to the terms and conditions of
76
+ this License, each Contributor hereby grants to You a perpetual,
77
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
78
+ copyright license to reproduce, prepare Derivative Works of,
79
+ publicly display, publicly perform, sublicense, and distribute the
80
+ Work and such Derivative Works in Source or Object form.
81
+
82
+ 3. Grant of Patent License. Subject to the terms and conditions of
83
+ this License, each Contributor hereby grants to You a perpetual,
84
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
85
+ (except as stated in this section) patent license to make, have made,
86
+ use, offer to sell, sell, import, and otherwise transfer the Work,
87
+ where such license applies only to those patent claims licensable
88
+ by such Contributor that are necessarily infringed by their
89
+ Contribution(s) alone or by combination of their Contribution(s)
90
+ with the Work to which such Contribution(s) was submitted. If You
91
+ institute patent litigation against any entity (including a
92
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
93
+ or a Contribution incorporated within the Work constitutes direct
94
+ or contributory patent infringement, then any patent licenses
95
+ granted to You under this License for that Work shall terminate
96
+ as of the date such litigation is filed.
97
+
98
+ 4. Redistribution. You may reproduce and distribute copies of the
99
+ Work or Derivative Works thereof in any medium, with or without
100
+ modifications, and in Source or Object form, provided that You
101
+ meet the following conditions:
102
+
103
+ (a) You must give any other recipients of the Work or
104
+ Derivative Works a copy of this License; and
105
+
106
+ (b) You must cause any modified files to carry prominent notices
107
+ stating that You changed the files; and
108
+
109
+ (c) You must retain, in the Source form of any Derivative Works
110
+ that You distribute, all copyright, patent, trademark, and
111
+ attribution notices from the Source form of the Work,
112
+ excluding those notices that do not pertain to any part of
113
+ the Derivative Works; and
114
+
115
+ (d) If the Work includes a "NOTICE" text file as part of its
116
+ distribution, then any Derivative Works that You distribute must
117
+ include a readable copy of the attribution notices contained
118
+ within such NOTICE file, excluding those notices that do not
119
+ pertain to any part of the Derivative Works, in at least one
120
+ of the following places: within a NOTICE text file distributed
121
+ as part of the Derivative Works; within the Source form or
122
+ documentation, if provided along with the Derivative Works; or,
123
+ within a display generated by the Derivative Works, if and
124
+ wherever such third-party notices normally appear. The contents
125
+ of the NOTICE file are for informational purposes only and
126
+ do not modify the License. You may add Your own attribution
127
+ notices within Derivative Works that You distribute, alongside
128
+ or as an addendum to the NOTICE text from the Work, provided
129
+ that such additional attribution notices cannot be construed
130
+ as modifying the License.
131
+
132
+ You may add Your own copyright statement to Your modifications and
133
+ may provide additional or different license terms and conditions
134
+ for use, reproduction, or distribution of Your modifications, or
135
+ for any such Derivative Works as a whole, provided Your use,
136
+ reproduction, and distribution of the Work otherwise complies with
137
+ the conditions stated in this License.
138
+
139
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
140
+ any Contribution intentionally submitted for inclusion in the Work
141
+ by You to the Licensor shall be under the terms and conditions of
142
+ this License, without any additional terms or conditions.
143
+ Notwithstanding the above, nothing herein shall supersede or modify
144
+ the terms of any separate license agreement you may have executed
145
+ with Licensor regarding such Contributions.
146
+
147
+ 6. Trademarks. This License does not grant permission to use the trade
148
+ names, trademarks, service marks, or product names of the Licensor,
149
+ except as required for reasonable and customary use in describing the
150
+ origin of the Work and reproducing the content of the NOTICE file.
151
+
152
+ 7. Disclaimer of Warranty. Unless required by applicable law or
153
+ agreed to in writing, Licensor provides the Work (and each
154
+ Contributor provides its Contributions) on an "AS IS" BASIS,
155
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
156
+ implied, including, without limitation, any warranties or conditions
157
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
158
+ PARTICULAR PURPOSE. You are solely responsible for determining the
159
+ appropriateness of using or redistributing the Work and assume any
160
+ risks associated with Your exercise of permissions under this License.
161
+
162
+ 8. Limitation of Liability. In no event and under no legal theory,
163
+ whether in tort (including negligence), contract, or otherwise,
164
+ unless required by applicable law (such as deliberate and grossly
165
+ negligent acts) or agreed to in writing, shall any Contributor be
166
+ liable to You for damages, including any direct, indirect, special,
167
+ incidental, or consequential damages of any character arising as a
168
+ result of this License or out of the use or inability to use the
169
+ Work (including but not limited to damages for loss of goodwill,
170
+ work stoppage, computer failure or malfunction, or any and all
171
+ other commercial damages or losses), even if such Contributor
172
+ has been advised of the possibility of such damages.
173
+
174
+ 9. Accepting Warranty or Additional Liability. While redistributing
175
+ the Work or Derivative Works thereof, You may choose to offer,
176
+ and charge a fee for, acceptance of support, warranty, indemnity,
177
+ or other liability obligations and/or rights consistent with this
178
+ License. However, in accepting such obligations, You may act only
179
+ on Your own behalf and on Your sole responsibility, not on behalf
180
+ of any other Contributor, and only if You agree to indemnify,
181
+ defend, and hold each Contributor harmless for any liability
182
+ incurred by, or claims asserted against, such Contributor by reason
183
+ of your accepting any such warranty or additional liability.
184
+
185
+ END OF TERMS AND CONDITIONS
186
+
187
+ APPENDIX: How to apply the Apache License to your work.
188
+
189
+ To apply the Apache License to your work, attach the following
190
+ boilerplate notice, with the fields enclosed by brackets "[]"
191
+ replaced with your own identifying information. (Don't include
192
+ the brackets!) The text should be enclosed in the appropriate
193
+ comment syntax for the file format. We also recommend that a
194
+ file or class name and description of purpose be included on the
195
+ same "printed page" as the copyright notice for easier
196
+ identification within third-party archives.
197
+
198
+ Copyright 2026 Mohammad Ausaf
199
+
200
+ Licensed under the Apache License, Version 2.0 (the "License");
201
+ you may not use this file except in compliance with the License.
202
+ You may obtain a copy of the License at
203
+
204
+ http://www.apache.org/licenses/LICENSE-2.0
205
+
206
+ Unless required by applicable law or agreed to in writing, software
207
+ distributed under the License is distributed on an "AS IS" BASIS,
208
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
209
+ See the License for the specific language governing permissions and
210
+ limitations under the License.
211
+ License-File: LICENSE
212
+ License-File: NOTICE
213
+ Keywords: agents,configuration,database,database-versioning,datastore,drift-detection,mcp,mongodb,postgres,rollback,version-control
214
+ Requires-Python: >=3.11
215
+ Requires-Dist: tomli; python_version < '3.11'
216
+ Provides-Extra: cli
217
+ Requires-Dist: click>=8.1; extra == 'cli'
218
+ Requires-Dist: rich>=13.0; extra == 'cli'
219
+ Provides-Extra: dev
220
+ Requires-Dist: httpx>=0.27; extra == 'dev'
221
+ Requires-Dist: mypy; extra == 'dev'
222
+ Requires-Dist: pytest-asyncio; extra == 'dev'
223
+ Requires-Dist: pytest>=8.0; extra == 'dev'
224
+ Requires-Dist: ruff; extra == 'dev'
225
+ Provides-Extra: impact
226
+ Provides-Extra: mcp
227
+ Requires-Dist: mcp>=1.0; extra == 'mcp'
228
+ Provides-Extra: mongo
229
+ Requires-Dist: pymongo>=4.6; extra == 'mongo'
230
+ Provides-Extra: postgres
231
+ Requires-Dist: psycopg[binary]>=3.2; extra == 'postgres'
232
+ Description-Content-Type: text/markdown
233
+
234
+ # cfgit
235
+
236
+ Non-custodial version control for live datastore records.
237
+
238
+ A clean tool for dirty workflows. Git that does not make you move in.
239
+
240
+ cfgit gives git-shaped history, diff, rollback, tags, and drift reconciliation to
241
+ records that already live in your database. Your application keeps reading the
242
+ same database. Your scripts and admin tools can still write it. cfgit sits beside
243
+ the store, records what changed, and refuses to clobber changes it did not record.
244
+
245
+ <p align="center">
246
+ <img src="docs/screenshots/01-diff.png" alt="Side-by-side line diff of a live agent config, with a sticky field header and collapsed context" width="32%" />
247
+ <img src="docs/screenshots/02-impact.png" alt="System-impact panel: deterministic facts plus opt-in LLM narration of what the change does downstream" width="32%" />
248
+ <img src="docs/screenshots/03-scoped-impact.png" alt="Scoped impact: select records on the left and reason the change against only those" width="32%" />
249
+ </p>
250
+
251
+ <p align="center">
252
+ <sub>Line-aligned diff of a live record &nbsp;·&nbsp; system-impact panel &nbsp;·&nbsp; impact scoped to the records you select &nbsp;(demo data)</sub>
253
+ </p>
254
+
255
+ ## Why cfgit exists
256
+
257
+ Many teams keep runtime behavior in live database records: model routing, agent
258
+ prompts, provider settings, pricing tables, policy config, workflow definitions,
259
+ feature controls, and other control-plane data. These records are often edited by
260
+ people, scripts, admin APIs, and AI coding agents. The edits take effect
261
+ immediately, but the workflow usually lacks the things engineers expect from code:
262
+
263
+ - a useful history
264
+ - a readable diff
265
+ - a safe commit path
266
+ - rollback to a known good point
267
+ - a way to see when someone changed the database outside the tool
268
+
269
+ Existing "git for data" tools usually solve a different problem: they want to
270
+ own the database or sit in front of storage. cfgit is for the case where you
271
+ cannot move the data and cannot put a gateway in the runtime path.
272
+
273
+ ## Core idea
274
+
275
+ cfgit versions opaque JSON records identified by a stable id. It stores history
276
+ beside the live datastore, not inside your application code and not in a hosted
277
+ prompt registry.
278
+
279
+ The important state is drift:
280
+
281
+ - `cfg status` detects live records that changed outside cfgit.
282
+ - `cfg diff <record> =HEAD =live` shows what changed.
283
+ - `cfg adopt <record>` folds that out-of-band change into history.
284
+ - `cfg commit` refuses to overwrite un-adopted drift.
285
+
286
+ That drift reconciliation is the main reason cfgit exists.
287
+
288
+ ## Status
289
+
290
+ cfgit is pre-1.0 software. The current implementation includes:
291
+
292
+ - CLI with JSON output
293
+ - MongoDB adapter
294
+ - Postgres adapter
295
+ - local author permission checks
296
+ - per-environment identity modes with hashed token or DB-principal verification
297
+ - opt-in branch and PR workflow for draft changes before runtime merge
298
+ - system restore by tag or timestamp
299
+ - localhost web UI
300
+ - MCP server
301
+ - portable Codex or Claude Code skill
302
+ - optional `cfgit-impact` plugin for deterministic impact summaries and opt-in LLM narration
303
+
304
+ The engine is intentionally DB-neutral. Mongo and Postgres are the first two
305
+ adapters to prove the storage seam.
306
+
307
+ ## When to use cfgit
308
+
309
+ Good fit:
310
+
311
+ - control-plane collections or tables
312
+ - low to moderate record counts
313
+ - records edited by a small team or agents
314
+ - changes where "who changed what and why" matters
315
+ - data where rollback to a known good state is a real operation
316
+
317
+ Examples:
318
+
319
+ - agent configs
320
+ - model routing records
321
+ - provider templates
322
+ - pricing or policy config
323
+ - workflow definitions
324
+ - feature or runtime behavior config
325
+
326
+ Bad fit:
327
+
328
+ - user-generated content
329
+ - events, logs, analytics, metrics
330
+ - high-write transactional tables
331
+ - append-only data
332
+ - rows written by traffic rather than curated by people
333
+
334
+ cfgit stores full document versions. It is not a warehouse, event log, backup
335
+ system, or schema migration tool.
336
+
337
+ ## Install
338
+
339
+ From a checkout:
340
+
341
+ ```bash
342
+ python -m venv .venv
343
+ . .venv/bin/activate
344
+ pip install -e '.[mongo,postgres,mcp,dev]'
345
+ pip install -e plugins/cfg_impact
346
+ ```
347
+
348
+ Minimal install for Mongo only:
349
+
350
+ ```bash
351
+ pip install -e '.[mongo]'
352
+ ```
353
+
354
+ Minimal install for Postgres only:
355
+
356
+ ```bash
357
+ pip install -e '.[postgres]'
358
+ ```
359
+
360
+ ## Quick start
361
+
362
+ Create `.cfg.toml` in the repo or working directory where you want to operate:
363
+
364
+ ```toml
365
+ [project]
366
+ name = "runtime-control-plane"
367
+
368
+ [history]
369
+ history_collection = "config_history"
370
+ heads_collection = "config_heads"
371
+
372
+ [branches]
373
+ enabled = false
374
+ refs_collection = "cfgit_refs"
375
+ default_branch = "main"
376
+
377
+ [[collection]]
378
+ name = "agent_configs"
379
+ id_field = "config_id"
380
+ live_when = { is_active = true }
381
+ ignore_fields = ["_id", "is_active", "updated_at", "updated_by"]
382
+ secret_fields = []
383
+
384
+ [env.dev]
385
+ database = "mongo"
386
+ uri = "env:DEV_MONGODB_URI"
387
+ db = "my-dev-db"
388
+ needs_approval = false
389
+
390
+ [env.dev.identity]
391
+ mode = "open"
392
+
393
+ [env.dev.permissions]
394
+ mode = "open"
395
+ admins = []
396
+ writers = []
397
+ admin_actions = ["restore_system"]
398
+ ```
399
+
400
+ You can define multiple `[env.<name>]` blocks, but one cfgit command opens one
401
+ env at a time:
402
+
403
+ ```bash
404
+ cfg --env dev status
405
+ cfg --env prod log agent_configs:agent_planner
406
+ ```
407
+
408
+ Keep each physical history store under one stable env name. If the same database
409
+ is later addressed as a different env, cfgit will report that history exists
410
+ under the original env instead of returning an empty log.
411
+
412
+ Point it at a local or staging database first:
413
+
414
+ ```bash
415
+ export DEV_MONGODB_URI='mongodb://localhost:27017/?replicaSet=rs0'
416
+ cfg init
417
+ cfg doctor
418
+ cfg import --all -m "initial import"
419
+ cfg status
420
+ ```
421
+
422
+ `cfg doctor` is read-only. Run it before the first import for a new database or
423
+ `.cfg.toml`; it reports secret-deny matches, large fields, and live-rule/key
424
+ issues in one pass, with paste-ready `secret_fields` and `ignore_fields`
425
+ suggestions.
426
+
427
+ Check drift:
428
+
429
+ ```bash
430
+ cfg status
431
+ cfg diff agent_configs:agent_planner =HEAD =live
432
+ ```
433
+
434
+ Commit a full JSON document:
435
+
436
+ ```bash
437
+ cfg commit agent_configs:agent_planner --from planner.json -m "tune planner routing"
438
+ ```
439
+
440
+ Commit multiple records as one batch intent:
441
+
442
+ ```json
443
+ [
444
+ {"record": "agent_configs:planner", "doc": {"config_id": "planner", "model": "fast"}},
445
+ {"record": "modelgarden_models:openai/gpt-4o-mini", "doc": {"model_path": "openai/gpt-4o-mini"}}
446
+ ]
447
+ ```
448
+
449
+ ```bash
450
+ cfg commit --bulk-from batch.json -m "switch planner routing"
451
+ ```
452
+
453
+ Bulk commit preflights the whole batch before writing. If any target has
454
+ un-adopted drift, is missing, duplicates another target, or trips the secret
455
+ policy, cfgit applies none of the batch.
456
+
457
+ Draft changes on a branch before mutating runtime:
458
+
459
+ ```bash
460
+ cfg branch create router-test --from main
461
+ cfg --branch router-test commit agent_configs:agent_planner --from planner.json -m "try router change"
462
+ cfg diff main..router-test
463
+ cfg pr create --base main --head router-test -m "review router change"
464
+ cfg pr merge <pr-id>
465
+ ```
466
+
467
+ Branching is opt-in with `[branches] enabled = true`. `branch`, branch commits,
468
+ branch diff, and PR creation write only cfgit draft/review refs. The only branch
469
+ command that mutates runtime is `cfg pr merge`, and it refuses stale main heads
470
+ or un-adopted live drift.
471
+
472
+ `commit`, `import`, and `adopt` scan the would-be-stored document for secret-like
473
+ field names and values from `[secrets]`. Fields listed in `secret_fields` are
474
+ stripped before history. Use `--allow-secret` only for intentional fixtures or
475
+ known false positives; cfgit records the override in history metadata.
476
+
477
+ Adopt an out-of-band database write:
478
+
479
+ ```bash
480
+ cfg adopt agent_configs:agent_planner -m "adopt admin console edit"
481
+ ```
482
+
483
+ Tag and restore:
484
+
485
+ ```bash
486
+ cfg tag june7-good
487
+ cfg restore --tag june7-good --dry-run -m "preview rollback"
488
+ cfg restore --tag june7-good -m "restore known good state"
489
+ ```
490
+
491
+ Open the local UI:
492
+
493
+ ```bash
494
+ cfg ui
495
+ ```
496
+
497
+ Run the MCP server:
498
+
499
+ ```bash
500
+ cfg-mcp
501
+ ```
502
+
503
+ ## Record syntax
504
+
505
+ Records are addressed as:
506
+
507
+ ```text
508
+ collection:id
509
+ ```
510
+
511
+ Examples:
512
+
513
+ ```text
514
+ agent_configs:agent_planner
515
+ modelgarden_models:openai/gpt-4o-mini
516
+ ```
517
+
518
+ The collection and id field are configured in `.cfg.toml`.
519
+
520
+ ## Commands
521
+
522
+ Common commands:
523
+
524
+ ```bash
525
+ cfg init
526
+ cfg doctor [record]
527
+ cfg import --all -m "initial import"
528
+ cfg status [record]
529
+ cfg diff <record> [from] [to]
530
+ cfg impact <record> [from] [to]
531
+ cfg commit <record> --from <file.json> -m "message"
532
+ cfg commit --bulk-from <batch.json> -m "message"
533
+ cfg branch list
534
+ cfg branch create <name> --from main
535
+ cfg branch delete <name>
536
+ cfg switch <name>
537
+ cfg --branch <name> commit <record> --from <file.json> -m "message"
538
+ cfg --branch <name> commit --bulk-from <batch.json> -m "message"
539
+ cfg diff main..<branch>
540
+ cfg --branch <branch> log
541
+ cfg pr create --base main --head <branch> -m "message"
542
+ cfg pr list
543
+ cfg pr show <id>
544
+ cfg pr close <id>
545
+ cfg pr merge <id>
546
+ cfg log <record>
547
+ cfg show <record> <ref>
548
+ cfg adopt <record> -m "message"
549
+ cfg adopt --all -m "message"
550
+ cfg tag <name>
551
+ cfg restore <record> <ref> -m "message"
552
+ cfg restore --as-of <date> --dry-run -m "message"
553
+ cfg restore --tag <name> --dry-run -m "message"
554
+ cfg fsck
555
+ cfg whoami
556
+ cfg ui
557
+ ```
558
+
559
+ Every command supports `--json` for scripts and agents.
560
+
561
+ Refs:
562
+
563
+ - `=HEAD` or `HEAD`: last cfgit-recorded version
564
+ - `=live` or `live`: current live database record
565
+ - `@<seq>`: history entry number
566
+ - `<oid-prefix>`: content hash prefix
567
+ - `tag:<name>`: tagged version
568
+
569
+ ## Local UI
570
+
571
+ `cfg ui` starts a localhost-only web UI over the same action layer as the CLI and
572
+ MCP server. It reads like a git client: a collection-and-record tree on the left,
573
+ a commit-graph history rail, and a line-aligned side-by-side diff that collapses
574
+ unchanged context (expandable in place) and keeps the field name pinned while you
575
+ scroll. It can run status, diff, impact, commit, branch draft commits, PR open
576
+ and merge, log, show, adopt, restore, tag, init, import, and fsck, and ships
577
+ dark and light themes.
578
+
579
+ By default it binds to `127.0.0.1:8765` and tries the next free ports if needed:
580
+
581
+ ```bash
582
+ cfg ui
583
+ cfg ui --port 9000 --no-open
584
+ ```
585
+
586
+ If you omit `--port`, cfgit will try the next free local ports. If you pass
587
+ `--port` explicitly, cfgit treats that port as intentional and fails if it is
588
+ already in use.
589
+
590
+ ## MCP and agent usage
591
+
592
+ The MCP server exposes the same operations with a uniform envelope:
593
+
594
+ ```json
595
+ {
596
+ "status": "ok",
597
+ "code": 0,
598
+ "message": "",
599
+ "data": {}
600
+ }
601
+ ```
602
+
603
+ Tools include:
604
+
605
+ - `cfg_status`
606
+ - `cfg_doctor`
607
+ - `cfg_diff`
608
+ - `cfg_impact`
609
+ - `cfg_commit`
610
+ - `cfg_bulk_commit`
611
+ - `cfg_branch_list`
612
+ - `cfg_branch_create`
613
+ - `cfg_branch_delete`
614
+ - `cfg_branch_diff`
615
+ - `cfg_branch_log`
616
+ - `cfg_pr_create`
617
+ - `cfg_pr_list`
618
+ - `cfg_pr_show`
619
+ - `cfg_pr_close`
620
+ - `cfg_pr_merge`
621
+ - `cfg_log`
622
+ - `cfg_show`
623
+ - `cfg_adopt`
624
+ - `cfg_restore`
625
+ - `cfg_tag`
626
+ - `cfg_fsck`
627
+ - `cfg_whoami`
628
+ - `cfg_init`
629
+ - `cfg_identity_hash`
630
+
631
+ A portable skill lives at `skills/cfgit/SKILL.md`.
632
+ `cfg_impact` accepts the same `against` list/string as the CLI `--against` flag,
633
+ so MCP clients can request scoped narration without shelling out.
634
+
635
+ If `cfg_log` or `cfg_show` returns `bad_config` with a message saying history
636
+ exists under another env, the same database has been addressed with two
637
+ different `.cfg.toml` env names. Re-run with the env that wrote the history, or
638
+ standardize the config so that database always uses one env name.
639
+
640
+ ## Impact summaries
641
+
642
+ `cfg impact` runs deterministic local analysis by default. It categorizes changed
643
+ paths, finds static references to changed values across configured records, and
644
+ reports a risk level.
645
+
646
+ Optional LLM narration lives in the separate `cfgit-impact` plugin. It reads the
647
+ real before/after of the change plus a map of the surrounding records, then
648
+ explains in plain language what the change does, what it ripples into, and how to
649
+ roll it back:
650
+
651
+ ```bash
652
+ pip install -e plugins/cfg_impact
653
+ cfg impact agent_configs:agent_planner --llm --json
654
+ ```
655
+
656
+ By default the narration reasons against the whole system. To scope it to a few
657
+ records you care about, pass `--against` (repeat it, or comma-separate). The model
658
+ then reasons about the changed record against only those selected records; no
659
+ unselected sibling record text leaves your machine:
660
+
661
+ ```bash
662
+ cfg impact agent_configs:brief_classifier \
663
+ --against agent_configs:critic --against agent_configs:shot_breakdown --llm
664
+ ```
665
+
666
+ In the web UI the same scoping is a click: select records in the left tree and the
667
+ button reads `Impact (2)`, scoping the analysis to that set.
668
+
669
+ Provider selection comes from `[connections].ai_provider` in `.cfg.toml`, unless
670
+ you pass `--provider`. `--llm` is gated by `[connections].share_with_ai`; add
671
+ the exact record id, `collection:*`, or `*` before any provider call. The plugin
672
+ supports `claude`, `openai`, and `gemini`. API keys are read from the environment
673
+ only (`ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `GEMINI_API_KEY` or `GOOGLE_API_KEY`),
674
+ never from the config file.
675
+
676
+ The core package never imports LLM provider code or vendor SDKs. That boundary is
677
+ tested.
678
+
679
+ ## Storage adapters
680
+
681
+ Mongo:
682
+
683
+ - requires a replica set or sharded cluster for transactional writes
684
+ - versions documents in configured collections
685
+ - stores history in configured history and heads collections
686
+
687
+ Postgres:
688
+
689
+ - uses ordinary ACID transactions
690
+ - expects each live table to have:
691
+ - an id column named by `id_field`
692
+ - optional scalar columns used by `live_when`
693
+ - a `doc jsonb` column containing the full record
694
+
695
+ See [docs/ADAPTERS.md](docs/ADAPTERS.md).
696
+
697
+ ## Safety model
698
+
699
+ cfgit is non-custodial. It does not stop other writers from changing the
700
+ database. It detects and reconciles those changes.
701
+
702
+ Important safety properties:
703
+
704
+ - mutating operations use adapter-level compare-and-swap checks
705
+ - commits refuse to clobber live drift
706
+ - system restore supports dry runs
707
+ - per-environment identity can stay open or require verified token/DB-principal identity
708
+ - local permissions can restrict high-blast-radius actions
709
+ - secret fields can be stripped from stored history
710
+ - core imports no DB drivers and no LLM providers
711
+
712
+ Start on a local or staging database. Do not point a new config at production
713
+ until you have run `cfg status`, `cfg import`, `cfg diff`, and restore dry runs
714
+ against a safe environment.
715
+
716
+ ## Documentation
717
+
718
+ - [docs/USAGE.md](docs/USAGE.md): command flows and examples
719
+ - [docs/CONFIGURATION.md](docs/CONFIGURATION.md): `.cfg.toml` reference
720
+ - [docs/IDENTITY_AND_ATTRIBUTION.md](docs/IDENTITY_AND_ATTRIBUTION.md): identity modes and attribution limits
721
+ - [docs/ADAPTERS.md](docs/ADAPTERS.md): Mongo and Postgres adapter details
722
+ - [docs/AGENTS.md](docs/AGENTS.md): MCP, skill, and impact plugin usage
723
+ - [docs/SPEC_CORE.md](docs/SPEC_CORE.md): project framing and v1 scope
724
+ - [docs/SPEC.md](docs/SPEC.md): deeper engine reference
725
+ - [docs/README.md](docs/README.md): full documentation index, including archived project notes and historical specs
726
+ - [docs/project-notes/findings.md](docs/project-notes/findings.md): implementation findings from the origin build
727
+ - [docs/project-notes/handoff.md](docs/project-notes/handoff.md): archived handoff notes
728
+ - [docs/archive/spec-v0.1.md](docs/archive/spec-v0.1.md): original historical spec
729
+
730
+ ## Development
731
+
732
+ ```bash
733
+ python -m venv .venv
734
+ . .venv/bin/activate
735
+ pip install -e '.[mongo,postgres,mcp,dev]'
736
+ pip install -e plugins/cfg_impact
737
+ ruff check src tests plugins/cfg_impact/cfg_impact
738
+ pytest tests/ -q
739
+ git diff --check
740
+ ```
741
+
742
+ ## License
743
+
744
+ Apache-2.0. See [LICENSE](LICENSE), [NOTICE](NOTICE), and [CREDITS.md](CREDITS.md).