@intentius/behold 0.19.0 → 0.21.0

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 (52) hide show
  1. package/AGENTS.md +90 -5
  2. package/README.md +54 -1
  3. package/demos.json +3 -2
  4. package/dist/cli.js +1327 -303
  5. package/example-argo-estate/README.md +8 -8
  6. package/example-argo-estate/app-a/package.json +2 -2
  7. package/example-argo-estate/app-b/package.json +2 -2
  8. package/example-argo-estate/chant.workspace.json +27 -0
  9. package/example-argo-estate/control-plane/package.json +2 -2
  10. package/example-argo-estate/package-lock.json +133 -56
  11. package/example-carve/README.md +14 -14
  12. package/example-carve/app/package-lock.json +72 -9
  13. package/example-carve/app/package.json +2 -2
  14. package/example-carve/legacy-tf/versions.tf +1 -1
  15. package/example-choudoufu-estate/README.md +4 -4
  16. package/example-choudoufu-estate/chant.workspace.json +32 -0
  17. package/example-choudoufu-estate/scripts/choudoufu-up.sh +21 -0
  18. package/example-flux-estate/README.md +5 -5
  19. package/example-flux-estate/app-a/package.json +2 -2
  20. package/example-flux-estate/app-b/package.json +2 -2
  21. package/example-flux-estate/chant.workspace.json +27 -0
  22. package/example-flux-estate/control-plane/package.json +2 -2
  23. package/example-flux-estate/package-lock.json +133 -56
  24. package/example-k8s/README.md +20 -20
  25. package/example-k8s/chant.config.ts +1 -1
  26. package/example-k8s/ops/k3d-apply.op.ts +1 -1
  27. package/example-k8s/package-lock.json +129 -211
  28. package/example-k8s/package.json +2 -3
  29. package/example-terraform-estate/README.md +5 -5
  30. package/example-terraform-estate/chant.workspace.json +22 -0
  31. package/example-writes/README.md +5 -5
  32. package/example-writes/chant.config.ts +1 -1
  33. package/example-writes/ops/apply.op.ts +1 -1
  34. package/example-writes/ops/floci.op.ts +2 -2
  35. package/example-writes/ops/reconcile.op.ts +1 -1
  36. package/example-writes/package-lock.json +62 -175
  37. package/example-writes/package.json +2 -3
  38. package/package.json +6 -6
  39. package/web/app.js +431 -17
  40. package/web/behaviour-scale.js +32 -0
  41. package/web/behaviour-scale.test.js +39 -0
  42. package/web/embed.js +76 -0
  43. package/web/embed.test.js +45 -0
  44. package/web/index.html +20 -0
  45. package/web/operator.js +14 -1
  46. package/web/panel.js +11 -3
  47. package/web/run-playhead.js +13 -1
  48. package/web/view-url.js +138 -0
  49. package/web/view-url.test.js +84 -0
  50. package/web/workspace-gates.js +44 -0
  51. package/web/workspace-gates.test.js +34 -0
  52. package/example-choudoufu-estate/.behold.json +0 -8
@@ -3,7 +3,7 @@
3
3
  Three chant projects served as one composed estate, the Argo mirror of
4
4
  [example-flux-estate](../example-flux-estate):
5
5
 
