@git.zone/cli 6.6.1 → 6.7.1

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.
Files changed (51) hide show
  1. package/.smartconfig.json +2 -1
  2. package/assets/templates/asset_tspack_release_gitea/.gitea/workflows/release.yml +4 -3
  3. package/dist_ts/00_commitinfo_data.js +1 -1
  4. package/dist_ts/gitzone.cli.js +2 -2
  5. package/dist_ts/helpers.workflow.d.ts +3 -0
  6. package/dist_ts/helpers.workflow.js +14 -1
  7. package/dist_ts/mod_config/index.js +4 -1
  8. package/dist_ts/mod_deprecate/helpers.deprecation.d.ts +12 -0
  9. package/dist_ts/mod_deprecate/helpers.deprecation.js +87 -0
  10. package/dist_ts/mod_deprecate/index.d.ts +1 -1
  11. package/dist_ts/mod_deprecate/index.js +77 -40
  12. package/dist_ts/mod_format/classes.baseformatter.d.ts +6 -0
  13. package/dist_ts/mod_format/classes.baseformatter.js +61 -1
  14. package/dist_ts/mod_format/classes.formatplanner.js +14 -3
  15. package/dist_ts/mod_format/classes.formatstats.d.ts +4 -1
  16. package/dist_ts/mod_format/classes.formatstats.js +11 -1
  17. package/dist_ts/mod_format/formatters/readme.formatter.d.ts +2 -1
  18. package/dist_ts/mod_format/formatters/readme.formatter.js +80 -14
  19. package/dist_ts/mod_format/index.js +2 -1
  20. package/dist_ts/mod_format/interfaces.format.d.ts +6 -2
  21. package/dist_ts/mod_format/interfaces.format.js +1 -1
  22. package/dist_ts/mod_release/classes.releasejournal.d.ts +17 -3
  23. package/dist_ts/mod_release/classes.releasejournal.js +144 -12
  24. package/dist_ts/mod_release/helpers.npmartifact.d.ts +3 -1
  25. package/dist_ts/mod_release/helpers.npmartifact.js +64 -5
  26. package/dist_ts/mod_release/helpers.releasepublication.js +21 -19
  27. package/dist_ts/mod_release/index.d.ts +24 -0
  28. package/dist_ts/mod_release/index.js +82 -22
  29. package/dist_ts/plugins.d.ts +2 -1
  30. package/dist_ts/plugins.js +3 -2
  31. package/package.json +3 -3
  32. package/readme.md +80 -4
  33. package/ts/00_commitinfo_data.ts +1 -1
  34. package/ts/gitzone.cli.ts +1 -1
  35. package/ts/helpers.workflow.ts +17 -0
  36. package/ts/mod_config/index.ts +3 -0
  37. package/ts/mod_deprecate/helpers.deprecation.ts +151 -0
  38. package/ts/mod_deprecate/index.ts +92 -41
  39. package/ts/mod_format/classes.baseformatter.ts +71 -0
  40. package/ts/mod_format/classes.formatplanner.ts +16 -3
  41. package/ts/mod_format/classes.formatstats.ts +14 -1
  42. package/ts/mod_format/formatters/readme.formatter.ts +89 -14
  43. package/ts/mod_format/index.ts +1 -0
  44. package/ts/mod_format/interfaces.format.ts +7 -2
  45. package/ts/mod_release/classes.releasejournal.ts +219 -20
  46. package/ts/mod_release/helpers.npmartifact.ts +120 -23
  47. package/ts/mod_release/helpers.releasepublication.ts +49 -15
  48. package/ts/mod_release/index.ts +127 -30
  49. package/ts/plugins.ts +2 -0
  50. package/readme.hints.md +0 -596
  51. package/readme.plan.md +0 -176
