@quonfig/cli 0.0.35 → 0.0.37

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.
package/README.md CHANGED
@@ -14,7 +14,7 @@ $ npm install -g @quonfig/cli
14
14
  $ qfg COMMAND
15
15
  running command...
16
16
  $ qfg (--version)
17
- @quonfig/cli/0.0.35 linux-x64 node-v24.4.1
17
+ @quonfig/cli/0.0.37 linux-x64 node-v24.4.1
18
18
  $ qfg --help [COMMAND]
19
19
  USAGE
20
20
  $ qfg COMMAND
@@ -91,7 +91,7 @@ EXAMPLES
91
91
  $ qfg config-schema --json-schema # full JSON Schema document (copy into your editor)
92
92
  ```
93
93
 
94
- _See code: [src/commands/config-schema.ts](https://github.com/quonfig/cli/blob/v0.0.35/src/commands/config-schema.ts)_
94
+ _See code: [src/commands/config-schema.ts](https://github.com/quonfig/cli/blob/v0.0.37/src/commands/config-schema.ts)_
95
95
 
96
96
  ## `qfg create NAME`
97
97
 
@@ -176,7 +176,7 @@ EXAMPLES
176
176
  $ qfg set-rollout my.new.flag --environment production --true-percent 20
177
177
  ```
178
178
 