6
- - **control-plane/** — the Argo machinery: an `AppProject` fencing which repo
6
+ - **control-plane/.** The Argo machinery: an `AppProject` fencing which repo
7
7
  and which namespaces the estate may deploy, and one `Application` per app
8
8
  syncing that app's committed manifests from behold's own public repo. Argo's
9
9
  controller does the applying; this project never applies a workload itself.
@@ -14,13 +14,13 @@ Three chant projects served as one composed estate, the Argo mirror of
14
14
  npx @intentius/behold demo argo-estate
15
15
  ```
16
16
 
17
- The demo path is **declared only** — no cluster, no Argo install, no Docker. It
17
+ The demo path is **declared only**, no cluster, no Argo install, no Docker. It
18
18
  copies out, `npm install`s, and serves. (There is a live lane, but it is an
19
19
  acceptance run rather than part of the demo: see "Live" below.) What to look
20
20
  at:
21
21
 
22
22
  - The **estate**: per-project boundary boxes, and the `project` edges joining
23
- both Applications to the AppProject they name (behold#222) — the join chant
23
+ both Applications to the AppProject they name (behold#222), the join chant
24
24
  lints as ARGO002, so an estate whose lint passes cannot be drawn wrong.
25
25
  The entity graph carries them at the attributes tier (`?detail=3`).
26
26
  - The **logical lens** (zoom: logical): cluster ⊃ `namespace app-a` and
@@ -31,20 +31,20 @@ at:
31
31
  namespace Argo will own objects in is a namespace the estate is committed
32
32
  to, and behold#224 taught the composed estate to draw that projection.
33
33
  Serve `control-plane` alone (`behold serve control-plane`, zoom: logical)
34
- and the same boxes appear empty — the destination harvest still names them,
34
+ and the same boxes appear empty, the destination harvest still names them,
35
35
  but there is nothing from app-a/app-b in the graph to fill them with.
36
36
 
37
37
  That alone-vs-composed split is the Argo/Flux difference worth noticing:
38
38
  flux-estate's control plane must declare the app namespaces itself (a
39
39
  Kustomization's `targetNamespace` must already exist), while here
40
- `CreateNamespace=true` means Argo makes them — so the box exists on the
40
+ `CreateNamespace=true` means Argo makes them, so the box exists on the
41
41
  strength of the destination alone.
42
42
 
43
43
  Argo's ordering is the `argocd.argoproj.io/sync-wave` annotation, so unlike
44
44
  Flux's `dependsOn` (behold#223) there is no edge to draw for it: app-a is wave
45
45
  0, app-b wave 1, and the picture says nothing about it.
46
46
 
47
- The app `manifests/` are committed `chant build` output — the path each
47
+ The app `manifests/` are committed `chant build` output, the path each
48
48
  Application syncs. Changing an app's source means a rebuild (`npm run build` in
49
49
  the app), and the rebuilt manifests have to be on `main` before Argo can sync
50
50
  them. `chant build` in the control plane warns ARGO005 on both Applications:
@@ -55,11 +55,11 @@ check's own message says so.
55
55
  ## Live
56
56
 
57
57
  Nothing above needs a cluster, but the estate as committed does reconcile
58
- against a real one — the Applications point at this repo on `main` and the app
58
+ against a real one, the Applications point at this repo on `main` and the app
59
59
  `manifests/` are already there, so an Argo CD install has everything it needs.
60
60
  `just e2e-argo-estate` (behold#269) is that run: a scratch k3d cluster, Argo
61
61
  from the pinned `core-install` manifest, the control plane applied once, and
62
- then the composed estate served against the result — the destination-namespace
62
+ then the composed estate served against the result, the destination-namespace
63
63
  boxes filled with live cards, #238's health verdicts read off each
64
64
  Application's health/sync pair, and the unhappy arm (an Application pointed at
65
65
  a path that does not exist, then restored). It creates and deletes its own
@@ -7,7 +7,7 @@
7
7
  "build": "chant build src -o manifests/app.yaml --format yaml"
8
8
  },
9
9
  "dependencies": {
10
- "@intentius/chant": "^0.54.0",
11
- "@intentius/chant-lexicon-k8s": "^0.54.0"
10
+ "@intentius/chant": "^0.95.0",
11
+ "@intentius/chant-lexicon-k8s": "^0.95.0"
12
12
  }
13
13
  }
@@ -7,7 +7,7 @@
7
7
  "build": "chant build src -o manifests/app.yaml --format yaml"
8
8
  },
9
9
  "dependencies": {
10
- "@intentius/chant": "^0.54.0",
11
- "@intentius/chant-lexicon-k8s": "^0.54.0"
10
+ "@intentius/chant": "^0.95.0",
11
+ "@intentius/chant-lexicon-k8s": "^0.95.0"
12
12
  }
13
13
  }
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "example-argo-estate",
3
+ "schema": 1,
4
+ "pins": [
5
+ {
6
+ "package": "@intentius/chant",
7
+ "version": "0.95.0"
8
+ }
9
+ ],
10
+ "members": [
11
+ {
12
+ "name": "control-plane",
13
+ "dir": "control-plane",
14
+ "kind": "chant"
15
+ },
16
+ {
17
+ "name": "app-a",
18
+ "dir": "app-a",
19
+ "kind": "chant"
20
+ },
21
+ {
22
+ "name": "app-b",
23
+ "dir": "app-b",
24
+ "kind": "chant"
25
+ }
26
+ ]
27
+ }
@@ -7,7 +7,7 @@
7
7
  "build": "chant build src -o dist/control-plane.yaml --format yaml"
8
8
  },
9
9
  "dependencies": {
10
- "@intentius/chant": "^0.54.0",
11
- "@intentius/chant-lexicon-k8s": "^0.54.0"
10
+ "@intentius/chant": "^0.95.0",
11
+ "@intentius/chant-lexicon-k8s": "^0.95.0"
12
12
  }
13
13
  }
@@ -14,22 +14,22 @@
14
14
  "app-a": {
15
15
  "name": "behold-example-argo-app-a",
16
16
  "dependencies": {
17
- "@intentius/chant": "^0.54.0",
18
- "@intentius/chant-lexicon-k8s": "^0.54.0"
17
+ "@intentius/chant": "^0.95.0",
18
+ "@intentius/chant-lexicon-k8s": "^0.95.0"
19
19
  }
20
20
  },
21
21
  "app-b": {
22
22
  "name": "behold-example-argo-app-b",
23
23
  "dependencies": {
24
- "@intentius/chant": "^0.54.0",
25
- "@intentius/chant-lexicon-k8s": "^0.54.0"
24
+ "@intentius/chant": "^0.95.0",
25
+ "@intentius/chant-lexicon-k8s": "^0.95.0"
26
26
  }
27
27
  },
28
28
  "control-plane": {
29
29
  "name": "behold-example-argo-control-plane",
30
30
  "dependencies": {
31
- "@intentius/chant": "^0.54.0",
32
- "@intentius/chant-lexicon-k8s": "^0.54.0"
31
+ "@intentius/chant": "^0.95.0",
32
+ "@intentius/chant-lexicon-k8s": "^0.95.0"
33
33
  }
34
34
  },
35
35
  "node_modules/@dagrejs/dagre": {
@@ -464,14 +464,16 @@
464
464
  }
465
465
  },
466
466
  "node_modules/@intentius/chant": {
467
- "version": "0.54.0",
468
- "resolved": "https://registry.npmjs.org/@intentius/chant/-/chant-0.54.0.tgz",
469
- "integrity": "sha512-ETYVPvDWqJiEsaaaYK+1U2lGrZZqHPU6/bOH797oQNw5gd7ESkEoYZxlh0qO90FQGVdx1pQMvmlCWskWD4xIlA==",
467
+ "version": "0.95.0",
468
+ "resolved": "https://registry.npmjs.org/@intentius/chant/-/chant-0.95.0.tgz",
469
+ "integrity": "sha512-zhReqEbP7apFyI9bwHATxSKPbc9HK8W2lJvZpib0YNEgSafydm+dd31Hn+7o3AcHhYbAkLpHFQwlFYbM2uVYCg==",
470
470
  "license": "Apache-2.0",
471
471
  "dependencies": {
472
472
  "@dagrejs/dagre": "^3.0.0",
473
+ "ajv": "^8.20.0",
473
474
  "esbuild": "^0.28.1",
474
475
  "fflate": "^0.8.2",
476
+ "js-yaml": "^4.3.1",
475
477
  "picomatch": "^4.0.3",
476
478
  "tsx": "^4.0.0",
477
479
  "typescript": "^5.5.0",
@@ -479,12 +481,20 @@
479
481
  },
480
482
  "bin": {
481
483
  "chant": "bin/chant"
484
+ },
485
+ "peerDependencies": {
486
+ "vitest": ">=2"
487
+ },
488
+ "peerDependenciesMeta": {
489
+ "vitest": {
490
+ "optional": true
491
+ }
482
492
  }
483
493
  },
484
494
  "node_modules/@intentius/chant-k8s-client": {
485
- "version": "0.54.0",
486
- "resolved": "https://registry.npmjs.org/@intentius/chant-k8s-client/-/chant-k8s-client-0.54.0.tgz",
487
- "integrity": "sha512-LzoPfOQ4tIy7QR3ohLi/OqRgoZU/NXZ5TU6WeXFVqzffSjEoZu9yonjkaALy30Dqqa77XGFMTcP/SMZkNSEdsQ==",
495
+ "version": "0.95.0",
496
+ "resolved": "https://registry.npmjs.org/@intentius/chant-k8s-client/-/chant-k8s-client-0.95.0.tgz",
497
+ "integrity": "sha512-AjLnvTNzAIHbwsOv8gszuLqzH0UeA16Dy8dWIdEICUDLRdmi0gGcX7qZ/VNzQMIHu9Bu1hSIJz+gbmR44a7tYA==",
488
498
  "license": "Apache-2.0",
489
499
  "optional": true,
490
500
  "dependencies": {
@@ -492,23 +502,37 @@
492
502
  }
493
503
  },
494
504
  "node_modules/@intentius/chant-lexicon-k8s": {
495
- "version": "0.54.0",
496
- "resolved": "https://registry.npmjs.org/@intentius/chant-lexicon-k8s/-/chant-lexicon-k8s-0.54.0.tgz",
497
- "integrity": "sha512-Bz+UYEJmy6gCAhlTPXAsyeLG8B7B9KvBX/Cjt261z/nOc/0OwdOhZs3DkjD1UA1ZPKfkUxP/S1mJq8ux3ggNCw==",
505
+ "version": "0.95.0",
506
+ "resolved": "https://registry.npmjs.org/@intentius/chant-lexicon-k8s/-/chant-lexicon-k8s-0.95.0.tgz",
507
+ "integrity": "sha512-sanDVeXQYHXkwwQ5OZiVCbpHn25B6wt9XvW3uoBpzLv/lBhxrPfKGv5xhDyAfKaSktfCknWXlI2S0SV+6AOy8A==",
498
508
  "license": "Apache-2.0",
499
509
  "dependencies": {
510
+ "@intentius/chant-lexicon-otel": "*",
500
511
  "@types/js-yaml": "^4.0.9",
501
512
  "js-yaml": "^4.3.1"
502
513
  },
503
514
  "optionalDependencies": {
504
- "@intentius/chant-k8s-client": "^0.54.0"
515
+ "@intentius/chant-k8s-client": "^0.95.0"
505
516
  },
506
517
  "peerDependencies": {
507
- "@intentius/chant": "^0.54.0",
518
+ "@intentius/chant": "^0.95.0",
508
519
  "typescript": "^5.9.3",
509
520
  "zod": "^4.3.6"
510
521
  }
511
522
  },
523
+ "node_modules/@intentius/chant-lexicon-otel": {
524
+ "version": "0.95.0",
525
+ "resolved": "https://registry.npmjs.org/@intentius/chant-lexicon-otel/-/chant-lexicon-otel-0.95.0.tgz",
526
+ "integrity": "sha512-TTydUPN3fStnkdsmAIWKZiA2gBahxOAz9ihcsHx5rupnkOTSHO8soxayqbUBaUxVbdbrwYT9zpAcc3W3KcXBaQ==",
527
+ "license": "Apache-2.0",
528
+ "dependencies": {
529
+ "js-yaml": "^4.3.1"
530
+ },
531
+ "peerDependencies": {
532
+ "@intentius/chant": "^0.95.0",
533
+ "typescript": "^5.9.3"
534
+ }
535
+ },
512
536
  "node_modules/@jsep-plugin/assignment": {
513
537
  "version": "1.3.0",
514
538
  "resolved": "https://registry.npmjs.org/@jsep-plugin/assignment/-/assignment-1.3.0.tgz",
@@ -590,13 +614,13 @@
590
614
  "license": "MIT"
591
615
  },
592
616
  "node_modules/@types/node": {
593
- "version": "26.4.1",
594
- "resolved": "https://registry.npmjs.org/@types/node/-/node-26.4.1.tgz",
595
- "integrity": "sha512-k97ENvZWtvA6yqz5/FS6a7duDgOPEeOQOc2iKS/nY6mX6qJUKtLnWzQS+Xj6tXweyj6ZcTAK2Qecetnvi9nCLA==",
617
+ "version": "26.6.3",
618
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-26.6.3.tgz",
619
+ "integrity": "sha512-dsqMQQoeTLqu9wynDD00q573mNzso3IdQOAfHRJqLCcmCFPoGo9A1bDpUcv/9tnKpErQWv9uKeGfl37EIS02Yg==",
596
620
  "license": "MIT",
597
621
  "optional": true,
598
622
  "dependencies": {
599
- "undici-types": "~8.3.0"
623
+ "undici-types": "~8.9.0"
600
624
  }
601
625
  },
602
626
  "node_modules/@types/stream-buffers": {
@@ -619,6 +643,22 @@
619
643
  "node": ">= 20"
620
644
  }
621
645
  },
646
+ "node_modules/ajv": {
647
+ "version": "8.20.0",
648
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
649
+ "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
650
+ "license": "MIT",
651
+ "dependencies": {
652
+ "fast-deep-equal": "^3.1.3",
653
+ "fast-uri": "^3.0.1",
654
+ "json-schema-traverse": "^1.0.0",
655
+ "require-from-string": "^2.0.2"
656
+ },
657
+ "funding": {
658
+ "type": "github",
659
+ "url": "https://github.com/sponsors/epoberezkin"
660
+ }
661
+ },
622
662
  "node_modules/argparse": {
623
663
  "version": "2.0.1",
624
664
  "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
@@ -633,9 +673,9 @@
633
673
  "optional": true
634
674
  },
635
675
  "node_modules/b4a": {
636
- "version": "1.8.1",
637
- "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.8.1.tgz",
638
- "integrity": "sha512-aiqre1Nr0B/6DgE2N5vwTc+2/oQZ4Wh1t4NznYY4E00y8LCt6NqdRv81so00oo27D8MVKTpUa/MwUUtBLXCoDw==",
676
+ "version": "1.9.0",
677
+ "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.9.0.tgz",
678
+ "integrity": "sha512-dpfcF9fDNR6++cthXR67iyhgqWy9CBouAvIWhIntzBG6cvK/cnIPiZQjBwi/ZqjjBEDGfoNDtmB0kTjroOJ3pQ==",
639
679
  "license": "Apache-2.0",
640
680
  "optional": true,
641
681
  "peerDependencies": {
@@ -663,9 +703,9 @@
663
703
  }
664
704
  },
665
705
  "node_modules/bare-fs": {
666
- "version": "4.8.1",
667
- "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.8.1.tgz",
668
- "integrity": "sha512-N1nnXdHZAOSstz0XiHikGS4HGMH4CnSwhqWdGQQMqqdvp4Jybm9sE3R1WVnpWVd4SFkc8ryPDBLViNLwiEqECg==",
706
+ "version": "4.8.2",
707
+ "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-4.8.2.tgz",
708
+ "integrity": "sha512-+ZI68KHMUvosXfKbg/UOHK0tbCdRnegbvPEdEcZ3Nd6TetieQsJPRXBRXPdLyy8+3VSEbPXtsumTpEtt78xv9w==",
669
709
  "license": "Apache-2.0",
670
710
  "optional": true,
671
711
  "dependencies": {
@@ -723,9 +763,9 @@
723
763
  }
724
764
  },
725
765
  "node_modules/bare-url": {
726
- "version": "2.5.3",
727
- "resolved": "https://registry.npmjs.org/bare-url/-/bare-url-2.5.3.tgz",
728
- "integrity": "sha512-3absfEzoyFosWT8v83ZcJgbTJxv+S/sI7jBfeCMlUVatSaefRmwweqBhFpMllQv+HTxs/FbbToVOw1c05NORkQ==",
766
+ "version": "2.5.4",
767
+ "resolved": "https://registry.npmjs.org/bare-url/-/bare-url-2.5.4.tgz",
768
+ "integrity": "sha512-Gxa7UVWBr0/edU1b+TJhn/AZvMQUj9OGspvYsaTYQrAbZA4BOTZGL3LiZxvD+CeMlDH4juwD84+eTAp/bLYW5g==",
729
769
  "license": "Apache-2.0",
730
770
  "optional": true,
731
771
  "dependencies": {
@@ -924,6 +964,12 @@
924
964
  "bare-events": "^2.7.0"
925
965
  }
926
966
  },
967
+ "node_modules/fast-deep-equal": {
968
+ "version": "3.1.3",
969
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
970
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
971
+ "license": "MIT"
972
+ },
927
973
  "node_modules/fast-fifo": {
928
974
  "version": "1.3.2",
929
975
  "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz",
@@ -931,6 +977,22 @@
931
977
  "license": "MIT",
932
978
  "optional": true
933
979
  },
980
+ "node_modules/fast-uri": {
981
+ "version": "3.1.8",
982
+ "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.8.tgz",
983
+ "integrity": "sha512-GZMtZUTNRpOVIECoXwLNZS5xUGE+mVNbTB8h/7Rwh2TFWcBQiPzTgyZi05BF9UMZKkLJv8XBRJTlU7zg8+ZfMg==",
984
+ "funding": [
985
+ {
986
+ "type": "github",
987
+ "url": "https://github.com/sponsors/fastify"
988
+ },
989
+ {
990
+ "type": "opencollective",
991
+ "url": "https://opencollective.com/fastify"
992
+ }
993
+ ],
994
+ "license": "BSD-3-Clause"
995
+ },
934
996
  "node_modules/fflate": {
935
997
  "version": "0.8.3",
936
998
  "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.3.tgz",
@@ -1083,9 +1145,9 @@
1083
1145
  }
1084
1146
  },
1085
1147
  "node_modules/ip-address": {
1086
- "version": "10.7.0",
1087
- "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.7.0.tgz",
1088
- "integrity": "sha512-BGFsyJd5mpXp3rK6jIdADLNgpJUK1jnjzvYF8lK+VyDab9JAmqN0YOKDdP17HlgKb2+ehPgDc8EtnRLbGCAMhA==",
1148
+ "version": "10.7.2",
1149
+ "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.7.2.tgz",
1150
+ "integrity": "sha512-7H/2gFSIitxc0hG3nOI1glS8QLo/EHBFFLk8vEUjXY/xu0AdL8jZ9U1IzO2PUm0d2D/ofQcAifb0g6OBkt8U7w==",
1089
1151
  "license": "MIT",
1090
1152
  "optional": true,
1091
1153
  "engines": {
@@ -1103,9 +1165,9 @@
1103
1165
  }
1104
1166
  },
1105
1167
  "node_modules/jose": {
1106
- "version": "6.2.10",
1107
- "resolved": "https://registry.npmjs.org/jose/-/jose-6.2.10.tgz",
1108
- "integrity": "sha512-iiW7J9qRFlGxvCOIBDBDxFePQSn7ZMAnrYGhrrOo6siO/MIqwfyilLR27pkfDgUk+raLuzADS8A3S/KLBisc0g==",
1168
+ "version": "6.2.12",
1169
+ "resolved": "https://registry.npmjs.org/jose/-/jose-6.2.12.tgz",
1170
+ "integrity": "sha512-9NiFmJEex0sy2Dk58j2UGBSHgUs2ypF9eZSu4L6vjOX3Dp96Sw1F3uL+H+D1sx02jZZdzUT0HgvCy59CuvXcWw==",
1109
1171
  "license": "MIT",
1110
1172
  "optional": true,
1111
1173
  "funding": {
@@ -1144,6 +1206,12 @@
1144
1206
  "node": ">= 10.16.0"
1145
1207
  }
1146
1208
  },
1209
+ "node_modules/json-schema-traverse": {
1210
+ "version": "1.0.0",
1211
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
1212
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
1213
+ "license": "MIT"
1214
+ },
1147
1215
  "node_modules/jsonpath-plus": {
1148
1216
  "version": "10.4.0",
1149
1217
  "resolved": "https://registry.npmjs.org/jsonpath-plus/-/jsonpath-plus-10.4.0.tgz",
@@ -1204,9 +1272,9 @@
1204
1272
  "optional": true
1205
1273
  },
1206
1274
  "node_modules/oauth4webapi": {
1207
- "version": "3.8.7",
1208
- "resolved": "https://registry.npmjs.org/oauth4webapi/-/oauth4webapi-3.8.7.tgz",
1209
- "integrity": "sha512-4RxcKxXjuItDFZ20RRPf4YTw3kpeXJyCgJFxVzJ068A7PNJ18st2Dg90tlC1LkSDS0GecroagCLHYEIVUhCAkw==",
1275
+ "version": "3.8.8",
1276
+ "resolved": "https://registry.npmjs.org/oauth4webapi/-/oauth4webapi-3.8.8.tgz",
1277
+ "integrity": "sha512-8N28E+a/oxfXWBgOMt+ZP/JUf/XR+IFbvkAEPP3gznXOMv9BpAAwiIj0TFNz3tGTPc0ZQ8zmWBNgN1nAys0gng==",
1210
1278
  "license": "MIT",
1211
1279
  "optional": true,
1212
1280
  "funding": {
@@ -1224,14 +1292,14 @@
1224
1292
  }
1225
1293
  },
1226
1294
  "node_modules/openid-client": {
1227
- "version": "6.8.7",
1228
- "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-6.8.7.tgz",
1229
- "integrity": "sha512-gtKthNu7evSBvTdrrlHb4F3Fi9dcwlb5QaITlCs+9mfpvuOi0Q3qtBf5+iY4sEP8hy1qCoAdxBNPDcmZeVSDzQ==",
1295
+ "version": "6.8.8",
1296
+ "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-6.8.8.tgz",
1297
+ "integrity": "sha512-ZsucJA5Ad04Uv7YN4ql+s4GXNmb9uAYQwyJTsJx7CH/MX3JZioLE2pVKi1SC+YrbSLA4Px3Gi30dMjgOZtb6pA==",
1230
1298
  "license": "MIT",
1231
1299
  "optional": true,
1232
1300
  "dependencies": {
1233
- "jose": "^6.2.8",
1234
- "oauth4webapi": "^3.8.7"
1301
+ "jose": "^6.2.12",
1302
+ "oauth4webapi": "^3.8.8"
1235
1303
  },
1236
1304
  "funding": {
1237
1305
  "url": "https://github.com/sponsors/panva"
@@ -1260,6 +1328,15 @@
1260
1328
  "once": "^1.3.1"
1261
1329
  }
1262
1330
  },
1331
+ "node_modules/require-from-string": {
1332
+ "version": "2.0.2",
1333
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
1334
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
1335
+ "license": "MIT",
1336
+ "engines": {
1337
+ "node": ">=0.10.0"
1338
+ }
1339
+ },
1263
1340
  "node_modules/rfc4648": {
1264
1341
  "version": "1.5.4",
1265
1342
  "resolved": "https://registry.npmjs.org/rfc4648/-/rfc4648-1.5.4.tgz",
@@ -1279,9 +1356,9 @@
1279
1356
  }
1280
1357
  },
1281
1358
  "node_modules/socks": {
1282
- "version": "2.8.9",
1283
- "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.9.tgz",
1284
- "integrity": "sha512-LJhUYUvItdQ0LkJTmPeaEObWXAqFyfmP85x0tch/ez9cahmhlBBLbIqDFnvBnUJGagb0JbIQrkBs1wJ+yRYpEw==",
1359
+ "version": "2.8.10",
1360
+ "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.10.tgz",
1361
+ "integrity": "sha512-e0VyvkVTwVYViNovRkZ9aodhxVlyoMn7eJhVUPxZ+eK9P/7CBkxvvsBOHqFPEH416726W8tLXXXjKwqgTErrCQ==",
1285
1362
  "license": "MIT",
1286
1363
  "optional": true,
1287
1364
  "dependencies": {
@@ -1410,9 +1487,9 @@
1410
1487
  }
1411
1488
  },
1412
1489
  "node_modules/undici": {
1413
- "version": "8.10.1",
1414
- "resolved": "https://registry.npmjs.org/undici/-/undici-8.10.1.tgz",
1415
- "integrity": "sha512-YQ3WlbqjYMmNpdvDH64jAgLjxuAR9+649calDWhbshYaeQGO2bR4nI94ORJmwI3J9YhoKQnpyGOK+0zlWS5N5Q==",
1490
+ "version": "8.11.2",
1491
+ "resolved": "https://registry.npmjs.org/undici/-/undici-8.11.2.tgz",
1492
+ "integrity": "sha512-u4UB2/IrKdU6lFxumHmmo1a3fCQO5tzQllRorfoRS63txhrB7xTpSn1PftwC4qEHkOaqP95fCWW4lJzwErwzhQ==",
1416
1493
  "license": "MIT",
1417
1494
  "optional": true,
1418
1495
  "engines": {
@@ -1420,9 +1497,9 @@
1420
1497
  }
1421
1498
  },
1422
1499
  "node_modules/undici-types": {
1423
- "version": "8.3.0",
1424
- "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz",
1425
- "integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==",
1500
+ "version": "8.9.0",
1501
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.9.0.tgz",
1502
+ "integrity": "sha512-KTDyRTYX8sWmKXAikPHHSyc63CRPETMctyjKFupcC6OBLXT3xsN0e9aF7m+mIXutFWpUXuedtowG7iLOzp0kQg==",
1426
1503
  "license": "MIT",
1427
1504
  "optional": true
1428
1505
  },
@@ -1434,9 +1511,9 @@
1434
1511
  "optional": true
1435
1512
  },
1436
1513
  "node_modules/ws": {
1437
- "version": "8.21.3",
1438
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.3.tgz",
1439
- "integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==",
1514
+ "version": "8.22.0",
1515
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.22.0.tgz",
1516
+ "integrity": "sha512-Ydggc987+RO0AnWtZ/7Wq9FtNvcrL1b/RO0ud9mWjUPgDrsAAwQSF51sm2hm1XofbU/4jkpGEsLFsZZxU+1DOg==",
1440
1517
  "license": "MIT",
1441
1518
  "optional": true,
1442
1519
  "engines": {
@@ -1,4 +1,4 @@
1
- # example-carve — the mixed estate the peeling demo runs on
1
+ # example-carve, the mixed estate the peeling demo runs on
2
2
 
3
3
  A migration caught half-done. `app/` is chant; `legacy-tf/` is Terraform; both
4
4
  describe one AWS account, and the walkthrough carves one more resource across
@@ -11,9 +11,9 @@ behold demo carve # copies this directory, installs, advises, serves
11
11
  ```
12
12
 
13
13
  The boot does three things before a port opens: `npm install` in `app/` (whose
14
- chant every step of the walkthrough shells), `@cdktf/hcl2json` into the copy's
14
+ chant every step of the walkthrough shells), `@cdktn/hcl2json` into the copy's
15
15
  root `node_modules` (chant lazy-loads the HCL parser from its own install
16
- upward, so `<copy>/node_modules` is where it resolves — not beside the `.tf`
16
+ upward, so `<copy>/node_modules` is where it resolves rather than beside the `.tf`
17
17
  files), and `chant carve advise --report` over the copy's own Terraform. If any
18
18
  of that fails, the committed `carve-report.json` is served instead and the
19
19
  reason is on screen; a blank graph is the one outcome that's never allowed.
@@ -53,7 +53,7 @@ Real output, from `chant carve advise` (first cut at chant 0.44.7, verified
53
53
  identical at 0.52.1). Reproduce it with:
54
54
 
55
55
  ```sh
56
- npm install -D @cdktf/hcl2json # once, anywhere on your PATH resolution
56
+ npm install -D @cdktn/hcl2json # once, anywhere on your PATH resolution
57
57
  chant carve advise --from example-carve/legacy-tf \
58
58
  --state example-carve/legacy-tf/terraform.tfstate
59
59
  ```
@@ -61,7 +61,7 @@ chant carve advise --from example-carve/legacy-tf \
61
61
  | score | address | band | why | role in the script |
62
62
  |---|---|---|---|---|
63
63
  | 100 | `aws_cloudwatch_log_group.worker` | clean leaf | clean 1:1 native map, no boundary edges | the free first move: named, not carved |
64
- | 84 | `aws_s3_bucket.assets` | clean leaf | 1 inbound, 1 output | **the star** — the resource we carve on camera |
64
+ | 84 | `aws_s3_bucket.assets` | clean leaf | 1 inbound, 1 output | **the star**, the resource we carve on camera |
65
65
  | 71 | `module.cdn` | carvable w/ edits | 1 outbound, tier 2, data present | one module, so module scoring appears |
66
66
  | 69 | `aws_iam_role.api` | carvable w/ edits | 1 inbound, 1 outbound, tier 2 | what an inbound edge costs |
67
67
  | 69 | `aws_vpc_endpoint.ssm` | carvable w/ edits | 4 outbound, tier 2 | outbound edges are cheap, but they add up |
@@ -85,7 +85,7 @@ above is that arithmetic on the edges in `legacy-tf/`, which is why the estate
85
85
  is shaped the way it is:
86
86
 
87
87
  - The bucket has one inbound edge — `aws_lambda_function.api`'s
88
- `ASSETS_BUCKET` environment variable — and, since `outputs.tf`'s
88
+ `ASSETS_BUCKET` environment variable, and, since `outputs.tf`'s
89
89
  `assets_bucket` reads it too, one output edge. Two edges, two rewrites, 84.
90
90
  `assets_bucket` is deliberate: a downstream consumer of this state reads the
91
91
  bucket name today, so the carve has a second thing to bridge, not just the
@@ -98,7 +98,7 @@ is shaped the way it is:
98
98
  output, and 32 says so.
99
99
  - The subnets and the security group each read a data source, which costs 10.
100
100
  The subnets also feed `private_subnet_ids`, an existing output, which costs
101
- 4 more apiece and drops them under the security group's 43 — the one place
101
+ 4 more apiece and drops them under the security group's 43, the one place
102
102
  the outputs term reorders the table, not just re-scores it.
103
103
 
104
104
  No resource uses `count` or `for_each`, so the instance-count penalty is zero
@@ -132,7 +132,7 @@ bucket scores 84 instead of 88 and the report's `patchOnCarve` list names
132
132
  fold is applied, not just reported (chant#1637), so the emitted bucket actually
133
133
  carries `VersioningConfiguration` and `PublicAccessBlockConfiguration` instead
134
134
  of leaving them in an "unmapped attributes" comment. The committed report above
135
- is byte-identical to what 0.44.7 regenerates — re-verified at 0.52.1 — which is
135
+ is byte-identical to what 0.44.7 regenerates — re-verified at 0.52.1, which is
136
136
  why the demo's fallback path and its fresh-run path show the same picture.
137
137
 
138
138
  ## The six beats
@@ -177,7 +177,7 @@ still says so. Run `chant carve apply` yourself in the copy and the card leaves
177
177
  the Terraform bands for the `app — chant` box, keeping its Terraform address,
178
178
  and the panel counts `carved so far — 1 of 12 carved`.
179
179
 
180
- `carve apply` is the one beat that has no button — not in the stepper, not on
180
+ `carve apply` is the one beat that has no button: not in the stepper, not on
181
181
  the API. It resolves the marker that makes chant the owner of a live resource,
182
182
  which is a decision that stays with the person at the terminal. The Handoff
183
183
  step echoes the command beside the two `terraform` ones, for the same reason
@@ -188,13 +188,13 @@ and in the same shape.
188
188
  **Offline is the default.** The synthetic `terraform.tfstate` is committed, so
189
189
  `carve advise` and `carve emit --state` run with no Docker, no terraform binary,
190
190
  no AWS account and no network. The only dependency beyond this directory is
191
- `@cdktf/hcl2json`, which chant lazy-loads and names in its error if absent. This
191
+ `@cdktn/hcl2json`, which chant lazy-loads and names in its error if absent. This
192
192
  tier guarantees the first thirty seconds of the video.
193
193
 
194
194
  **`--live` is the full video.** `behold demo carve --live` boots a scratch
195
195
  Floci (`behold-carve-floci`, its own port, deleted on exit), arms
196
196
  `legacy-tf/floci-override.tf.disabled` (see its header) into the demo copy, and
197
- `terraform apply -target`s the starred resources into it — so the tfstate the
197
+ `terraform apply -target`s the starred resources into it, so the tfstate the
198
198
  advisor reads is one terraform really wrote. At Handoff the stepper gains a
199
199
  read-only **terraform plan** button: before `state rm` it shows a no-op, after
200
200
  it the carved bucket is simply gone from Terraform's world — `0 to destroy`.
@@ -204,7 +204,7 @@ never blinked."
204
204
  The observe beat is footage now, not caption: after Emit, "▶ watch chant read
205
205
  it live" runs `chant lifecycle diff prod --live` in the carveout with the
206
206
  endpoint pointed at the scratch Floci, and the bucket reads OBSERVED —
207
- `EXTERNAL`, ownership `foreign` — while Terraform still owns it. That is
207
+ `EXTERNAL`, ownership `foreign`, while Terraform still owns it. That is
208
208
  chant#1647's physical-identity read path (chant ≥ 0.44.12): stack-absent no
209
209
  longer means confirmed-absent when the declared `BucketName` names the
210
210
  resource precisely.
@@ -223,7 +223,7 @@ grey band, so expect `-target` rather than one apply of the whole estate.
223
223
  and as of chant 0.44.7 (chant#1637, chant PR #1640) the emitted `Bucket`
224
224
  actually carries both: `VersioningConfiguration` and
225
225
  `PublicAccessBlockConfiguration` come out as native props, not an "unmapped
226
- Terraform attributes" comment. That used to be the rough edge here — a fold
226
+ Terraform attributes" comment. That used to be the rough edge here, a fold
227
227
  that was reported but not applied, so `chant build` failed two AWS policy
228
228
  rules on source the advisor called clean. It is fixed now.
229
229
 
@@ -237,7 +237,7 @@ here would show up scanning the `.tf` by eye, because there is nothing to
237
237
  find — only an absence.
238
238
 
239
239
  Verified against chant 0.44.7. The walkthrough's Emit beat still shows `lint`,
240
- not `build` — the step's "why lint and not build?" note says why on screen —
240
+ not `build`, the step's "why lint and not build?" note says why on screen —
241
241
  but the reason changed: `build` doesn't fail because the fold is incomplete
242
242
  anymore, it fails because the estate really does have a policy gap. "chant
243
243
  found a policy gap Terraform never noticed" is the honest line to close the