package/readme.hints.md DELETED
@@ -1,596 +0,0 @@
1
- # Gitzone CLI - Development Hints
2
-
3
- - the cli of the git.zone project.
4
-
5
- ## Project Overview
6
-
7
- Gitzone CLI (`@git.zone/cli`) is a comprehensive toolbelt for streamlining local development cycles. It provides utilities for:
8
-
9
- - Project initialization and templating (via smartscaf)
10
- - Code formatting and standardization
11
- - Version control and commit management
12
- - Docker and CI/CD integration
13
- - Meta project management
14
-
15
- ## Architecture
16
-
17
- ### Core Structure
18
-
19
- - Main CLI entry: `cli.ts` / `cli.child.ts`
20
- - Modular architecture with separate modules in `ts/mod_*` directories
21
- - Each module handles specific functionality (format, commit, docker, etc.)
22
- - Extensive use of plugins pattern via `plugins.ts` files
23
-
24
- ### Configuration Management
25
-
26
- - Uses `.smartconfig.json` for tool configuration
27
- - CLI settings live under the `@git.zone/cli` namespace
28
- - Agent and non-interactive defaults now belong under `@git.zone/cli.cli`
29
- - Project type, module metadata, release settings, commit defaults, and format settings live in the same file
30
-
31
- ### Format Module (`mod_format`) - SIGNIFICANTLY ENHANCED
32
-
33
- The format module is responsible for project standardization:
34
-
35
- #### Current Modules:
36
-
37
- 1. **cleanup** - Removes obsolete files (yarn.lock, tslint.json, etc.)
38
- 2. **copy** - File copying with glob patterns (fully implemented)
39
- 3. **gitignore** - Creates/updates .gitignore from templates
40
- 4. **license** - Checks dependency licenses for compatibility
41
- 5. **smartconfig** - Manages project metadata and configuration
42
- 6. **packagejson** - Formats and updates package.json
43
- 7. **prettier** - Applies code formatting with batching
44
- 8. **readme** - Ensures readme files exist
45
- 9. **templates** - Updates project templates based on type
46
- 10. **tsconfig** - Formats TypeScript configuration
47
-
48
- #### Execution Order (Dependency-Based):
49
-
50
- - Modules are now executed in parallel groups based on dependencies
51
- - Independent modules run concurrently for better performance
52
- - Dependency analyzer ensures correct execution order
53
-
54
- ### New Architecture Features
55
-
56
- 1. **BaseFormatter Pattern**: All formatters extend abstract BaseFormatter class
57
- 2. **FormatContext**: Central state management across all modules
58
- 3. **FormatPlanner**: Implements plan → action workflow
59
- 4. **RollbackManager**: Full backup/restore capabilities
60
- 5. **ChangeCache**: Tracks file changes to optimize performance
61
- 6. **DependencyAnalyzer**: Manages module execution order
62
- 7. **DiffReporter**: Generates diff views for changes
63
- 8. **FormatStats**: Comprehensive execution statistics
64
-
65
- ### Key Patterns
66
-
67
- 1. **Plugin Architecture**: All dependencies imported through `plugins.ts` files
68
- 2. **Streaming**: Uses smartstream for file processing
69
- 3. **Interactive Prompts**: smartinteract for user input
70
- 4. **Enhanced Error Handling**: Comprehensive try-catch with automatic rollback
71
- 5. **Template System**: Templates handled by smartscaf, not directly by gitzone
72
- 6. **Type Safety**: Full TypeScript with interfaces and type definitions
73
-
74
- ### Important Notes
75
-
76
- - `.nogit/` directory used for temporary/untracked files, backups, and cache
77
- - `.nogit/gitzone-backups/` stores format operation backups
78
- - `.nogit/gitzone-cache/` stores file change cache
79
- - Templates are managed by smartscaf - improvements should be made there
80
- - License checking configurable with exceptions support
81
- - All features implemented: `ensureDependency`, copy module, etc.
82
-
83
- ## Recent Improvements (Completed)
84
-
85
- 1. **Plan → Action Workflow**: Shows changes before applying them
86
- 2. **Rollback Mechanism**: Full backup and restore on failures
87
- 3. **Enhanced Configuration**: Granular control via `.smartconfig.json`
88
- 4. **Better Error Handling**: Detailed errors with recovery options
89
- 5. **Performance Optimizations**: Parallel execution and caching
90
- 6. **Reporting**: Diff views, statistics, verbose logging
91
- 7. **Architecture**: Clean separation of concerns with new classes
92
- 8. **Split Commit/Release Workflows**: `commit` creates source commits; `release` owns versioning, tags, and artifact publishing
93
-
94
- ### Commit/Release Workflow Refactor (Latest)
95
-
96
- The commit module no longer bumps versions, creates tags, or publishes packages. Release work now belongs to `gitzone release`:
97
-
98
- **Changes:**
99
-
100
- - `gitzone commit` analyzes changes, updates `changelog.md` `Pending`, commits, and optionally pushes.
101
- - `gitzone release` reads `Pending`, bumps versions, moves changelog entries into a version section, tags, pushes, and publishes configured artifacts.
102
- - Commit workflow steps are configured in `.smartconfig.json` under `@git.zone/cli.commit.steps`.
103
- - Smartconfig schema versioning lives at `@git.zone/cli.schemaVersion`; run `gitzone config migrate <version>` for targeted migrations.
104
- - Release publishing is target-based under `@git.zone/cli.release.targets`.
105
- - NPM registries only live under `@git.zone/cli.release.targets.npm.registries`.
106
-
107
- ### Exact artifact release journal schemas 1 and 2
108
-
109
- Every release that reaches final publication atomically installs
110
- canonical state below the Git common directory at
111
- `gitzone/releases/v1/v<version>/`. npm releases contain exactly one
112
- `package.tgz`; the journal binds that file's package identity, byte length,
113
- SHA-1, SHA-256, SHA-512 integrity, release commit, annotated tag object, hashed
114
- Git destination, registry list, and target attempts. The state is deliberately
115
- outside the worktree so build cleanliness checks do not conflict with durable
116
- recovery.
117
-
118
- Non-Docker releases retain journal schema 1 byte-for-byte. Docker releases use
119
- schema 2 in the same storage tree. Before confirmation or source mutation,
120
- GitZone validates the deterministic tSDocker request against the source commit;
121
- it validates the final release-commit request again immediately before journal
122
- installation. Schema 2 then persists immutable candidate and OCI graph evidence
123
- plus the complete ordered promotion set before Git or npm publication.
124
- Each destination promotion is write-ahead claimed, remotely reconciled by exact
125
- digest, and append-only. Positive destination conflict is terminal. Candidate
126
- cleanup of a qualified result is journaled only after every promotion is
127
- verified, except that a terminal qualification destination conflict permits
128
- cleanup while Git/npm stay blocked. Completed Docker state is terminal.
129
-
130
- Journal writes are fsynced same-directory replacements under the shared
131
- atomic-mkdir lock and require the caller's exact prior revision. Transactions
132
- may update target attempts and completion state but cannot alter release,
133
- artifact, destination, or target identity. A malformed, noncanonical, future,
134
- or manually reformatted journal fails closed.
135
-
136
- Selected Git publication requires a canonical remote name and validates its
137
- single resolved push URL before remote contact, including during planning.
138
- Embedded HTTP(S) credentials, passwords, parameters, and unsupported protocols
139
- fail closed. Git publication then probes the exact branch, annotated tag
140
- object, and peeled tag commit before and after an atomic leased push. npm publication always uses the
141
- stored tarball and verifies each public registry anonymously with redirects
142
- disabled. Verification covers metadata identity, integrity and shasum, bounded
143
- downloaded bytes, SHA-256, and the `latest` dist-tag.
144
-
145
- `gitzone release inspect [version]` is read-only. `gitzone release resume
146
- <version>` rejects fresh-release overrides and never rebuilds or repacks the npm
147
- artifact. It also rejects changed journaled configuration. A nonterminal
148
- schema-2 resume canonical-compares the current request, requires matching
149
- project-local tSDocker package and binary versions `>=3.5.1` plus all required
150
- protocol-v1 capabilities, and validates the journaled request before any
151
- recovery. Additional future capabilities are accepted. A completed schema-2
152
- journal trusts terminal cleanup evidence without requiring the old candidate or
153
- current Docker configuration. A target left in `publishing` state requires the
154
- exact recorded attempt ID and independent proof that its process stopped; no
155
- timeout or PID guess reclaims publication authority. Recovery reclaims only
156
- private request files bound to that exact retired attempt before a CAS transition
157
- claims a fresh owner. Promotion recovery probes exact digest state before
158
- retrying and retains the old owner on inconclusive evidence. A tSDocker
159
- `RECOVERY_REQUIRED` qualification has no completed evidence, so its exact
160
- recovered owner removes only the incomplete `preparing` record before a fresh
161
- qualification attempt. Final qualified-candidate cleanup remains ordered after
162
- promotion.
163
-
164
- Recovery begins only after atomic journal installation. Local
165
- version, changelog, commit, tag, build, and pack failures before that point, as
166
- well as the pre-release `--merge` integration push, require explicit operator
167
- reconciliation; they are not represented as publication attempts.
168
-
169
- Schema 1 supports Git and public npm; npm publication requires resolved pnpm
170
- 11.25.0, 12.1.0, or 12.3.4 and its qualified pack/publish contract, while
171
- Git-only journals do not. Schema 2 adds Docker qualification,
172
- ordered promotion, and cleanup. Docker releases
173
- cannot use `--merge` because its pre-release push would violate qualification
174
- ordering, and `release.targets.docker.noBuild` must remain false because
175
- qualification always builds. Private npm cannot be anonymously verified.
176
- Legacy tag-triggered `npmci npm publish` jobs must be removed because they
177
- bypass journal ownership.
178
-
179
- **Benefits:**
180
-
181
- - Commit is safer and has no publishing side effects.
182
- - Multiple source commits can accumulate into one release via `Pending`.
183
- - Durable target states distinguish pending, publishing, verified, failed,
184
- conflicting, and skipped publication while retaining exact attempt evidence.
185
-
186
- ### Auto-Accept Flag for Commits
187
-
188
- The commit module now supports `-y/--yes` flag for non-interactive commits:
189
-
190
- **Usage:**
191
-
192
- - `gitzone commit -y` - Auto-accepts AI recommendations without prompts
193
- - `gitzone commit -yp` - Auto-accepts and pushes to origin
194
- - Separate `-p/--push` flag controls push behavior
195
-
196
- **Implementation:**
197
-
198
- - Creates AnswerBucket programmatically when `-y` flag detected
199
- - Preserves all UI output for transparency
200
- - Fully backward compatible with interactive mode
201
- - CI/CD friendly for automated workflows
202
-
203
- ## Destructive Command Policy
204
-
205
- `gitzone docker prune` used to be a single line:
206
-
207
- ```ts
208
- await smartshellInstance.exec(`docker system prune -a -f --volumes`);
209
- ```
210
-
211
- Machine-wide, forced, volumes included, behind a command described as "Run
212
- Docker-related maintenance tasks". On a shared host that is unrecoverable data
213
- loss with no prompt. It is now allowlist-scoped (`classes.dockerpruner.ts`).
214
-
215
- The policy every destructive path in this CLI should follow:
216
-
217
- 1. **Scope by positive evidence, never by absence.** Start from an allowlist —
218
- a label, a registry claim, an explicit target — not from "everything unused".
219
- `DockerPruner.isToolOwned` requires _both_ `git.zone.tool` (provenance) and
220
- `git.zone.safe-to-prune=true` (consent); either alone is insufficient.
221
- 2. **Report by default, destroy behind `--apply`.**
222
- 3. **Persisted data needs its own gate.** Volumes and data directories are
223
- excluded unless separately requested, and additionally require a typed `yes`
224
- or `--yes`. The gate is enforced before the output branches so JSON mode
225
- cannot bypass it.
226
- 4. **Re-verify at apply time** and throw on drift rather than proceeding.
227
- 5. **Ambiguity excludes.** Unprovable ownership means skip, never remove.
228
- 6. **The name must match the blast radius.** A destructive command described as
229
- "cleanup" or "maintenance" is the actual root cause of accidental invocation.
230
-
231
- Known remaining gaps are listed in `readme.plan.md`.
232
-
233
- ## Services Module (`mod_services`) — Cleanup Design
234
-
235
- ### Why data accumulated
236
-
237
- `gitzone services clean` historically failed for service data written by a
238
- container uid. A recursive delete run as the invoking user removed only the
239
- part of the tree it owned. For MongoDB the result was a half-deleted WiredTiger
240
- dataset that crash-looped on the next start (`WiredTigerHS.wt file is corrupted
241
- or missing`), kept alive indefinitely by `restart: unless-stopped`. Users hit a
242
- failing `clean`, gave up, and the data stayed. This was the root cause of
243
- multi-GB accumulation, not a missing feature.
244
-
245
- `DockerContainer.removeDataDirectory` fixes it by persisting a deletion intent
246
- and atomically renaming the canonical path to a tokenized quarantine before any
247
- recursive delete. Native deletion runs there; if the quarantine survives, a
248
- short-lived root container mounts only that directory. The helper uses
249
- shell-free Docker argv, stopped creation, exact configuration and label
250
- inspection, and an immutable-ID fence before execution or cleanup. Interrupted
251
- cleanup resumes the recorded quarantine, so partial work is never mistaken for
252
- a usable canonical dataset.
253
-
254
- ### Identifying tool-owned resources
255
-
256
- Follows the `git.zone.*` label convention already established by
257
- `@git.zone/tsdocker`. Containers created by `gitzone services` carry:
258
-
259
- ```text
260
- git.zone.tool=gitzone-services
261
- git.zone.service=mongodb|objectstorage|elasticsearch
262
- git.zone.project-path=<abs path>
263
- git.zone.data-path=<abs path>
264
- git.zone.safe-to-prune=true
265
- ```
266
-
267
- Data directories are additionally claimed by a marker at
268
- `<project>/.nogit/.gitzone-services.json`. The marker deliberately lives outside
269
- the bind-mounted directory so it can never confuse mongod, ObjectStorage or
270
- Elasticsearch at runtime.
271
-
272
- Nothing is ever matched by image or by bare name pattern. MongoDB and
273
- Elasticsearch containers predating labels are identified only when exactly one
274
- registry entry claims their name. ObjectStorage always requires exact labels.
275
-
276
- ### Prune safety model (`classes.servicepruner.ts`)
277
-
278
- Mirrors `TsDockerPruner`: build a plan, print it, and mutate only on `--apply`
279
- with every item re-verified immediately before removal.
280
-
281
- Projects classify as `live`, `stale`, `orphaned`, or `unknown`. Only `stale` and
282
- `orphaned` are candidates; `unknown` never is. Ambiguity must _tighten_ the
283
- decision — a container name claimed by two projects forces both to `unknown`,
284
- because an unattributable container also means "no container is running" cannot
285
- be proven. Getting this backwards initially made 1.18 GB look reclaimable when
286
- it was not.
287
-
288
- Invariants, enforced at plan time and again at apply time:
289
-
290
- - A data directory is never removed while any running container bind-mounts it
291
- or an overlapping path (`helpers.pathsOverlap`).
292
- - A path must match `<project>/.nogit/{mongodata,objectstoragedata,esdata}` exactly
293
- (`isSafeServiceDataPath`); this is an allowlist, checked after resolution.
294
- - Ownership must be proven by marker or registry entry. ObjectStorage is
295
- stricter: an exact marker entry is required for deletion, but an exactly
296
- label-owned canonical container can repair a missing marker before removal.
297
- - Data-directory staleness is re-checked at apply time. Container removal
298
- separately rechecks immutable identity, running state, ownership, and legacy
299
- classification before mutation.
300
- - An unreachable Docker daemon disables container, data, and registry
301
- reclamation, so ambiguity never reads as absence.
302
-
303
- Legacy `.nogit/miniodata` is deliberately outside the allowlist. Marker
304
- migration retains that path with `safeToPrune: false`; registry migration
305
- retains the legacy container reference separately. The service and general
306
- Docker pruners reject legacy MinIO containers, and service prune rejects
307
- bind-operation helpers again at apply time.
308
-
309
- ### ObjectStorage migration and lifecycle
310
-
311
- `objectstorage` is the canonical service identifier and `s3` is its user-facing
312
- alias. Persisted `minio` and `s3` entries migrate to the same canonical flat
313
- array value because `@git.zone/cli.services` remains a tsdeploy capability
314
- input. New CLI input does not accept the provider name `minio`.
315
-
316
- The active container is `<project>-objectstorage`, its data path is
317
- `.nogit/objectstoragedata`, and its image is pinned by manifest-list digest.
318
- Ports `9000` and `3000` are published as the configured API and UI ports on
319
- `127.0.0.1`. `S3_ADMIN_PASSWORD`, `S3_REGION`, and `S3_UI_PORT` are
320
- ObjectStorage-specific runtime fields. Existing generic fields such as
321
- `S3_ENDPOINT`, `S3_HOST`, and `S3_USESSL` are preserved rather than silently
322
- rewritten; internal reconciliation always targets loopback explicitly.
323
-
324
- Startup first rejects legacy `<project>-minio` containers, registry-retained
325
- alternate legacy names, and `.nogit/miniodata`, then proves exact labels on any
326
- canonical same-name container. Exact container proof can repair a missing valid
327
- data marker; invalid or foreign markers remain blocking. Drift reconciliation
328
- covers the complete runtime contract, including
329
- the exact set of `OBJST_*` and `UI_PORT` controls while allowing unrelated image
330
- environment, and all subsequent Docker mutations use the discovered immutable
331
- ID. A shared 30-second deadline bounds Docker setup, `/readyz`, authenticated
332
- bucket lookup/creation, and verification. SmartBucket provides its own bounded,
333
- idempotent client cleanup. A pre-existing ID enters rollback only after `docker
334
- start` succeeds; an uncertain pre-existing start remains adoptable because
335
- state inspection cannot prove which concurrent invocation caused the transition.
336
-
337
- The v2 marker and global registry schemas separate canonical ObjectStorage from
338
- legacy MinIO evidence. Legacy evidence is detection-only: never activate it,
339
- reinterpret its disk data, pass it to lifecycle methods, or make it reclaimable.
340
- Migration validates every selected store before the first write, then revalidates
341
- each store at its own apply boundary. Closed-schema selection, marker, and
342
- registry state rejects malformed, foreign, conflicting, or future shapes.
343
- Runtime config validates known fields while preserving unknown fields. The
344
- global registry uses a shared atomic-mkdir transaction lock, fresh raw reads,
345
- fsynced same-directory
346
- replacement writes, and compare-delete for unregister operations. Lock ownership
347
- is token-checked and release first renames to an invocation tombstone. Stale locks
348
- are never broken automatically; the error reports the exact lock path for manual
349
- inspection after the recorded process is known to be gone.
350
-
351
- The same lock primitive protects runtime-config migration and saves, marker
352
- migration and ownership recording, and each service's start/delete data-path
353
- critical section. Runtime config saves compare the bytes loaded by that instance
354
- with the current file before replacement, so a stale command cannot overwrite a
355
- newer port or credential change. Marker writers re-read inside the lock and merge
356
- claims. Start and stop refresh config inside a global per-project/service lock.
357
- Data deletion rechecks labeled stopped containers and all configured mounts
358
- inside that lock; a preserved stopped container blocks its project's data from
359
- becoming reclaimable. Before recursive deletion, an exact persisted intent
360
- atomically moves the canonical directory to a tokenized quarantine. Interrupted
361
- or partial cleanup resumes only that recorded path and cannot leave a corrupt
362
- canonical dataset. Every service startup rejects a pending deletion intent so a
363
- fresh canonical directory cannot strand quarantined data.
364
-
365
- Bind-operation helpers use one deterministic Docker name per host target as an
366
- atomic helper-level lock. Each create adds a random invocation label and a
367
- stable ownership-spec label. Uncertain creates are polled within the rollback
368
- deadline and may be removed only when the invocation label matches. A later
369
- operation may remove an old stopped canonical helper by non-forced immutable-ID
370
- removal; fresh, running, or noncanonical occupants fail closed. This lock covers
371
- the root helper operations, not the entire service start/clean command.
372
-
373
- ### MongoDB auth modes
374
-
375
- Default is authenticated, single-node replica set with a keyfile.
376
- `gitzone services auth mongodb off` opts into a no-auth instance for runtimes
377
- that cannot complete a SCRAM handshake over `node:crypto` (Deno). In that mode
378
- the port is published on `127.0.0.1` only — publishing scope is the real
379
- exposure control, since `--bind_ip_all` binds inside the container netns — and a
380
- non-local `MONGODB_HOST` is refused. `MONGO_INITDB_ROOT_*` must be omitted in
381
- no-auth mode because the official entrypoint turns them into `--auth`.
382
-
383
- Re-enabling auth over data created without it finds no root user, because
384
- `MONGO_INITDB_ROOT_*` only applies to an empty dbpath. `ensureMongoRootUser`
385
- bootstraps it through MongoDB's localhost exception, which by design only works
386
- while zero users exist and therefore cannot escalate anything.
387
-
388
- ### Per-service configuration lives in a sibling key
389
-
390
- `@git.zone/cli.serviceOptions` holds committed per-service configuration
391
- (currently `mongodb.auth`). It is a **sibling** of `services`, not a richer
392
- `services` value, because widening `services` breaks deployments — see the
393
- coupling note below. Verified empirically: a mixed array `[{name:'mongodb'},…]`
394
- and an object-shaped `services` both make TsDeploy throw.
395
-
396
- Precedence is `.smartconfig.json` declaration → `.nogit/env.json` local value →
397
- default enabled. The declaration wins so a fresh checkout is reproducible; the
398
- local fallback keeps projects configured under 2.24.0 working. Malformed
399
- declarations are ignored rather than throwing, and ignoring always resolves to
400
- the safe default. `setMongoAuthEnabled` writes both files so they cannot drift.
401
-
402
- An older CLI ignores `serviceOptions` entirely and gets auth-enabled MongoDB —
403
- the failure direction is toward the secure default.
404
-
405
- ### Coupling: services config is a deployment input
406
-
407
- `@git.zone/cli.services` is read by `@git.zone/tsdeploy`
408
- (`deriveRequiredCapabilities` in `classes.cloudlydeployment.ts`) to derive a
409
- workload's `requiredCapabilities`. It **throws** unless the value is a flat array
410
- of unique, non-empty, lowercase canonical strings. Never add sub-keys under it
411
- and never change the persisted names — turning it into an object would fail real
412
- deployments. Any new services configuration belongs in `.nogit/env.json` or a
413
- sibling key.
414
-
415
- ## Development Tips
416
-
417
- - Always check readme.plan.md for ongoing improvement plans
418
- - Use `.smartconfig.json` for any new configuration options
419
- - Keep modules focused and single-purpose
420
- - Maintain the existing plugin pattern for dependencies
421
- - Test format operations on sample projects before deploying
422
- - Consider backward compatibility when changing configuration structure
423
- - Use BaseFormatter pattern for new format modules
424
- - Leverage FormatContext for cross-module state sharing
425
-
426
- ## Configuration Examples
427
-
428
- ```json
429
- {
430
- "@git.zone/cli": {
431
- "cli": {
432
- "interactive": true,
433
- "output": "human",
434
- "checkUpdates": true
435
- },
436
- "format": {
437
- "interactive": true,
438
- "showStats": true,
439
- "modules": {
440
- "skip": ["prettier"],
441
- "only": []
442
- }
443
- }
444
- }
445
- }
446
- ```
447
-
448
- ## CLI Usage
449
-
450
- ### Commit Commands
451
-
452
- ```bash
453
- # Interactive commit (default)
454
- gitzone commit
455
-
456
- # Read-only recommendation
457
- gitzone commit recommend --json
458
-
459
- # Auto-accept AI recommendations (no prompts)
460
- gitzone commit -y
461
- gitzone commit --yes
462
-
463
- # Auto-accept and push to origin
464
- gitzone commit -yp
465
- gitzone commit -y -p
466
- gitzone commit --yes --push
467
-
468
- # Run format before commit
469
- gitzone commit --format
470
- ```
471
-
472
- ### Format Commands
473
-
474
- ```bash
475
- # Basic format
476
- gitzone format
477
-
478
- # Read-only JSON plan
479
- gitzone format plan --json
480
-
481
- # CI-friendly check, exits non-zero when changes or validator errors remain
482
- gitzone format check
483
-
484
- # Dry run to preview changes
485
- gitzone format --dry-run
486
-
487
- # Limit formatter modules
488
- gitzone format --only prettier,packagejson
489
- gitzone format --skip license
490
-
491
- # Non-interactive apply
492
- gitzone format --write --yes
493
-
494
- # Deterministic format first, opencode for remaining issues
495
- gitzone format fix
496
-
497
- # Plan only (no execution)
498
- gitzone format --plan-only
499
-
500
- # Save plan for later
501
- gitzone format --save-plan format.json
502
-
503
- # Execute saved plan
504
- gitzone format --from-plan format.json
505
-
506
- # Verbose mode
507
- gitzone format --verbose
508
-
509
- # Detailed diff views
510
- gitzone format --detailed
511
-
512
- # Inspect config for agents and scripts
513
- gitzone config show --json
514
- gitzone config set cli.output json
515
- gitzone config get release.targets.npm.accessLevel
516
- ```
517
-
518
- ## Common Issues (Now Resolved)
519
-
520
- 1. ✅ Format operations are now reversible with rollback
521
- 2. ✅ Enhanced error messages with recovery suggestions
522
- 3. ✅ All modules fully implemented (including copy)
523
- 4. ✅ Dry-run capability available
524
- 5. ✅ Extensive configuration options available
525
-
526
- ## Future Considerations
527
-
528
- - Plugin system for custom formatters
529
- - Git hooks integration for pre-commit formatting
530
- - Advanced UI with interactive configuration
531
- - Format presets for common scenarios
532
- - Performance benchmarking tools
533
-
534
- ## API Changes
535
-
536
- ### Smartfile v13 Migration (Latest - Completed)
537
-
538
- The project has been fully migrated from @push.rocks/smartfile v11 to v13, which introduced a major breaking change where filesystem operations were split into two separate packages:
539
-
540
- **Packages:**
541
-
542
- - `@push.rocks/smartfile` v13.1.3 - File representation classes (SmartFile, StreamFile, VirtualDirectory)
543
- - `@push.rocks/smartfs` v1.6.0 - Filesystem operations (read, write, exists, stat, etc.)
544
-
545
- **Key API Changes:**
546
-
547
- 1. **File Reading**:
548
- - Old: `plugins.smartfile.fs.toStringSync(path)` or `plugins.smartfile.fs.toObjectSync(path)`
549
- - New: `await plugins.smartfs.file(path).encoding('utf8').read()` + JSON.parse if needed
550
- - Important: `read()` returns `string | Buffer` - use `as string` type assertion when encoding is set
551
-
552
- 2. **File Writing**:
553
- - Old: `plugins.smartfile.memory.toFs(content, path)` or `plugins.smartfile.memory.toFsSync(content, path)`
554
- - New: `await plugins.smartfs.file(path).encoding('utf8').write(content)`
555
-
556
- 3. **File Existence**:
557
- - Old: `plugins.smartfile.fs.fileExists(path)` or `plugins.smartfile.fs.fileExistsSync(path)`
558
- - New: `await plugins.smartfs.file(path).exists()`
559
-
560
- 4. **Directory Operations**:
561
- - Old: `plugins.smartfile.fs.ensureDir(path)`
562
- - New: `await plugins.smartfs.directory(path).recursive().create()`
563
- - Old: `plugins.smartfile.fs.remove(path)`
564
- - New: `await plugins.smartfs.directory(path).recursive().delete()` or `await plugins.smartfs.file(path).delete()`
565
-
566
- 5. **Directory Listing**:
567
- - Old: `plugins.smartfile.fs.listFolders(path)` or `plugins.smartfile.fs.listFoldersSync(path)`
568
- - New: `await plugins.smartfs.directory(path).list()` then filter by `stats.isDirectory`
569
- - Note: `list()` returns `IDirectoryEntry[]` with `path` and `name` properties - use `stat()` to check if directory
570
-
571
- 6. **File Stats**:
572
- - Old: `stats.isDirectory()` (method)
573
- - New: `stats.isDirectory` (boolean property)
574
- - Old: `stats.mtimeMs`
575
- - New: `stats.mtime.getTime()`
576
-
577
- 7. **SmartFile Factory**:
578
- - Old: Direct SmartFile instantiation
579
- - New: `plugins.smartfile.SmartFileFactory.nodeFs()` then factory methods
580
-
581
- **Migration Pattern:**
582
- All sync methods must become async. Functions that were previously synchronous (like `getProjectName()`) now return `Promise<T>` and must be awaited.
583
-
584
- **Affected Modules:**
585
-
586
- - ts/mod_format/\* (largest area - 15+ files)
587
- - ts/mod_commit/\* and ts/mod_release/\* (commit/release workflows)
588
- - ts/mod_services/\* (configuration management)
589
- - ts/mod_meta/\* (meta repository management)
590
- - ts/mod_standard/\* (template listing)
591
- - ts/mod_template/\* (template operations)
592
-
593
- **Previous API Changes:**
594
-
595
- - smartnpm requires instance creation: `new NpmRegistry()`
596
- - Type imports use `import type` for proper verbatim module syntax