179
- _See code: [src/commands/create.ts](https://github.com/quonfig/cli/blob/v0.0.35/src/commands/create.ts)_
179
+ _See code: [src/commands/create.ts](https://github.com/quonfig/cli/blob/v0.0.37/src/commands/create.ts)_
180
180
 
181
181
  ## `qfg delete NAME`
182
182
 
@@ -222,7 +222,7 @@ EXAMPLES
222
222
  $ qfg delete my.config --yes
223
223
  ```
224
224
 
225
- _See code: [src/commands/delete.ts](https://github.com/quonfig/cli/blob/v0.0.35/src/commands/delete.ts)_
225
+ _See code: [src/commands/delete.ts](https://github.com/quonfig/cli/blob/v0.0.37/src/commands/delete.ts)_
226
226
 
227
227
  ## `qfg flag info [NAME]`
228
228
 
@@ -425,7 +425,7 @@ EXAMPLES
425
425
  $ qfg generate --targets node-ts -o ./dist # combine with targets
426
426
  ```
427
427
 
428
- _See code: [src/commands/generate.ts](https://github.com/quonfig/cli/blob/v0.0.35/src/commands/generate.ts)_
428
+ _See code: [src/commands/generate.ts](https://github.com/quonfig/cli/blob/v0.0.37/src/commands/generate.ts)_
429
429
 
430
430
  ## `qfg generate-new-hex-key`
431
431
 
@@ -448,7 +448,7 @@ EXAMPLES
448
448
  $ qfg generate-new-hex-key
449
449
  ```
450
450
 
451
- _See code: [src/commands/generate-new-hex-key.ts](https://github.com/quonfig/cli/blob/v0.0.35/src/commands/generate-new-hex-key.ts)_
451
+ _See code: [src/commands/generate-new-hex-key.ts](https://github.com/quonfig/cli/blob/v0.0.37/src/commands/generate-new-hex-key.ts)_
452
452
 
453
453
  ## `qfg get [NAME]`
454
454
 
@@ -480,7 +480,7 @@ EXAMPLES
480
480
  $ qfg get my.config.name --environment=production
481
481
  ```
482
482
 
483
- _See code: [src/commands/get.ts](https://github.com/quonfig/cli/blob/v0.0.35/src/commands/get.ts)_
483
+ _See code: [src/commands/get.ts](https://github.com/quonfig/cli/blob/v0.0.37/src/commands/get.ts)_
484
484
 
485
485
  ## `qfg info [NAME]`
486
486
 
@@ -528,7 +528,7 @@ EXAMPLES
528
528
  $ qfg info my.config.name --exclude-evaluations # skip 24h stats
529
529
  ```
530
530
 
531
- _See code: [src/commands/info.ts](https://github.com/quonfig/cli/blob/v0.0.35/src/commands/info.ts)_
531
+ _See code: [src/commands/info.ts](https://github.com/quonfig/cli/blob/v0.0.37/src/commands/info.ts)_
532
532
 
533
533
  ## `qfg init [DIRECTORY]`
534
534
 
@@ -568,7 +568,7 @@ EXAMPLES
568
568
  $ qfg init --dry-run
569
569
  ```
570
570
 
571
- _See code: [src/commands/init.ts](https://github.com/quonfig/cli/blob/v0.0.35/src/commands/init.ts)_
571
+ _See code: [src/commands/init.ts](https://github.com/quonfig/cli/blob/v0.0.37/src/commands/init.ts)_
572
572
 
573
573
  ## `qfg interactive`
574
574
 
@@ -598,7 +598,7 @@ EXAMPLES
598
598
  $ qfg
599
599
  ```
600
600
 
601
- _See code: [src/commands/interactive.ts](https://github.com/quonfig/cli/blob/v0.0.35/src/commands/interactive.ts)_
601
+ _See code: [src/commands/interactive.ts](https://github.com/quonfig/cli/blob/v0.0.37/src/commands/interactive.ts)_
602
602
 
603
603
  ## `qfg list`
604
604
 
@@ -638,7 +638,7 @@ EXAMPLES
638
638
  $ qfg list --feature-flags
639
639
  ```
640
640
 
641
- _See code: [src/commands/list.ts](https://github.com/quonfig/cli/blob/v0.0.35/src/commands/list.ts)_
641
+ _See code: [src/commands/list.ts](https://github.com/quonfig/cli/blob/v0.0.37/src/commands/list.ts)_
642
642
 
643
643
  ## `qfg log-level NAME`
644
644
 
@@ -703,7 +703,7 @@ EXAMPLES
703
703
  $ qfg log-level log-level.my-app --target=Chatty --value=INFO --environment=production
704
704
  ```
705
705
 
706
- _See code: [src/commands/log-level.ts](https://github.com/quonfig/cli/blob/v0.0.35/src/commands/log-level.ts)_
706
+ _See code: [src/commands/log-level.ts](https://github.com/quonfig/cli/blob/v0.0.37/src/commands/log-level.ts)_
707
707
 
708
708
  ## `qfg login`
709
709
 
@@ -728,7 +728,7 @@ EXAMPLES
728
728
  $ qfg login --profile myprofile
729
729
  ```
730
730
 
731
- _See code: [src/commands/login.ts](https://github.com/quonfig/cli/blob/v0.0.35/src/commands/login.ts)_
731
+ _See code: [src/commands/login.ts](https://github.com/quonfig/cli/blob/v0.0.37/src/commands/login.ts)_
732
732
 
733
733
  ## `qfg logout`
734
734
 
@@ -751,7 +751,7 @@ EXAMPLES
751
751
  $ qfg logout
752
752
  ```
753
753
 
754
- _See code: [src/commands/logout.ts](https://github.com/quonfig/cli/blob/v0.0.35/src/commands/logout.ts)_
754
+ _See code: [src/commands/logout.ts](https://github.com/quonfig/cli/blob/v0.0.37/src/commands/logout.ts)_
755
755
 
756
756
  ## `qfg migrate`
757
757
 
@@ -805,7 +805,7 @@ EXAMPLES
805
805
  $ qfg migrate --from launch --api-key $LAUNCH_API_KEY --dir ./quonfig-repo --staging
806
806
  ```
807
807
 
808
- _See code: [src/commands/migrate.ts](https://github.com/quonfig/cli/blob/v0.0.35/src/commands/migrate.ts)_
808
+ _See code: [src/commands/migrate.ts](https://github.com/quonfig/cli/blob/v0.0.37/src/commands/migrate.ts)_
809
809
 
810
810
  ## `qfg migrate doctor`
811
811
 
@@ -843,7 +843,7 @@ EXAMPLES
843
843
  $ qfg migrate doctor --json
844
844
  ```
845
845
 
846
- _See code: [src/commands/migrate/doctor.ts](https://github.com/quonfig/cli/blob/v0.0.35/src/commands/migrate/doctor.ts)_
846
+ _See code: [src/commands/migrate/doctor.ts](https://github.com/quonfig/cli/blob/v0.0.37/src/commands/migrate/doctor.ts)_
847
847
 
848
848
  ## `qfg migrate my-code`
849
849
 
@@ -875,7 +875,7 @@ EXAMPLES
875
875
  $ qfg migrate my-code --dry-run
876
876
  ```
877
877
 
878
- _See code: [src/commands/migrate/my-code.ts](https://github.com/quonfig/cli/blob/v0.0.35/src/commands/migrate/my-code.ts)_
878
+ _See code: [src/commands/migrate/my-code.ts](https://github.com/quonfig/cli/blob/v0.0.37/src/commands/migrate/my-code.ts)_
879
879
 
880
880
  ## `qfg migrate status`
881
881
 
@@ -906,7 +906,7 @@ EXAMPLES
906
906
  $ qfg migrate status --json
907
907
  ```
908
908
 
909
- _See code: [src/commands/migrate/status.ts](https://github.com/quonfig/cli/blob/v0.0.35/src/commands/migrate/status.ts)_
909
+ _See code: [src/commands/migrate/status.ts](https://github.com/quonfig/cli/blob/v0.0.37/src/commands/migrate/status.ts)_
910
910
 
911
911
  ## `qfg override [NAME] [VALUE]`
912
912
 
@@ -961,7 +961,7 @@ EXAMPLES
961
961
  $ qfg override my.flag true --env=staging
962
962
  ```
963
963
 
964
- _See code: [src/commands/override.ts](https://github.com/quonfig/cli/blob/v0.0.35/src/commands/override.ts)_
964
+ _See code: [src/commands/override.ts](https://github.com/quonfig/cli/blob/v0.0.37/src/commands/override.ts)_
965
965
 
966
966
  ## `qfg pull`
967
967
 
@@ -1008,7 +1008,7 @@ EXAMPLES
1008
1008
  $ qfg pull # uses QUONFIG_DIR env var
1009
1009
  ```
1010
1010
 
1011
- _See code: [src/commands/pull.ts](https://github.com/quonfig/cli/blob/v0.0.35/src/commands/pull.ts)_
1011
+ _See code: [src/commands/pull.ts](https://github.com/quonfig/cli/blob/v0.0.37/src/commands/pull.ts)_
1012
1012
 
1013
1013
  ## `qfg push`
1014
1014
 
@@ -1056,7 +1056,7 @@ EXAMPLES
1056
1056
  $ qfg push --dir ./our-config --yes
1057
1057
  ```
1058
1058
 
1059
- _See code: [src/commands/push.ts](https://github.com/quonfig/cli/blob/v0.0.35/src/commands/push.ts)_
1059
+ _See code: [src/commands/push.ts](https://github.com/quonfig/cli/blob/v0.0.37/src/commands/push.ts)_
1060
1060
 
1061
1061
  ## `qfg schema NAME`
1062
1062
 
@@ -1094,7 +1094,7 @@ EXAMPLES
1094
1094
  $ qfg schema my-schema --set-json-schema=@schemas/my-schema.json --protected
1095
1095
  ```
1096
1096
 
1097
- _See code: [src/commands/schema.ts](https://github.com/quonfig/cli/blob/v0.0.35/src/commands/schema.ts)_
1097
+ _See code: [src/commands/schema.ts](https://github.com/quonfig/cli/blob/v0.0.37/src/commands/schema.ts)_
1098
1098
 
1099
1099
  ## `qfg sdk-key`
1100
1100
 
@@ -1121,7 +1121,7 @@ EXAMPLES
1121
1121
  $ qfg sdk-key revoke <key-id>
1122
1122
  ```
1123
1123
 
1124
- _See code: [src/commands/sdk-key.ts](https://github.com/quonfig/cli/blob/v0.0.35/src/commands/sdk-key.ts)_
1124
+ _See code: [src/commands/sdk-key.ts](https://github.com/quonfig/cli/blob/v0.0.37/src/commands/sdk-key.ts)_
1125
1125
 
1126
1126
  ## `qfg sdk-key create`
1127
1127
 
@@ -1153,7 +1153,7 @@ EXAMPLES
1153
1153
  $ qfg sdk-key create --environment staging --type browser
1154
1154
  ```
1155
1155
 
1156
- _See code: [src/commands/sdk-key/create.ts](https://github.com/quonfig/cli/blob/v0.0.35/src/commands/sdk-key/create.ts)_
1156
+ _See code: [src/commands/sdk-key/create.ts](https://github.com/quonfig/cli/blob/v0.0.37/src/commands/sdk-key/create.ts)_
1157
1157
 
1158
1158
  ## `qfg sdk-key list`
1159
1159
 
@@ -1182,7 +1182,7 @@ EXAMPLES
1182
1182
  $ qfg sdk-key list --environment production
1183
1183
  ```
1184
1184
 
1185
- _See code: [src/commands/sdk-key/list.ts](https://github.com/quonfig/cli/blob/v0.0.35/src/commands/sdk-key/list.ts)_
1185
+ _See code: [src/commands/sdk-key/list.ts](https://github.com/quonfig/cli/blob/v0.0.37/src/commands/sdk-key/list.ts)_
1186
1186
 
1187
1187
  ## `qfg sdk-key revoke KEYID`
1188
1188
 
@@ -1209,7 +1209,7 @@ EXAMPLES
1209
1209
  $ qfg sdk-key revoke a1b2c3d4-e5f6-7890-abcd-ef1234567890
1210
1210
  ```
1211
1211
 
1212
- _See code: [src/commands/sdk-key/revoke.ts](https://github.com/quonfig/cli/blob/v0.0.35/src/commands/sdk-key/revoke.ts)_
1212
+ _See code: [src/commands/sdk-key/revoke.ts](https://github.com/quonfig/cli/blob/v0.0.37/src/commands/sdk-key/revoke.ts)_
1213
1213
 
1214
1214
  ## `qfg set-default [NAME]`
1215
1215
 
@@ -1280,7 +1280,7 @@ EXAMPLES
1280
1280
  $ qfg pull && qfg config-schema
1281
1281
  ```
1282
1282
 
1283
- _See code: [src/commands/set-default.ts](https://github.com/quonfig/cli/blob/v0.0.35/src/commands/set-default.ts)_
1283
+ _See code: [src/commands/set-default.ts](https://github.com/quonfig/cli/blob/v0.0.37/src/commands/set-default.ts)_
1284
1284
 
1285
1285
  ## `qfg set-rollout [NAME]`
1286
1286
 
@@ -1357,7 +1357,7 @@ EXAMPLES
1357
1357
  $ qfg set-rollout my.variant.flag --environment production --weights "a:33,b:33,c:34" --hash-by user.id
1358
1358
  ```
1359
1359
 
1360
- _See code: [src/commands/set-rollout.ts](https://github.com/quonfig/cli/blob/v0.0.35/src/commands/set-rollout.ts)_
1360
+ _See code: [src/commands/set-rollout.ts](https://github.com/quonfig/cli/blob/v0.0.37/src/commands/set-rollout.ts)_
1361
1361
 
1362
1362
  ## `qfg sync`
1363
1363
 
@@ -1389,7 +1389,7 @@ EXAMPLES
1389
1389
  $ qfg sync --watch --dir ./our-config --interval 30
1390
1390
  ```
1391
1391
 
1392
- _See code: [src/commands/sync.ts](https://github.com/quonfig/cli/blob/v0.0.35/src/commands/sync.ts)_
1392
+ _See code: [src/commands/sync.ts](https://github.com/quonfig/cli/blob/v0.0.37/src/commands/sync.ts)_
1393
1393
 
1394
1394
  ## `qfg toggle [NAME]`
1395
1395
 
@@ -1491,7 +1491,7 @@ EXAMPLES
1491
1491
  $ qfg verify --json
1492
1492
  ```
1493
1493
 
1494
- _See code: [src/commands/verify.ts](https://github.com/quonfig/cli/blob/v0.0.35/src/commands/verify.ts)_
1494
+ _See code: [src/commands/verify.ts](https://github.com/quonfig/cli/blob/v0.0.37/src/commands/verify.ts)_
1495
1495
 
1496
1496
  ## `qfg whoami`
1497
1497
 
@@ -1514,7 +1514,7 @@ EXAMPLES
1514
1514
  $ qfg whoami
1515
1515
  ```
1516
1516
 
1517
- _See code: [src/commands/whoami.ts](https://github.com/quonfig/cli/blob/v0.0.35/src/commands/whoami.ts)_
1517
+ _See code: [src/commands/whoami.ts](https://github.com/quonfig/cli/blob/v0.0.37/src/commands/whoami.ts)_
1518
1518
 
1519
1519
  ## `qfg workspace`
1520
1520
 
@@ -1537,7 +1537,7 @@ EXAMPLES
1537
1537
  $ qfg workspace
1538
1538
  ```
1539
1539
 
1540
- _See code: [src/commands/workspace.ts](https://github.com/quonfig/cli/blob/v0.0.35/src/commands/workspace.ts)_
1540
+ _See code: [src/commands/workspace.ts](https://github.com/quonfig/cli/blob/v0.0.37/src/commands/workspace.ts)_
1541
1541
 
1542
1542
  ## `qfg workspace bootstrap`
1543
1543
 
@@ -1570,7 +1570,7 @@ EXAMPLES
1570
1570
  $ qfg workspace bootstrap --dir ./our-config --skip-validate
1571
1571
  ```
1572
1572
 
1573
- _See code: [src/commands/workspace/bootstrap.ts](https://github.com/quonfig/cli/blob/v0.0.35/src/commands/workspace/bootstrap.ts)_
1573
+ _See code: [src/commands/workspace/bootstrap.ts](https://github.com/quonfig/cli/blob/v0.0.37/src/commands/workspace/bootstrap.ts)_
1574
1574
 
1575
1575
  ## `qfg workspace create SLUG`
1576
1576
 
@@ -1604,7 +1604,7 @@ EXAMPLES
1604
1604
  $ qfg workspace create my-team --org 11111111-1111-1111-1111-111111111111
1605
1605
  ```
1606
1606
 
1607
- _See code: [src/commands/workspace/create.ts](https://github.com/quonfig/cli/blob/v0.0.35/src/commands/workspace/create.ts)_
1607
+ _See code: [src/commands/workspace/create.ts](https://github.com/quonfig/cli/blob/v0.0.37/src/commands/workspace/create.ts)_
1608
1608
 
1609
1609
  ## `qfg workspace switch [SLUG]`
1610
1610
 
@@ -1632,7 +1632,7 @@ EXAMPLES
1632
1632
  $ qfg workspace switch acme/production
1633
1633
  ```
1634
1634
 
1635
- _See code: [src/commands/workspace/switch.ts](https://github.com/quonfig/cli/blob/v0.0.35/src/commands/workspace/switch.ts)_
1635
+ _See code: [src/commands/workspace/switch.ts](https://github.com/quonfig/cli/blob/v0.0.37/src/commands/workspace/switch.ts)_
1636
1636
  <!-- commandsstop -->
1637
1637
 
1638
1638
  ## Local Development
@@ -3,7 +3,7 @@ import * as path from 'node:path';
3
3
  import { Flags } from '@oclif/core';
4
4
  import { BaseCommand } from '../index.js';
5
5
  import { mintGiteaToken } from '../util/gitea-api.js';
6
- import { dirtyTrackedFiles, getRemoteUrl, gitFetch, gitSetRemote, isGitRepo, isLocalBehindOrDivergedFromRemote, runGit } from '../util/git-ops.js';
6
+ import { dirtyTrackedFiles, getOriginMainSha, getRemoteUrl, gitFetch, gitSetRemote, isGitRepo, isLocalBehindOrDivergedFromRemote, runGit } from '../util/git-ops.js';
7
7
  import { PushFatalError, runPush, } from '../push/run-push.js';
8
8
  import { computeBarePathDiff } from '../push/bare-path-diff.js';
9
9
  import { callConfigsPush } from '../push/config-push-client.js';
@@ -225,6 +225,14 @@ export function buildRealDeps(cmd, orgSlug) {
225
225
  return [];
226
226
  }
227
227
  },
228
+ async getOriginMainSha(dir) {
229
+ // qfg-gj3i: clone-path returns the local origin/main SHA after
230
+ // fetch. Bare path has no `.git/` to rev-parse — return undefined
231
+ // and let the server apply its bare-path lock policy.
232
+ if (!(await isGitRepo(dir)))
233
+ return undefined;
234
+ return getOriginMainSha(dir);
235
+ },
228
236
  };
229
237
  const deps = {
230
238
  async mintWriteToken(requestedTarget) {
@@ -19,12 +19,14 @@ export declare function normalizeLogLevelKey(key: string): string;
19
19
  */
20
20
  export declare function normalizeKey(key: string): string;
21
21
  /**
22
- * qfg-l18w: Operators Quonfig accepts in rule criteria. Mirrors the
23
- * `OperatorSchema` enum in cli/src/verify/validate.ts (and app-quonfig's
24
- * config-schemas.ts). If we emit an operator outside this set, qfg verify
25
- * fails — which is what was happening for `PROP_SEMVER_*` in the FormHealth
26
- * dry-run before this check existed. Keep this list in lockstep with the
27
- * verify schema; a CI test in this file enforces parity.
22
+ * qfg-l18w / qfg-0q1f: Operators Quonfig accepts in rule criteria. Mirrors
23
+ * the `OperatorSchema` enum in cli/src/verify/validate.ts (and app-quonfig's
24
+ * config-schemas.ts). All currently-known Launch operators are supported;
25
+ * this allowlist guards against future Launch additions Quonfig hasn't
26
+ * implemented yet — emitting an unrecognized operator would otherwise be
27
+ * caught only at qfg verify time, after the migrator has already written
28
+ * a broken file. Keep this list in lockstep with the verify schema; a CI
29
+ * test in this file enforces parity.
28
30
  */
29
31
  export declare const QUONFIG_SUPPORTED_OPERATORS: Set<string>;
30
32
  export declare function transformConfig(config: LaunchConfig, envIdMap: Record<string, string>, onDroppedEnv?: (envId: string) => void, onCoercedSentinel?: (envId: string, valueType: string) => void): Record<string, unknown>;
@@ -33,12 +33,14 @@ export function normalizeKey(key) {
33
33
  return key.replaceAll('/', '.');
34
34
  }
35
35
  /**
36
- * qfg-l18w: Operators Quonfig accepts in rule criteria. Mirrors the
37
- * `OperatorSchema` enum in cli/src/verify/validate.ts (and app-quonfig's
38
- * config-schemas.ts). If we emit an operator outside this set, qfg verify
39
- * fails — which is what was happening for `PROP_SEMVER_*` in the FormHealth
40
- * dry-run before this check existed. Keep this list in lockstep with the
41
- * verify schema; a CI test in this file enforces parity.
36
+ * qfg-l18w / qfg-0q1f: Operators Quonfig accepts in rule criteria. Mirrors
37
+ * the `OperatorSchema` enum in cli/src/verify/validate.ts (and app-quonfig's
38
+ * config-schemas.ts). All currently-known Launch operators are supported;
39
+ * this allowlist guards against future Launch additions Quonfig hasn't
40
+ * implemented yet — emitting an unrecognized operator would otherwise be
41
+ * caught only at qfg verify time, after the migrator has already written
42
+ * a broken file. Keep this list in lockstep with the verify schema; a CI
43
+ * test in this file enforces parity.
42
44
  */
43
45
  export const QUONFIG_SUPPORTED_OPERATORS = new Set([
44
46
  'ALWAYS_TRUE',
@@ -54,6 +56,9 @@ export const QUONFIG_SUPPORTED_OPERATORS = new Set([
54
56
  'PROP_LESS_THAN_OR_EQUAL',
55
57
  'PROP_GREATER_THAN',
56
58
  'PROP_GREATER_THAN_OR_EQUAL',
59
+ 'PROP_SEMVER_LESS_THAN',
60
+ 'PROP_SEMVER_EQUAL',
61
+ 'PROP_SEMVER_GREATER_THAN',
57
62
  'PROP_BEFORE',
58
63
  'PROP_AFTER',
59
64
  'PROP_MATCHES',
@@ -66,12 +71,10 @@ export const QUONFIG_SUPPORTED_OPERATORS = new Set([
66
71
  ]);
67
72
  /**
68
73
  * qfg-l18w: Walk every rule criterion in a transformed config and fail-fast at
69
- * migrate time if it carries an operator Quonfig does not understand. The
70
- * primary offender today is `PROP_SEMVER_*` (Launch supports semver
71
- * comparisons; Quonfig does not have a semver operator at all). Without this
72
- * check the migrator silently writes invalid JSON and the failure surfaces
73
- * later at qfg-verify — the customer's local file is broken and re-runs
74
- * re-clobber any manual fix.
74
+ * migrate time if it carries an operator Quonfig does not understand. Without
75
+ * this check the migrator would silently write invalid JSON and the failure
76
+ * would only surface later at qfg-verify — leaving the customer's local file
77
+ * broken and re-runs re-clobbering any manual fix.
75
78
  *
76
79
  * Routes through `InvalidSourceConfigError` so the failure is per-config (the
77
80
  * rest of the run still produces a usable workspace, and the offending key
@@ -59,6 +59,16 @@ export interface GitOps {
59
59
  * files are excluded — same rule as `dirtyTrackedFiles` in git-ops.ts.
60
60
  */
61
61
  dirtyTrackedFiles(dir: string): Promise<string[]>;
62
+ /**
63
+ * Returns the local SHA of `origin/main` after fetch — the remote tip
64
+ * the diff was computed against — or undefined if no `origin/main` ref
65
+ * exists (bare-path push, or repo never fetched).
66
+ *
67
+ * Threaded into the `configs.push` call as `expectedSha` so the
68
+ * server-side optimistic lock (qfg-gj3i) can reject pushes whose
69
+ * origin moved between fetch and push.
70
+ */
71
+ getOriginMainSha(dir: string): Promise<string | undefined>;
62
72
  /** Set origin to `url` (add if missing, set-url if present). */
63
73
  setRemoteOrigin(dir: string, url: string): Promise<void>;
64
74
  }
@@ -218,11 +218,17 @@ export async function runPush(input, deps) {
218
218
  ...(d.beforeJson === undefined ? {} : { beforeJson: d.beforeJson }),
219
219
  ...(d.afterJson === undefined ? {} : { afterJson: d.afterJson }),
220
220
  }));
221
+ // qfg-gj3i: pass origin/main SHA as expectedSha so the server-side
222
+ // optimistic lock can reject the push if origin moved between fetch
223
+ // and now. Undefined on bare-path; the server treats absence as
224
+ // "non-clone client" and applies its bare-path policy.
225
+ const expectedSha = await deps.gitOps.getOriginMainSha(input.dir);
221
226
  log('Sending push to Quonfig cloud...');
222
227
  const result = await deps.pushToServer({
223
228
  workspaceId: backend.workspaceId,
224
229
  files: serverFiles,
225
230
  message: commitMessage,
231
+ ...(expectedSha === undefined ? {} : { expectedSha }),
226
232
  });
227
233
  if (result.kind === 'denied') {
228
234
  errLog(`Push denied for ${result.denials.length} file(s):`);
@@ -160,3 +160,19 @@ export type GitPullRebaseResult = {
160
160
  * only reports the outcome.
161
161
  */
162
162
  export declare const gitPullRebase: (dir: string) => Promise<GitPullRebaseResult>;
163
+ /**
164
+ * Returns the local SHA of `origin/main` (i.e. the remote tip we last
165
+ * fetched), or undefined if the repo has no `origin/main` ref.
166
+ *
167
+ * Used as the `expectedSha` passed to the server-side `configs.push`
168
+ * optimistic lock (qfg-gj3i): the server compares the value we send
169
+ * against the current Gitea workspace HEAD and rejects the push if
170
+ * origin advanced between fetch and push. Belt-and-suspenders next to
171
+ * the CLI-side stale-HEAD guard from qfg-fboj — closes the gap for
172
+ * non-CLI clients and CLI regressions.
173
+ *
174
+ * Returns undefined on bare-path pushes (no `.git/`) and on any git
175
+ * error so the caller can fall back to other locks rather than aborting
176
+ * on an opaque rev-parse failure.
177
+ */
178
+ export declare const getOriginMainSha: (dir: string) => Promise<string | undefined>;
@@ -392,3 +392,28 @@ export const gitPullRebase = async (dir) => {
392
392
  return { kind: 'failed', reason };
393
393
  }
394
394
  };
395
+ /**
396
+ * Returns the local SHA of `origin/main` (i.e. the remote tip we last
397
+ * fetched), or undefined if the repo has no `origin/main` ref.
398
+ *
399
+ * Used as the `expectedSha` passed to the server-side `configs.push`
400
+ * optimistic lock (qfg-gj3i): the server compares the value we send
401
+ * against the current Gitea workspace HEAD and rejects the push if
402
+ * origin advanced between fetch and push. Belt-and-suspenders next to
403
+ * the CLI-side stale-HEAD guard from qfg-fboj — closes the gap for
404
+ * non-CLI clients and CLI regressions.
405
+ *
406
+ * Returns undefined on bare-path pushes (no `.git/`) and on any git
407
+ * error so the caller can fall back to other locks rather than aborting
408
+ * on an opaque rev-parse failure.
409
+ */
410
+ export const getOriginMainSha = async (dir) => {
411
+ try {
412
+ const { stdout } = await runGit(['-C', dir, 'rev-parse', 'origin/main']);
413
+ const sha = stdout.trim();
414
+ return sha.length > 0 ? sha : undefined;
415
+ }
416
+ catch {
417
+ return undefined;
418
+ }
419
+ };
@@ -42,6 +42,9 @@ const OperatorSchema = z.enum([
42
42
  'PROP_LESS_THAN_OR_EQUAL',
43
43
  'PROP_GREATER_THAN',
44
44
  'PROP_GREATER_THAN_OR_EQUAL',
45
+ 'PROP_SEMVER_LESS_THAN',
46
+ 'PROP_SEMVER_EQUAL',
47
+ 'PROP_SEMVER_GREATER_THAN',
45
48
  'PROP_BEFORE',
46
49
  'PROP_AFTER',
47
50
  'PROP_MATCHES',
@@ -169,6 +172,9 @@ const PROPERTY_OPERATORS = new Set([
169
172
  'PROP_LESS_THAN_OR_EQUAL',
170
173
  'PROP_GREATER_THAN',
171
174
  'PROP_GREATER_THAN_OR_EQUAL',
175
+ 'PROP_SEMVER_LESS_THAN',
176
+ 'PROP_SEMVER_EQUAL',
177
+ 'PROP_SEMVER_GREATER_THAN',
172
178
  'PROP_BEFORE',
173
179
  'PROP_AFTER',
174
180
  'PROP_MATCHES',
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- declare const _default: "0.0.35";
1
+ declare const _default: "0.0.37";
2
2
  export default _default;
package/dist/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // AUTO-GENERATED from package.json by scripts/generate-version.mjs — do not edit.
2
- export default '0.0.35';
2
+ export default '0.0.37';
@@ -2916,5 +2916,5 @@
2916
2916
  ]
2917
2917
  }
2918
2918
  },
2919
- "version": "0.0.35"
2919
+ "version": "0.0.37"
2920
2920
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "packageManager": "yarn@4.11.0+sha512.4e54aeace9141df2f0177c266b05ec50dc044638157dae128c471ba65994ac802122d7ab35bcd9e81641228b7dcf24867d28e750e0bcae8a05277d600008ad54",
3
3
  "name": "@quonfig/cli",
4
- "version": "0.0.35",
4
+ "version": "0.0.37",
5
5
  "bugs": {
6
6
  "url": "https://github.com/quonfig/cli/issues"
7
7
  },