@uzysjung/agent-harness 26.169.0 → 26.170.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.
- package/dist/{chunk-SU2RUN2W.js → chunk-MGFWOWF4.js} +13 -9
- package/dist/{chunk-SU2RUN2W.js.map → chunk-MGFWOWF4.js.map} +1 -1
- package/dist/index.js +1606 -600
- package/dist/index.js.map +1 -1
- package/dist/trust-tier-drift.js +1 -1
- package/package.json +2 -1
- package/templates/agents/implementer.md +3 -0
- package/templates/agents/reviewer.md +3 -3
package/dist/index.js
CHANGED
|
@@ -37,14 +37,15 @@ import {
|
|
|
37
37
|
assetCliSupport,
|
|
38
38
|
assetReachesCli,
|
|
39
39
|
assetTrustTier,
|
|
40
|
-
backupContent,
|
|
41
40
|
backupFile,
|
|
41
|
+
backupFromCopy,
|
|
42
42
|
backupIfLossyUtf8,
|
|
43
43
|
backupOriginal,
|
|
44
44
|
buildAssetEntries,
|
|
45
45
|
buildAssetSpec,
|
|
46
46
|
buildInstallLog,
|
|
47
47
|
buildManifest,
|
|
48
|
+
claimBackupDir,
|
|
48
49
|
claudeRecorded,
|
|
49
50
|
claudeTargets,
|
|
50
51
|
collectPolicyHashes,
|
|
@@ -104,7 +105,7 @@ import {
|
|
|
104
105
|
targetsInclude,
|
|
105
106
|
upsertHarnessImport,
|
|
106
107
|
writeInstallLog
|
|
107
|
-
} from "./chunk-
|
|
108
|
+
} from "./chunk-MGFWOWF4.js";
|
|
108
109
|
|
|
109
110
|
// node_modules/sisteransi/src/index.js
|
|
110
111
|
var require_src = __commonJS({
|
|
@@ -802,6 +803,587 @@ import { join as join2 } from "path";
|
|
|
802
803
|
init_esm_shims();
|
|
803
804
|
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
804
805
|
import { join } from "path";
|
|
806
|
+
|
|
807
|
+
// src/legacy-fingerprints.ts
|
|
808
|
+
init_esm_shims();
|
|
809
|
+
import { createHash } from "crypto";
|
|
810
|
+
function legacySectionKey(lines2) {
|
|
811
|
+
const out = lines2.map((l) => l.replace(/\r$/, "").trimEnd());
|
|
812
|
+
while (out.length > 1 && out.at(-1) === "") out.pop();
|
|
813
|
+
return createHash("sha256").update(out.join("\n")).digest("hex");
|
|
814
|
+
}
|
|
815
|
+
function legacyPreambleKey(text) {
|
|
816
|
+
const pre = [];
|
|
817
|
+
for (const line of text.split("\n")) {
|
|
818
|
+
if (/^## /.test(line)) break;
|
|
819
|
+
pre.push(line);
|
|
820
|
+
}
|
|
821
|
+
const head = pre.filter((l) => !/^# /.test(l));
|
|
822
|
+
return head.some((l) => l.trim() !== "") ? legacySectionKey(head) : null;
|
|
823
|
+
}
|
|
824
|
+
function rows(text) {
|
|
825
|
+
return text.split("\n").filter((l) => l !== "").map((l) => l.split(" "));
|
|
826
|
+
}
|
|
827
|
+
function keySet(text) {
|
|
828
|
+
return new Set(rows(text).map((r) => r[0] ?? ""));
|
|
829
|
+
}
|
|
830
|
+
var FILES = `
|
|
831
|
+
.claude/CLAUDE.md c8a0f19e0c84faec6fc0a999efbf205d72270a1f8bcb8d28894d564431405b52
|
|
832
|
+
.claude/CLAUDE.md c833b9a2b3e762563bdf8984520257579408de387ce3021ac2c606551f39aa75
|
|
833
|
+
.claude/CLAUDE.md 5a167acf64d246b278f878228f07cf76fe2a808e201d3d82c1c0274f50d736de
|
|
834
|
+
.claude/CLAUDE.md 7fbfe6999a82a880a3a0d34bdaf8e263cfd9c927ef5fb33873059182094d3f7f
|
|
835
|
+
.claude/CLAUDE.md 1dc65a4d8c0f2c47d541852f767d85dca41637d7b4009db6dbf41a0beb20ff68
|
|
836
|
+
.claude/CLAUDE.md db2c8bc13b4d9882c71ab1977e5fc5aa66fb031d5943faba587ce9eba100a0b8
|
|
837
|
+
.claude/CLAUDE.md dca32656dfd75c8676504836501607b7c821115a6dd14cba7baafb5c631cb1ff
|
|
838
|
+
.claude/CLAUDE.md 3aeeea1767e0f910adff08340895a524df829240df93d298bb3d0e327d0711e0
|
|
839
|
+
.claude/CLAUDE.md 16347e86e7c1699db212586685a640135891ec5787ba486e0a12562d85bc9b60
|
|
840
|
+
.claude/CLAUDE.md 71db56ff054601a03f8e287a965c1eb1be64d9db1fccc3b03c1f499c2f23119a
|
|
841
|
+
.claude/CLAUDE.md d92c6bbc4c2c1c7a2547e697f7f128b7918d4e2062c9af958b729e7cb0c58308
|
|
842
|
+
.claude/CLAUDE.md 7f94cca4a8ca2f257164ba9b44360d10f99030d3b636c667f65fd0a1771e123c
|
|
843
|
+
.claude/agents/build-error-resolver.md 28597d1e97a68701999704b789a97a20a28b121b7c27ee6a6e80ab43bcd514b8
|
|
844
|
+
.claude/agents/build-error-resolver.md a050a74ed31acba06b36e8c34bc35bc0e684b6b7ab01c891dfc2d13ba94f9824
|
|
845
|
+
.claude/agents/build-error-resolver.md 59f9eb1ae55c6a943d43610cc4e74d05018d681758ac19cb31d874c51605914e
|
|
846
|
+
.claude/agents/code-reviewer.md e112e5e0bbc501788e8a3bfd2771d34e31a8564bbd87391bff7401af1509782c
|
|
847
|
+
.claude/agents/data-analyst.md 1d75c07c51b8a000e536cd8a1c23e0609d93ea51b02cd48f9877610082cb2475
|
|
848
|
+
.claude/agents/implementer.md ba0ee71bf5ae6f8aeb461b0d6161fe0869a7c45820d49145b2abf27264af7dd2
|
|
849
|
+
.claude/agents/implementer.md a12f9132a55526208837e4960c96705df595c0e1cc2870eba1e56f2a87632de1
|
|
850
|
+
.claude/agents/plan-checker.md 405be32ad0d95d8d4cbc8cddb94e7b2be74981a4dadc160aa9200156b56d40df
|
|
851
|
+
.claude/agents/plan-checker.md 467ddec15189cc4273adacd08f97e7eabe1cc164901882f2dd5bba81fbf72327
|
|
852
|
+
.claude/agents/plan-checker.md f605005ba6ebf1e3494e47e257d68a2d34317d15a47b5c8b52317d9cf914b004
|
|
853
|
+
.claude/agents/plan-checker.md 86ad22297e6f1d75d42146685d759af10698cf763feb1c9484d1f0437262e833
|
|
854
|
+
.claude/agents/plan-checker.md 451181ce44f67f747f7190aa53932565df1ce6c934da4584f03f339502fb9265
|
|
855
|
+
.claude/agents/reviewer.md 4036905c0b8deff6555c9f6cbe962609c243d063c417196cca57fc6f87139cd6
|
|
856
|
+
.claude/agents/reviewer.md 1a0153a7fcc8a170f3f08f2a4e392ca72117d413d690441b930028ce923a6094
|
|
857
|
+
.claude/agents/reviewer.md 98c63bfe35afafb28b2543e5b3c662a5df58b66b877b753efc54b9af32208298
|
|
858
|
+
.claude/agents/security-reviewer.md eacaa50c2b2fdee398ba2e3c896c018ea8887d34701e5b841278ea2c1472cc19
|
|
859
|
+
.claude/agents/silent-failure-hunter.md 004ce0389356e0666d80c89cef39ad895ab326b3f7d19d34d23c70ab249a795d
|
|
860
|
+
.claude/agents/strategist.md b217c7bd273e672de44d4df123201cc5c10203fa9bafad84a370d4b7d32b7fc6
|
|
861
|
+
.claude/agents/strategist.md b8d0b387748b5403ee6a489c7e9969f864ebad9544d3d34ee9ff1b4d40f4662f
|
|
862
|
+
.claude/commands/ecc/checkpoint.md 7462e42241b4e38ca4826750567002420f014089b81406279248e22e5879f608
|
|
863
|
+
.claude/commands/ecc/e2e.md fdc040d9d32ca1c4bcc53ccca32042983f9132240fcaca5144de51e4385b9479
|
|
864
|
+
.claude/commands/ecc/eval.md 586ffc66cf889428ff46a86c0d8067f925d58899758eea5f129c9fa62ca55f5f
|
|
865
|
+
.claude/commands/ecc/evolve.md b4a635e1fc9e70f5f53c8bb36a1e8a385e249b5802afaffcc54e17cbacc1c8ca
|
|
866
|
+
.claude/commands/ecc/harness-audit.md ba76cdd30f6fdcf9b6286de753881eebe0e15306829bc3cf53af1591e4126771
|
|
867
|
+
.claude/commands/ecc/instinct-status.md 642b16d6b155f635b76800d78618f4525fc7db9fa298e947e7651e5b3d5fe85c
|
|
868
|
+
.claude/commands/ecc/promote.md b8e6e79dd43053a183b426e88e31631dfe6c812efd37241e26798b88b3febdab
|
|
869
|
+
.claude/commands/ecc/security-scan.md 440cb02294593a8cc86bb1e707fe43a28506f2833de6e20ec811cab12a543db3
|
|
870
|
+
.claude/commands/uzys/auto.md 39e06b3164527fc59bd1cdbf156cdf1f953aab188c68603bce7a396f51921b40
|
|
871
|
+
.claude/commands/uzys/build.md 3eed86d0f9bd8b60724d829a95578e7febab0043a6bdd6353993b2a55021a908
|
|
872
|
+
.claude/commands/uzys/plan.md e1c11ecaa804b6a333f669a8a375b06fc8ba245d9683aed0f172c3fdadf8b4b7
|
|
873
|
+
.claude/commands/uzys/review.md af4e3a4af894bc161f966c64fda60cdc83d815c174f3ad1f9c0a0d40d76a07b6
|
|
874
|
+
.claude/commands/uzys/ship.md 572a644f37c41e1844b95701fe116b2b6e71f22d0ef8593725ab2de24d61207d
|
|
875
|
+
.claude/commands/uzys/spec.md 91ec49031ec683dcd9c5a2befa9b8aca3c95ffb415928b95a2fefa113e102554
|
|
876
|
+
.claude/commands/uzys/test.md 63e58f69bb431a3995b9baae6f6c55f958ae0c46a3d89740ec551fab4b3bb920
|
|
877
|
+
.claude/hooks/agentshield-gate.sh 9493cb98409a5b7b4368307ecf535f39c32d933f8f012f79c9c2b6c2fa788012
|
|
878
|
+
.claude/hooks/checkpoint-snapshot.sh 8ef77c09baa3e24740b19a7d119b83e58559cafcd8e6ab4edfaacc4e42caffef
|
|
879
|
+
.claude/hooks/checkpoint-snapshot.sh f86e7f445cad48569353b9cbce6e162074fdb5224f4b0781734f5a200b94868c
|
|
880
|
+
.claude/hooks/gate-check.sh f04831db7fbce538cc9c9cbcada62a7917e621e6275365686c4849e39da14583
|
|
881
|
+
.claude/hooks/hito-counter.sh eb79ca20fcbaa070c621d5c985422e68e5dbe6b9f4c25f7bf81ae82fe77f6d49
|
|
882
|
+
.claude/hooks/karpathy-gate.sh e72ea3c24cbb953ea7786504362a45f8ec07473a89aeb2006bde2fe0fb6b51c7
|
|
883
|
+
.claude/hooks/mcp-pre-exec.sh 3a7b64149a45dca9e1c15a793e1e84cc28d1f7675d7b519c38cf4b4b27ef5219
|
|
884
|
+
.claude/hooks/mcp-pre-exec.sh ad7f79a13eae3b59e530f00c5ca37b05b01df6629d2c09034bb4f3ac55429120
|
|
885
|
+
.claude/hooks/protect-files.sh f18aef8b355be30afc14e097e8f152a0f00351342e9c1505859f400b445af242
|
|
886
|
+
.claude/hooks/protect-files.sh 0190071614b9466bd4f29189b99f839eceecb08b480f397e5937f8087e6aac08
|
|
887
|
+
.claude/hooks/protect-files.sh 416780a048c3bf674e4348e8982906ae768ca81480b46b56c0fad800d9f21d55
|
|
888
|
+
.claude/hooks/protect-files.sh 5408a423eaade935d984d187f6f93387869cba9423b4644120f30025df4a7b5d
|
|
889
|
+
.claude/hooks/session-start.sh 1c2ffddd804bc82bd456b6cf6e1566084f6c5b43d3596b418e982d073bdfdfb1
|
|
890
|
+
.claude/hooks/session-start.sh b82d19dda66419967708a9937746d03bdd099886f9e7ed9103254209017f1147
|
|
891
|
+
.claude/hooks/session-start.sh 894ebdc240b80b37da93b4124994471c1cb0a26d8592d7a621d8fa3a748e8c79
|
|
892
|
+
.claude/hooks/session-start.sh dfad4b1add755a7efa89cacd370ba418c629f64911d1e0da1bcb19502bbc5948
|
|
893
|
+
.claude/hooks/session-start.sh dcea99eab4c03341b2c571185e8433379e3c5bcfa5bed35d8f1979eee3a45c1a
|
|
894
|
+
.claude/hooks/session-start.sh 490b1d99f6d901d63e48a8122d67225f5c48cc835db0f410fed91c364666ba2e
|
|
895
|
+
.claude/hooks/session-start.sh 613156711d285ae2dc3ac6b1c26d72b7f92f90c80639c6aed1c5fe982bc68114
|
|
896
|
+
.claude/hooks/session-start.sh 238e4a9565b2cde0809fed3b49059fa5b3189ad1c2e86d4963fcbf5e73de7152
|
|
897
|
+
.claude/hooks/spec-drift-check.sh 48e2c5ed391086c842a9a647dcafe50d757513b993561c3137c9cf4ecf96f7b8
|
|
898
|
+
.claude/hooks/spec-drift-check.sh d5bbbfbc3da3bc3eb2d3ac06cc10dc02426ec9472f4fba68300b895c3ffb24ec
|
|
899
|
+
.claude/hooks/spec-drift-check.sh 43f01059a5cc1d779c9e80eb4207fb4e263d853f5a367dbfd45b0b77685d0e28
|
|
900
|
+
.claude/hooks/spec-drift-check.sh d979fffa4f45c4ac03940a70abfa63860bf2a22fbdac9469a43f64565a6abdd2
|
|
901
|
+
.claude/hooks/spec-drift-check.sh 1c7c81e4009866b204e03fd7c4eac87a1b66d7b467a747393dca2bab6793eee2
|
|
902
|
+
.claude/hooks/task-brief-nudge.sh a5bca92a610efab0d770c96e12d3f6996cb184ae0175005724635a9a920fefac
|
|
903
|
+
.claude/rules/api-contract.md ae12cbcacd6380d41d13ca87d0e6f5d589df9f8561f408618cb365e144afced3
|
|
904
|
+
.claude/rules/benchmark-parity.md 595149aec4ed190e7ea96c11c271fa6b743f7ad8c38910dffd2cc180d9a51e8f
|
|
905
|
+
.claude/rules/benchmark-parity.md ee33155ed0ac2c267d0ebacb5f89335cca7dd679c5b2d54ffec81c4738bd9be3
|
|
906
|
+
.claude/rules/benchmark-parity.md b602bc9fc5627ec1e964915240f15748bd13e5bd99737346dbd8d3d2e7c633a8
|
|
907
|
+
.claude/rules/benchmark-parity.md f98f9429c3250ba860b1d39ca304854de0c9e905cdd12fd068d57025e40350e3
|
|
908
|
+
.claude/rules/change-management.md d21082487eeef59664899f85df6098bd46e3c74dbba3f2ebf9e49cf5bab64c34
|
|
909
|
+
.claude/rules/change-management.md 62b7932f691664459d2d7b0971c6aaee22cfeb5f9103ca1145cc55631a072077
|
|
910
|
+
.claude/rules/change-management.md 264b79b82de252cfc933d63708ac8bdf9f18c74f388063d62960456dfa764e2f
|
|
911
|
+
.claude/rules/change-management.md 611bb3a89d47d5b43ac22de8be59edbdf9b700959901d1fa878dc0f89d9ec40e
|
|
912
|
+
.claude/rules/change-management.md d2977a144259dc744835d9bb6c3cfa8d1b390f5393c34d883ba0f67a6bc4dc3e
|
|
913
|
+
.claude/rules/change-management.md 20c548a1380f1e5e9aad5821e0bce0ae999a2dbcfc1f564a990bb30f3590d418
|
|
914
|
+
.claude/rules/change-management.md 0c46f2fe8a9045c14a93895a1614b068d04a4b0e96c183d46ab688e57885c6a6
|
|
915
|
+
.claude/rules/cli-development.md a0bfd2fe69336e8b3bf329a2029d926c96192bc24e784f22f7b99861358829b7
|
|
916
|
+
.claude/rules/cli-development.md b116324d53c7ed3b36d51474f17bd61eede610dff7abea4d3533656dd5cf9a34
|
|
917
|
+
.claude/rules/cli-development.md d5a267f7e22c9d292693857577c2e5819811147b561a38c15b450740d4dce98b
|
|
918
|
+
.claude/rules/cli-development.md 158b76f589d0588f07453b4c47bf9368117467843cda37ddc8bec7197cd671b3
|
|
919
|
+
.claude/rules/cli-development.md cc0545a04706c18304eb92c365d691986d511f02436f405894306e829b4f5b8e
|
|
920
|
+
.claude/rules/cli-development.md 27f7696b1ed13ae15f9e0bfb4bdf2206325f42d87cca6e1a6efcc76f6c9d32bf
|
|
921
|
+
.claude/rules/cli-development.md 73813a5f6f0111507430c1f83c9a099b870bc2a03c16a391817dc74444597eaa
|
|
922
|
+
.claude/rules/code-style.md 2e67fc49d4c8eacaa6dac9064cf566d7f3039509a5b6c5f03b5b2126b0043def
|
|
923
|
+
.claude/rules/data-analysis.md 81b87e41919f7a7a4b06ff459a127b1c44ff6804876856eac0b17da8b0568695
|
|
924
|
+
.claude/rules/database.md a421fe0ffea76ec480cd9cc90ef753ceef7bff3ad4f49ee7837786960b634ba5
|
|
925
|
+
.claude/rules/design-workflow.md 5b6a40c9004355420de2f647c782728e47eb6b01722d7453acf570b6aa002dc7
|
|
926
|
+
.claude/rules/design-workflow.md 49fc2c7efedac467d52031b3bedd7d33fec9c73dff45d20071a5456b82015cd3
|
|
927
|
+
.claude/rules/doc-governance.md 0618fa6f93d245cb46d42862b881fa840e54b196e759d748937d7098c60eed71
|
|
928
|
+
.claude/rules/doc-governance.md e3b2197e19609724e6301ff6035ec9d34e5a60b5385bb4f48a2b633c3c3ca2d5
|
|
929
|
+
.claude/rules/doc-governance.md 5569bb742cc2c0666b2431e3eb662d5fdeb99f8f7224506e0379ce618c4bdf61
|
|
930
|
+
.claude/rules/doc-governance.md d83292a77146ae96e7adcb2dd796811ad8af979526e8d81b1a33bce8cebe6b7b
|
|
931
|
+
.claude/rules/doc-governance.md 54157849bbf9897969745f1d162181b93f4dd9260ae18d4a890b6ad014232797
|
|
932
|
+
.claude/rules/doc-governance.md 8d508bf15bbc1e87b8d0820a6e54a6d5de4b243ae8859ee98b6657d60dfbc7c7
|
|
933
|
+
.claude/rules/doc-governance.md c6f2bb6210ae076acf15e6928a8bb20adbd9d40727433c462d5e1b5eb73803de
|
|
934
|
+
.claude/rules/doc-governance.md 5257f74d94188b18977670a4299658673e00d7b227c54ebb19e00ab019d9adfb
|
|
935
|
+
.claude/rules/doc-governance.md 364c147096985e1fad1a03457ac864a6e4839d8d9487a5c7f20fbaafeeb43eaa
|
|
936
|
+
.claude/rules/doc-governance.md 589e70962b426503098c5d1a60da4b11f9a0c97a654d3ccac900d58f02b7fb52
|
|
937
|
+
.claude/rules/doc-governance.md 7a79bba801a1fb3695566bc19c9bd2f89456219560d76ac4f2bcf405c238b6a1
|
|
938
|
+
.claude/rules/doc-governance.md 3360574fb55f332cf3de18ea32506326fb2880651a593c0bec0246337633fe80
|
|
939
|
+
.claude/rules/doc-governance.md c14e70d6fc5b0ca8e9385d293cccdc39512ec6e73fac6f34ed723572acbebd97
|
|
940
|
+
.claude/rules/error-handling.md 5ea6a188e3a925d5f1f38c1defb766bf71af7a408b58ecce208c7fd3059aa843
|
|
941
|
+
.claude/rules/gates-taxonomy.md 2276e03e41463f946d5b4867c953579aab91445bb781a4d24ecd9337d2f67e3d
|
|
942
|
+
.claude/rules/gates-taxonomy.md 8a5162bd03f20c92230e2bd84a879de5f5d24a5746e6489f3dc895891055f4a2
|
|
943
|
+
.claude/rules/git-policy.md 932e24935cdd20f088b4a3a75a493cb454e065c75e294283fd01a7a768bf9059
|
|
944
|
+
.claude/rules/git-policy.md 3c0cf97e7ec6d921cb8b066d6d34a9f70f57fbdb0c78e9ab11cb919a4251da0d
|
|
945
|
+
.claude/rules/git-policy.md 0d8d01c7b471b4623be31221e773b7298bf230aa102394e0384859db5393b0c6
|
|
946
|
+
.claude/rules/git-policy.md 1c83e7e9acd5967d31406fec70a231cd8de09d5931eb7ca8ebed68f428c3d081
|
|
947
|
+
.claude/rules/git-policy.md 421e837c323bed48fd7e51d02e3c27dd479037d67ecce9dbcc0da3b8c1e764b3
|
|
948
|
+
.claude/rules/git-policy.md 02e127647bee532d0ffc5b994eb2f554f42e96b10529618f953e9b27a3ec0ab2
|
|
949
|
+
.claude/rules/git-policy.md c4f5c1f4b33f3f91aebe673b736b3dc76db785a225d0214f29ab6ceccec26550
|
|
950
|
+
.claude/rules/git-policy.md e1ebe8b7abf6e61015bef44c6f848f13ae8cafe16384b765b35905efecf0a21b
|
|
951
|
+
.claude/rules/git-policy.md 469077325ea8c4a67dfe827014370bc099494998f55aa76f864f6411b40b07d8
|
|
952
|
+
.claude/rules/htmx.md 4faf811dcf5b2b85f899507b249db4853b328c73b2d45760106c1b2132b53c83
|
|
953
|
+
.claude/rules/nextjs.md 855eb2f49b830a89ebd9b92f29a05ea3348d6dda032d2a267c15a5c762371ea5
|
|
954
|
+
.claude/rules/no-false-ship.md 964853f056a2ed898b09648faaf5302d471d3e723dc8e15d387e32aba82eee14
|
|
955
|
+
.claude/rules/no-false-ship.md 2d760fd1f3387233703c04127bc595874a835ea46a50055d7c506cdbc7ece5cf
|
|
956
|
+
.claude/rules/no-false-ship.md 9098f58fe799367cb6cfc02779715b02c4f0a2e5c24539fb2d65f5eb36332762
|
|
957
|
+
.claude/rules/playwright-launch.md 770232379a9205f0466804b83edb4f53e1ccef2fcbc5e82b8e0c5b0a96fac783
|
|
958
|
+
.claude/rules/playwright-launch.md 1bf90d35a050a1f0d712f406329d687bf9bc7661ed0a183e83613bfaef895820
|
|
959
|
+
.claude/rules/playwright-launch.md 783be44da36bf9eaef56d0117d6cd19b7c0c1ef9242745b3f3f87721e84f2664
|
|
960
|
+
.claude/rules/pyside6.md 19c092d5fd7691818e9a759bb23173c9aa1f511c4766a67a9e7fa918b7062852
|
|
961
|
+
.claude/rules/shadcn.md af1fc4624cdede22a35d087b8a7fb4ef042302e2c998373c73f018736e68e5a4
|
|
962
|
+
.claude/rules/ship-checklist.md 14319e7639aa4827690099efd5ad228c997e56a9002eeba6c90e7f274c44bb12
|
|
963
|
+
.claude/rules/ship-checklist.md d371f417f9af32a72afa99e38378d5a95a085ea5c8ad106328cf41a5f61cf117
|
|
964
|
+
.claude/rules/ship-checklist.md 27d3885cc3944a1a4d92dbd8e0d51ac943d7971d2284db77244deafe007c2906
|
|
965
|
+
.claude/rules/ship-checklist.md 286fe3b971c1aa72bb41f610c576ef6d23a9778ed4ab4cbbb493d1f241494a44
|
|
966
|
+
.claude/rules/ship-checklist.md e5d1dc357c54026f473ffba52b6ae3746ef49173b8270fea6faf16fbc2ec7b10
|
|
967
|
+
.claude/rules/ship-checklist.md 6825d1ce40a817f9fa004256b17b0685eb1ccb69ea27641c97e53dd5e323e755
|
|
968
|
+
.claude/rules/ship-checklist.md e713a2738dad8a03d16f0cb1b24a7b207bb4a1445766f883391a0b4a8ad6a766
|
|
969
|
+
.claude/rules/ship-checklist.md 0d9988b3d6b387dd13738c5f1667a8f07e72929f5515168e2ef6e94ad4c0da88
|
|
970
|
+
.claude/rules/ship-checklist.md 1b42169da6e29bfee8ea695831154f672d7cabd8816d1993678c4955a43ed1e4
|
|
971
|
+
.claude/rules/ship-checklist.md 9423f862188ea0ddcb5ec9594e457988c23dc80a0bdba7ed6cc7630f8cc4623e
|
|
972
|
+
.claude/rules/ship-checklist.md be7e93da56b688c9b90d5392dc29b16197d5d4857152f073eb39d1c737952a02
|
|
973
|
+
.claude/rules/tauri.md dd429a144c71f1205384abb5c305b373908e8f6c2c4ae7d6b4dfa9fa707e972d
|
|
974
|
+
.claude/rules/test-policy.md d775453a9b0c3fd7f65eba039e512ec6fc92eda448a2218738da6bb1c85a3023
|
|
975
|
+
.claude/rules/test-policy.md a106e6952520eaa2cebedb9a20a47ee12a8bd0069639077f324cc1d93e3d5501
|
|
976
|
+
.claude/rules/test-policy.md 1b6f0c2fab4842c974c11dd53b22320fb5593870390e0c375625ec584196e580
|
|
977
|
+
.claude/rules/test-policy.md cc73a7e656c237c4313bfa814a9eadab5a44542ff8dbf250fceaf97d6ae1f05b
|
|
978
|
+
.claude/rules/test-policy.md 87660a29cbf43f49e24fd7f53124f0383c94c8333138d1cc1ab9dc233b5e8a4a
|
|
979
|
+
.claude/rules/test-policy.md 54426764c08cadc8c1b31bdaa5817f5c4aefc359d263bd13051949aec7858c0b
|
|
980
|
+
.claude/rules/test-policy.md 9f1e71e12db41a3b20653854c66adcb224c47e86d6a5815d3b7002418cae458b
|
|
981
|
+
.claude/rules/test-policy.md 95b9c6af6a63e4cc85488e109f42440b7f7d1892c73d5b96b7ab387354303cf4
|
|
982
|
+
.claude/rules/test-policy.md 3460db5bbfaea281e417c55b5a76236b10c64c38cf38fe16b934f6799c1268b5
|
|
983
|
+
.claude/rules/ui-components.md 836b66be19c773b3cfa2ee92ed29bd802d8883a55da21cf0be9b73e25a2c8ebe
|
|
984
|
+
.claude/skills/agent-introspection-debugging/SKILL.md aff0d52785d3013d9f98de95ca778bfcab7c566db20352ead42852a1659292d2
|
|
985
|
+
.claude/skills/agent-introspection-debugging/SKILL.md f03dc3838ba8b81ad6a87959a2d666f8d5915d3516cea60d12a65ce74685c54e
|
|
986
|
+
.claude/skills/asis-tobe-decision/SKILL.md 8880ea604b8458acd30b8dc515efc54a6a1640590c572d5f4be7034cbd2d7242
|
|
987
|
+
.claude/skills/audit-harness-fit/README.md 885c756b8fbe51d23747667d3d96ba8c76e1c0e5fb48030cd394b0dad4c304f5
|
|
988
|
+
.claude/skills/audit-harness-fit/README.md e1295cd42a0671d373d7d071374918abdc37aa294052ed6bde8511ac07e80039
|
|
989
|
+
.claude/skills/audit-harness-fit/README.md 2aa6eb69e9991d0156b140f5c4ca36dd87b32ad006aa8dc176f173e7a864ecb9
|
|
990
|
+
.claude/skills/audit-harness-fit/SKILL.md 6919e5c6fce93b4262392ddd9e0476b700e921e39a91ab646bf48f05f4fbe39a
|
|
991
|
+
.claude/skills/audit-harness-fit/SKILL.md ccf5817e3ebcc7575e409b4a1c397f2ef23d690e355490487b2bd829736d1ab5
|
|
992
|
+
.claude/skills/audit-harness-fit/SKILL.md 85c489aec23eb0b9f907c3b10395dabbe03add8300f6d365e886e02f833fd769
|
|
993
|
+
.claude/skills/audit-harness-fit/SKILL.md 5f20eaac20e77c3207978857e2424bcb86d5681362528eed7cc3a09afdffb845
|
|
994
|
+
.claude/skills/audit-harness-fit/SKILL.md 3c348fe635f8b389a349db3f686ebca4f49e1ef7058aa3b4c6e0211e51c12562
|
|
995
|
+
.claude/skills/audit-harness-fit/SKILL.md 9dfd4565013a630c0aa66c9396b4d4073fe70f8601bff89989ebe162da7beb76
|
|
996
|
+
.claude/skills/audit-harness-fit/SKILL.md a23c98c78fd9c5f4660dd73058d58eaf78aa49c107bbc0e3c60de73231f5c163
|
|
997
|
+
.claude/skills/audit-harness-fit/evals/scenarios.yaml 016257464f98f62433e2aba5a064405f41128b54eba05e3702cf44ce93d97ae6
|
|
998
|
+
.claude/skills/audit-harness-fit/evals/scenarios.yaml ac6355013fb7be658196e135ac449bfa5afdc564adb1d5d1ed10d65a64d16e04
|
|
999
|
+
.claude/skills/audit-harness-fit/evals/scenarios.yaml 714fe2ef457dd38fc9b3b354b7f2d616c5d7121770ef1dd889d008eaec661159
|
|
1000
|
+
.claude/skills/audit-harness-fit/references/apply.md e4803a5d6d6c0d32c9808172a03f0f555320ef29fdf73277dd4fc535c4474d77
|
|
1001
|
+
.claude/skills/audit-harness-fit/references/apply.md 97886bd748ef2e2d9a979dd0cf65c5acf81a90c2a19d08851ce87c66df933f92
|
|
1002
|
+
.claude/skills/audit-harness-fit/references/apply.md 6f38cb6673546bfe6609ff6ae18436e5487f93386ac1bfb4625f9c85997c36e6
|
|
1003
|
+
.claude/skills/audit-harness-fit/references/audit.md 39d077f20624e69582ac0e2df28d192c08e8246f8c7dfb8e471e7c461f1cc5f0
|
|
1004
|
+
.claude/skills/audit-harness-fit/references/audit.md 973605514d4eb560b79ff267058e6dbd47bd61b53752f3f91e7f49a4904eac4f
|
|
1005
|
+
.claude/skills/audit-harness-fit/references/audit.md 328d620140846005bf326998387e9305371bf95b5e95cb3a9e7272377e26277a
|
|
1006
|
+
.claude/skills/audit-harness-fit/references/audit.md 4b4eef5a9060ad0a7fb264b261c69802c1c3f0e7c61787ccca18be898c84c091
|
|
1007
|
+
.claude/skills/audit-harness-fit/references/audit.md b93eba13d00481e391fc05e70d894164661ae689f28b08d47514e2c35ebfc790
|
|
1008
|
+
.claude/skills/audit-harness-fit/references/official-criteria.md b80c77f12fdf1752f671eb1c0f8edb6f4f34c3777d6753b9af713f91cff77222
|
|
1009
|
+
.claude/skills/audit-harness-fit/references/populate.md 48227ddac79899f725769050f6105aff0b352d47f72b01341e836362db943ad3
|
|
1010
|
+
.claude/skills/audit-harness-fit/references/populate.md eabe235e5e097ad44a42588201ed89dca359e9fd1a301e29be02deb0338d38cf
|
|
1011
|
+
.claude/skills/audit-harness-fit/references/verification.md deff70dc0f419a760e8b280a2ae57b43a0ae859c17fb6627ea749741b855ff62
|
|
1012
|
+
.claude/skills/audit-harness-fit/references/verification.md aa367e0655a98ce575919e5c30687713187346a7976b97fc1081a99bbbef6ce3
|
|
1013
|
+
.claude/skills/audit-harness-fit/references/verification.md 18bd5f577b85cb043229ca9df160ec9c0f3fb70d01c3db5abb5ccbba7ae6dab1
|
|
1014
|
+
.claude/skills/audit-harness-fit/references/verification.md 695c1f08c6bee5de28d0edfec796df12ca5fbff8cdb473bafbda6fb7f3cff79a
|
|
1015
|
+
.claude/skills/audit-service-gaps/SKILL.md aefd2a47a0b9c2b6bd1846151e60cef0147d0bfbb4b1933da2431f980a0f2922
|
|
1016
|
+
.claude/skills/audit-service-gaps/SKILL.md ba9ac6df2315538935aff945f25a7596b3a9e478c4cdcb3a218ff404f4b612d7
|
|
1017
|
+
.claude/skills/audit-service-gaps/SKILL.md 81323cc7d4bda9f3739e8a72f566699d209f888aa216f77f106e77db975f231d
|
|
1018
|
+
.claude/skills/audit-service-gaps/SKILL.md bbc7782ea688ae74f12934145c1041f58a029eb07d9979c316849cb9fb88f56e
|
|
1019
|
+
.claude/skills/audit-service-gaps/references/modes-and-evidence.md fa73b3edf2c55f5caf47f1f2d930d8c2ccd737af0a2def5f40a1db942029275d
|
|
1020
|
+
.claude/skills/audit-service-gaps/references/worked-example.md e5f31f498e864dcaabe2a0d6a05fe1d64cd8be6a1b79a18de78bcbb42e06d658
|
|
1021
|
+
.claude/skills/chatgpt-delegate/SKILL.md 0e614e643bb8bad52db3663ff9394f77ef6c89a6c72c529796deeed824eca0f0
|
|
1022
|
+
.claude/skills/clear-korean-communication/SKILL.md a8afb5e0114332fd7831de12a12cd981e95726458df61f1a3fdb6160086aedc5
|
|
1023
|
+
.claude/skills/clear-korean-communication/SKILL.md fe480eb8357a79abcc1f6c5954c61f0a8b3e7479b9835b7fbdead18a9dac4b46
|
|
1024
|
+
.claude/skills/clear-korean-communication/SKILL.md a8a41bd88b2b04c931047f08614f8c431eb8e401fe366d110291201a9fb571e8
|
|
1025
|
+
.claude/skills/clear-korean-communication/references/pre-send-checklist.md 65f93177e9a442332c2c90f4e905c4d558b6349e47d5c86eee7705b76b71a1b9
|
|
1026
|
+
.claude/skills/clear-korean-communication/references/why-it-works.md d4439db6a1765fab5fa6875d0528fe715366c270ea35853ad8bb1404388200cb
|
|
1027
|
+
.claude/skills/clear-korean-communication/references/worked-examples.md d53369cf02c62147510bae3a0cfa878ce89013bed11a30c32cc675dd0a0df825
|
|
1028
|
+
.claude/skills/codex-consult/SKILL.md 0af4f6cd00739e62d73f7adc9c8ea85b0db3ee53432bc5605fbf6bf788a0cd13
|
|
1029
|
+
.claude/skills/codex-consult/SKILL.md 288d6d5f4135b8f3e1d8b06b42b68c238e63c9257f973ecdc4f86445d5619be1
|
|
1030
|
+
.claude/skills/codex-consult/SKILL.md 767b0d65ff96f0a10c2cd81335a5ded2a85394b8e8ab3aa1c7737c6296f22582
|
|
1031
|
+
.claude/skills/codex-consult/scripts/codex-ask.sh 64835a9e11094bc24d9e8f9044a98a699ca45155d516dba926ffb8c145cbf1f6
|
|
1032
|
+
.claude/skills/compaction-handoff/SKILL.md 1b19203ae45869dd43b7ca4b28c63bb5c4267aefc9a62abb17d29bdceee316a9
|
|
1033
|
+
.claude/skills/compaction-handoff/SKILL.md b484a4408f25f4b78bf2e7cd88b1b3fec7b969d6c4a03de8a3b8e072719fc74f
|
|
1034
|
+
.claude/skills/compaction-handoff/SKILL.md 42d8300cddc4bbe78b353c8ff846b5fd8ed2b4a68f1998982900fd31596c1755
|
|
1035
|
+
.claude/skills/compaction-handoff/SKILL.md 59191dc216233b74e5f5a72ed1041d8c236504a386e8b5df81dbf52062dbaad9
|
|
1036
|
+
.claude/skills/compaction-handoff/SKILL.md fe70142b0bbf21b5a7b6e9e5af8f0011e6b8e654746f97f4391384d5143c9701
|
|
1037
|
+
.claude/skills/continuous-learning-v2/SKILL.md 7629ed1a18ce078b57f22f407115a41a7f404aee73de17667ec5571b0001a8e4
|
|
1038
|
+
.claude/skills/continuous-learning-v2/SKILL.md 75485ddb37e2d1d6f056b404d9939bf46a2b409b1286aec209a510112e5b64b1
|
|
1039
|
+
.claude/skills/continuous-learning-v2/agents/observer-loop.sh 25ceefcc260c3599b6d12148d1a573110ace3091c723bdee3a3cf10692e5d4e2
|
|
1040
|
+
.claude/skills/continuous-learning-v2/agents/observer.md 320d50ff2965efeabd6f07c2be134e11da160293e958c1bc27c309d613839ad2
|
|
1041
|
+
.claude/skills/continuous-learning-v2/agents/session-guardian.sh ee6e4c0990f8d538cae1c85aa194e01e9ca2336e5d993ef68eb608b96cb0d82c
|
|
1042
|
+
.claude/skills/continuous-learning-v2/agents/start-observer.sh 6b1966e38eb0c96d61de5d204b87097592884364be59e5bea6007289e8068936
|
|
1043
|
+
.claude/skills/continuous-learning-v2/config.json 6f17e7a99aafe252ecd0b9212fb5f606be50b8ce1685f5a6435e46e87ffeb970
|
|
1044
|
+
.claude/skills/continuous-learning-v2/hooks/observe.sh 285c673af5a5f5fcc0839e924ccdb4b7326c593f9198f690c635b2fa7091feb6
|
|
1045
|
+
.claude/skills/continuous-learning-v2/hooks/observe.sh e632c2f486248b8b141059c23586d5ca0187df8c34f53d7597cd845713e06948
|
|
1046
|
+
.claude/skills/continuous-learning-v2/scripts/detect-project.sh 527917b87d8b35b38baf01ca96c6fc4cbeb91ed9a24c6f9c09e4f4d290555295
|
|
1047
|
+
.claude/skills/continuous-learning-v2/scripts/detect-project.sh a39677edd0ce1deb7628ed31610baafc16090a710233963d2b6a55db64167cf9
|
|
1048
|
+
.claude/skills/continuous-learning-v2/scripts/instinct-cli.py 777193745515c8dce35676b1696c90a85e2610705157205a0b54e8e453b69942
|
|
1049
|
+
.claude/skills/continuous-learning-v2/scripts/instinct-cli.py 0b060a762f0fc4ad56e45cbaa14c14fb9ab3f468763f6a32a17bb864fbd3fc30
|
|
1050
|
+
.claude/skills/continuous-learning-v2/scripts/lib/homunculus-dir.sh 99dfa99ae0f7c6e2e15ed5b5bf3c46e91a5f089f4060ba93d5da5e85e04fd308
|
|
1051
|
+
.claude/skills/continuous-learning-v2/scripts/migrate-homunculus.sh 34f121c143a676d330f06209618aae8cb08f8155298cb5fa70c893314bf9b303
|
|
1052
|
+
.claude/skills/continuous-learning-v2/scripts/test_parse_instinct.py acf556e8a8023347b35988bb490927a4e9f65f2579b03f26cad610687656605b
|
|
1053
|
+
.claude/skills/deep-research/SKILL.md 2d631427fc9aba27a318735f930bdb49f5c6ce416506340025eac01648f1df09
|
|
1054
|
+
.claude/skills/deep-research/SKILL.md 69be70af34e27112f192cbe201210c4cf541c24952670487213de715aa297b40
|
|
1055
|
+
.claude/skills/deep-research/SKILL.md b852bebb31908f352c5397bde6de06ee7ca3c0e1c866fae4dedbd5c4fbb27323
|
|
1056
|
+
.claude/skills/deep-research/agents/openai.yaml cb877e559cfe405d0e12bfc9bcaef657ab05a30ef698e6f3e486e39c5e0a6d2d
|
|
1057
|
+
.claude/skills/e2e-testing/SKILL.md f84ae93c159bf6ecef5a60c9735dc82d96bc5f977ef52eb71678b66722acf684
|
|
1058
|
+
.claude/skills/e2e-testing/agents/openai.yaml 5f50508a300616d77f39dc50a51de10cabd05ef7ae770e7948ef6c28f340cdf2
|
|
1059
|
+
.claude/skills/eval-harness/SKILL.md 03fc47842b35861231efdd1d15de291942915c372b8ffcc05a22e942d1233ced
|
|
1060
|
+
.claude/skills/eval-harness/SKILL.md 98f10c6cfc7fd041a358093f5c700b489d431879b90db778db7623a3c1c5404f
|
|
1061
|
+
.claude/skills/eval-harness/SKILL.md 12399b9de9e044273fd4dd6a8177bc4f17db008a33df83557ef56770b1466a56
|
|
1062
|
+
.claude/skills/eval-harness/agents/openai.yaml 6f2c19eb59062ca776286c2f6a6a7f1b552b4f927a2b48de888a7dbb2eeec6bd
|
|
1063
|
+
.claude/skills/explain-plainly/SKILL.md 7838e4f78b7d4d46d31a7c932f069fc66ec4bcd873e49fb57f37923be188fd0d
|
|
1064
|
+
.claude/skills/external-model-consult/SKILL.md b1d7db909a459708ed721f5a7eeeeebe48fb3d57448f763e7e0000df5426a241
|
|
1065
|
+
.claude/skills/external-model-consult/SKILL.md c33d6d2e02aa9631fcb4e91aae83b56834307b0290a984af55378d2f0011d7dd
|
|
1066
|
+
.claude/skills/external-model-consult/SKILL.md 24cafc7b50fde21eb874fc2178d3ebd7eca3b1c54e9278d60a088f9079b7b534
|
|
1067
|
+
.claude/skills/external-model-consult/SKILL.md 2d115e29ad53d778ac4d4f942ec2039b441ecc571d612d27cc725695641f4db1
|
|
1068
|
+
.claude/skills/external-model-consult/SKILL.md a4d429bcd4737fbb2a90de6b9beb9cdf0488fe385eb0f6fb395f0e76322dbb0e
|
|
1069
|
+
.claude/skills/external-model-consult/references/direct-calls.md 6bf094fe54bcb09285ba552371eabf1d743545eccdb118157a8aea987b7c8147
|
|
1070
|
+
.claude/skills/external-model-consult/references/direct-calls.md 966db9c1f80c367ffc81842b83326a67190cc97287e7d624c0c16ee65fd4b16e
|
|
1071
|
+
.claude/skills/external-model-consult/references/model-evidence.md 27dfc0eaac4bbf97dbe4430852e947d99a7bd895aeaa7f1d565915c2a2fdef1d
|
|
1072
|
+
.claude/skills/external-model-consult/references/prompt-templates.md 2277839d5eb9ecbf8535f51a1f1ca97d55816e47b6ea578f34e9637280b1b5ea
|
|
1073
|
+
.claude/skills/external-model-consult/scripts/codex-ask.sh 64835a9e11094bc24d9e8f9044a98a699ca45155d516dba926ffb8c145cbf1f6
|
|
1074
|
+
.claude/skills/external-model-consult/scripts/codex-ask.sh 75f24da435dff5ea7ed7636d8b121456d1e91806e9a114ea993862e173d84d72
|
|
1075
|
+
.claude/skills/external-model-consult/scripts/codex-ask.sh c644272c25f3d0d42ab63bc8c4acf81c1ae90ce1af5f7780977dd63f464fda7b
|
|
1076
|
+
.claude/skills/external-model-consult/scripts/gemini-ask.sh 6736c394de1d059908ebed770221b298f37d09e01aa3eb58991265c2d45915cc
|
|
1077
|
+
.claude/skills/external-model-consult/scripts/gemini-ask.sh a598276b4e2d9e4a54b704229822d8da49a6c54497c8f2471af5420b4c3017c3
|
|
1078
|
+
.claude/skills/external-model-consult/scripts/gemini-ask.sh 9c5eb72c61d140228dff796ff599f88982b76763abbf52aaa31486ddeb03e9e8
|
|
1079
|
+
.claude/skills/gap-analysis-e2e/SKILL.md ef28d245d354c07de60244778469fcc344385a584eddba33c67e9b096654ba4f
|
|
1080
|
+
.claude/skills/gap-analysis-e2e/SKILL.md 739e9a181eac99c749b585fc4f2b64a30dcd4783083422afde64ea85a9a2b062
|
|
1081
|
+
.claude/skills/gemini-consult/SKILL.md f096ad4e6a16e4e6d33ff7d817382e3f8c07311fd7c1f809ae91a951a9f58856
|
|
1082
|
+
.claude/skills/gemini-consult/SKILL.md 24c7f1a8855f5f44447015990991c47c80dc14fd9e373dd818084f8870ff8004
|
|
1083
|
+
.claude/skills/gemini-consult/SKILL.md 9ec900de7b699b73addd0e6259b4a2fc8bbf559d22662842424a1402cb581793
|
|
1084
|
+
.claude/skills/gemini-consult/SKILL.md 81cf4563f9fc790a64796a24e6f85f3b33bffc7e31989dbaebedcc2452984805
|
|
1085
|
+
.claude/skills/gemini-consult/scripts/gemini-ask.sh d9f4cc371e3e3b1919dd773d41b351484c9a3612487bee1ba314378a8486a39c
|
|
1086
|
+
.claude/skills/gemini-consult/scripts/gemini-ask.sh 87b065bec8c13b28dcc451235dcf9679d97af4f68ec678153e23ee14f7c94d0a
|
|
1087
|
+
.claude/skills/gemini-consult/scripts/gemini-ask.sh 6736c394de1d059908ebed770221b298f37d09e01aa3eb58991265c2d45915cc
|
|
1088
|
+
.claude/skills/gemini-delegate/SKILL.md e3d569add39fecf8c412d76c287e88054710f70b87ac38d88c20ad7b00b301fa
|
|
1089
|
+
.claude/skills/genspark-delegate/SKILL.md 3f495d55f1968730c9ce66009745530c16adee5110267e7b735f6a0333e2bcf2
|
|
1090
|
+
.claude/skills/gh-issue-workflow/ISSUE.template.md e004bcbf6199486d527feea43aa68be108bfc8fd3b13800bc543baa778291dc0
|
|
1091
|
+
.claude/skills/gh-issue-workflow/ISSUE.template.md c30fbe41d1d6ca15a82c031441c8b20a6db20cabd3d52c9c2c7ec70ca97d60fa
|
|
1092
|
+
.claude/skills/gh-issue-workflow/ISSUE.template.md 6c897058f7cfbc7b3eb5a3688f21a106fda39b7ded0f05570cff349214aca427
|
|
1093
|
+
.claude/skills/gh-issue-workflow/SKILL.md f2b906076945adce0cfd80dd9331420eea0bd1c1758b76e1f300c82811b06f50
|
|
1094
|
+
.claude/skills/gh-issue-workflow/SKILL.md 99736619cdb450870fb8b51e9ef3375fdd4c625b5d23e37c75078e40b1f1dd32
|
|
1095
|
+
.claude/skills/gh-issue-workflow/SKILL.md 00dc33d939b034dac6c653a07a64da5b362e350bd9133def2f11420c94353008
|
|
1096
|
+
.claude/skills/gh-issue-workflow/SKILL.md ea1012246121662e0604e296913b63e7ce5a02b902182c86102dabe5e13563fd
|
|
1097
|
+
.claude/skills/gh-issue-workflow/SKILL.md 0b1ce6a696c1388e928240ec787b449dd0b0a92749789fe28f8627fbb9aee880
|
|
1098
|
+
.claude/skills/gh-issue-workflow/SKILL.md 578c25a3687c7c6557c2bd115489f44a49d5668e2cb97e114a009d7066db7a72
|
|
1099
|
+
.claude/skills/gh-issue-workflow/SKILL.md 7128c3faddf72ce6285b3a0e7179da01d6a434659ccef6f9b51851b3f5f50d17
|
|
1100
|
+
.claude/skills/gh-issue-workflow/references/hierarchy.md 0e16e38d5919e5eed0aa044899895fb13c3846a333f3470d8001bda09ba959c4
|
|
1101
|
+
.claude/skills/gh-issue-workflow/references/operating-model.md c6feec997887d05d3385441258c464609e52c4bbebb7c0b7390a5d6016ad9a0a
|
|
1102
|
+
.claude/skills/gh-issue-workflow/references/readiness.md 08df321b014d96f8d5b5e0c7af7f36d09d719fb098bdaec7928af4a77c1866cb
|
|
1103
|
+
.claude/skills/harness-health-audit/SKILL.md 12932ba2e5b77a7efab0ae2d0fca334bf249503a583de5a3933105fba89c94ef
|
|
1104
|
+
.claude/skills/harness-health-audit/SKILL.md 6a843a002f9a7ca9c04816214509caccc1cc3f3661595939cc4096366847f09e
|
|
1105
|
+
.claude/skills/harness-health-audit/SKILL.md 16501e7db181780684612f4f38db80861e775cc1204f444169efdbc5d9165bb3
|
|
1106
|
+
.claude/skills/harness-health-audit/SKILL.md b481d7844303896a24a3a95269a035ee57690d8c15c5ad5e85f16227fa5f7f27
|
|
1107
|
+
.claude/skills/harness-health-audit/scripts/observation-digest.mjs cfedf96b819819142f2d69bdd6663bcbdd56301c429545b4f31cc2f358249cb8
|
|
1108
|
+
.claude/skills/harness-health-audit/scripts/observation-digest.mjs 7c9c42fed4c3ab1a0df6363386c34e03776a53f6b32aa1bef3c6899dcd77aa5f
|
|
1109
|
+
.claude/skills/humanize-korean/SKILL.md 7d0d77c25f5990f203480abc6a02772d534a40ebfff4ab4086cf5da3ed1b7afd
|
|
1110
|
+
.claude/skills/investor-materials/SKILL.md 0541ac8ede8d39c59a646834481d0de86312e598331b86dc7027ece0def3c193
|
|
1111
|
+
.claude/skills/investor-outreach/SKILL.md ab71ee37a1ff5f9b7f27908d33fc47f03e7897e6c87be3f8d7c0e4a8d73fefdd
|
|
1112
|
+
.claude/skills/market-research/SKILL.md 7ef3fa13d6272fd295eeb2aca9f6a2f09f6a8270cf33b0675fc5a0018cf6e406
|
|
1113
|
+
.claude/skills/market-research/agents/openai.yaml 42e1b1bf676506bc50027131cd8226b151f48a57551197308102dd01fd080943
|
|
1114
|
+
.claude/skills/model-orchestration/SKILL.md da6b448d0119e7dfd441f47c9afa267c227ac9301561ddf07c3fdc81bf494ff6
|
|
1115
|
+
.claude/skills/model-orchestration/SKILL.md d4ec28fa8e7bcf48607a17dc84a9fb873dd9f58f6ffef38ae5324f94477160a1
|
|
1116
|
+
.claude/skills/model-orchestration/SKILL.md 2282ac0ca6c06006d36616295dbbb78bb593b93e06712baf8be6b6466426c540
|
|
1117
|
+
.claude/skills/model-orchestration/SKILL.md 7a60184798f2c7ab28d81af37bf61d4785b0831836f0be1e933d279c1b552161
|
|
1118
|
+
.claude/skills/model-orchestration/SKILL.md 2210704bbb4ae972e74f1062512accd53882a405fb91adb0461ad9a2325774a6
|
|
1119
|
+
.claude/skills/model-orchestration/SKILL.md a4447594e45e598028c5f614cc46d1555c6cbf20e0edce1c9d8a30ca17798268
|
|
1120
|
+
.claude/skills/model-orchestration/SKILL.md d8d1982fbc76d572b2f6a3ffd07cba944d3e734987fc5bc66002de5f86accd3b
|
|
1121
|
+
.claude/skills/model-orchestration/SKILL.md a67b5948e8072a87669621feda866198ffadd7c76979fdc3a0b1d8cf2a4ac8bd
|
|
1122
|
+
.claude/skills/model-orchestration/SKILL.md 34add0d50a3ed2687b4ac092a4146928b841f5f6a8bbbfd09a42e2b59f4ef2cf
|
|
1123
|
+
.claude/skills/model-orchestration/SKILL.md 6320632e46180275ee36a9e0897fd616ceb1b8ce7ffdf0647c871b293ae5c846
|
|
1124
|
+
.claude/skills/model-orchestration/SKILL.md a22190744eccc76d1f2d8995a1d66395e4ee173935b2114a334eff95239c234b
|
|
1125
|
+
.claude/skills/model-orchestration/SKILL.md 19d64858ca267987eb9be129a588b7e76ed86b7f788accf019e3f2c2db493117
|
|
1126
|
+
.claude/skills/model-orchestration/SKILL.md 65f0e657979e6b6c0fdacdd5b2cc73f73bb0cdb866c7c8ae1f099c54747c46fc
|
|
1127
|
+
.claude/skills/model-orchestration/SKILL.md 78cb2ac0f153afc4deb3ccc88b40abc7bab1f2b9ab8138d2fd3998082f380178
|
|
1128
|
+
.claude/skills/multi-model-debate/SKILL.md b6e4e4855ca36bcc2a720d926be68008259e0604c8c9dcc8b00cdd65c2bc48ec
|
|
1129
|
+
.claude/skills/multi-model-debate/agents/openai.yaml 64eb836095ff28669ebfd41d133a63e29faec0542dfc90862e10ed7fd275071e
|
|
1130
|
+
.claude/skills/multi-model-debate/references/adapters.md 06d54103576b4de93b9856c26f773842cfbb81b9491fe95c55354bd324fe4c51
|
|
1131
|
+
.claude/skills/multi-model-debate/references/evaluation.md 34f14eeecf6912c8afe5eefa1431744351b7911525d0f6eb612120d31170b290
|
|
1132
|
+
.claude/skills/multi-model-debate/references/prompts.md 45b348552563a499e221edd6fd75fb1d8e77b389aa25a9cc56688547e68434dc
|
|
1133
|
+
.claude/skills/multi-model-debate/references/research.md d99201f4774c7b3648e5bb3953c2e2979af752c1ccd8fe5013c8b6bea155e949
|
|
1134
|
+
.claude/skills/multi-persona-review/SKILL.md 8fa6a0d476b50e1c6b14fc62c31b03c8ea983711d24cc21351589ebc8f1dcd57
|
|
1135
|
+
.claude/skills/multi-persona-review/SKILL.md f0ac01160ebf176617cbe9d606a2b258eef8741c05b4a972f813ac90dd6e9dba
|
|
1136
|
+
.claude/skills/multi-persona-review/SKILL.md 4f221fec547e838d4698c4e2eaf82d6ebabbc52004be8933131e84add66fb397
|
|
1137
|
+
.claude/skills/multi-persona-review/SKILL.md 5339755ba6c7d61b82a1e06f1dde8ef46f5ee263092a7cc5cc6d300ae9bc79b0
|
|
1138
|
+
.claude/skills/multi-persona-review/SKILL.md b23879e303b7d0c95d30a9369f20b1928f93c24114b891a29f8bb17816cfac20
|
|
1139
|
+
.claude/skills/multi-persona-review/SKILL.md 29b1022bf403005764c95670b6d29ea3695ca935261afbf248c452058b2e2d56
|
|
1140
|
+
.claude/skills/multi-persona-review/SKILL.md 17f9f1a0c224168fb4c773f87f8ad84a4d7db9082088e096262aa71e1916f0f6
|
|
1141
|
+
.claude/skills/multi-persona-review/SKILL.md 6da7f5ccfae30d3d7e4ee77f90a06d7de30a532b590482a01d779addd912864e
|
|
1142
|
+
.claude/skills/multi-persona-review/references/reviewer-design.md 327b70bdedff29868b6b3b88d2279db572a811eb19defe8ec0c724e3a007cb45
|
|
1143
|
+
.claude/skills/multi-persona-review/references/reviewer-design.md 4afc9d327f91139b4d272a54e1b1992766b7e0482b4479c76ca9b5284e28d7c8
|
|
1144
|
+
.claude/skills/multi-persona-review/references/worked-example.md 95b48adac8ae5a91cb60fb9d5c32c90365734225775f0f85f26fb72404345943
|
|
1145
|
+
.claude/skills/natural-korean/SKILL.md 0057cef32a4accff3efa155a4916ac65fc283ee766abb2951227da91fa8bdee0
|
|
1146
|
+
.claude/skills/nextjs-turbopack/SKILL.md f65da15aabeb9dca7ae08525739e72ab16e79a78ff4004f7cab6ad2de1c2a79b
|
|
1147
|
+
.claude/skills/north-star/NORTH_STAR.template.md f778da89c561cf92b987bc1d46e5eb8c979f2422882714b0a0602ccce62a7b5d
|
|
1148
|
+
.claude/skills/north-star/NORTH_STAR.template.md 401ac922beb41b5b3c6d19313d5a46184cc90808aa330e0e288108355b5f8aff
|
|
1149
|
+
.claude/skills/north-star/NORTH_STAR.template.md 23a071af1893e3be7860111d448d02a55f965519811bdadafdba4231607d66c3
|
|
1150
|
+
.claude/skills/north-star/NORTH_STAR.template.md 741efd7d4c477f95ecd1fca85656d4582a694b3753ece77378ddab8ba0f0b69e
|
|
1151
|
+
.claude/skills/north-star/SKILL.md f73b7ce6a73bb3666ff3c18557ba37248a844107d54ffbaf5bb3d562fc2e7f61
|
|
1152
|
+
.claude/skills/north-star/SKILL.md e335733ad2c6dab82d104f868c5ce3d3de99ee1f139330eba9ff497529bd9485
|
|
1153
|
+
.claude/skills/north-star/SKILL.md 5b1f8176bb264e5a426594704e640eb69605d6482d6ba93f53329e9fe08dadcb
|
|
1154
|
+
.claude/skills/north-star/SKILL.md e37ed854c29f26f64a96ccd4847e71723f5bab9a56d3c8f53a4f9815120085fe
|
|
1155
|
+
.claude/skills/north-star/SKILL.md b11245dfa084bcd8b1fa4f7eb186e7a6ed97b30905a1507992c35448af45cc62
|
|
1156
|
+
.claude/skills/north-star/SKILL.md fa4427fb57243aed96d639362d97c69202170dfa949bfb0818f4600b1cd8432f
|
|
1157
|
+
.claude/skills/north-star/SKILL.md 0616424076bb18c4388d9e48ac4e4bacb51106b0b8bdcf6be223e413e0c43bf9
|
|
1158
|
+
.claude/skills/north-star/references/roadmap-method.md 78b6d7e05e014c5c7ecd5680767ed2469c6a147faf053b09f448f63cebda9da7
|
|
1159
|
+
.claude/skills/north-star/references/roadmap-method.md fd58a20159eb0b14b69781ea2536be1fdebd78c9eb83658c2b76de78efd21bab
|
|
1160
|
+
.claude/skills/north-star/references/roadmap-method.md 32e812eac7356e15704d0eff162f3fe3d93f1de880c7107017c1d802463190b6
|
|
1161
|
+
.claude/skills/northstar-roadmap/SKILL.md 489e7a70f81d80c296dd9160debe7ef69381506f9ac00874cfb48e2b61e58736
|
|
1162
|
+
.claude/skills/northstar-roadmap/SKILL.md 9a632a49e6bbf877fee61d448046444d57127b75b4f76f9b8ddf8946c8b7990b
|
|
1163
|
+
.claude/skills/objective-brief/SKILL.md 4df0bbd72dd7ea698d7d9d3b10476c4c4ff3e6bc3d9a1d29531e083c9e9bf59a
|
|
1164
|
+
.claude/skills/objective-brief/SKILL.md 51fa706442849b5f74e71c23fab8952526dd3a60ab1d78a3fe53d2631f24e47d
|
|
1165
|
+
.claude/skills/objective-brief/SKILL.md 531c8f0f09492e4a1643a5de38dbc293be9981a5c81ebc7f783620d5380a5806
|
|
1166
|
+
.claude/skills/python-patterns/SKILL.md df0c0abbbd0e6a01811d1b1d10d8fa7a8a19ce73afdc9432d24843f62649cdd2
|
|
1167
|
+
.claude/skills/python-testing/SKILL.md b304a8c503af32644f97a889c5545ee4f90e91980462ad4ce33fee3dea6f414f
|
|
1168
|
+
.claude/skills/recurrence-prevention/SKILL.md ab537b5f35be053ffa930f99c5b3d972b80fd621d18eda8390506d01503f6d78
|
|
1169
|
+
.claude/skills/recurrence-prevention/SKILL.md 905324644b719f2cfc2744be0bb21922c9e4e6534a83c6b8cad980d6327b92be
|
|
1170
|
+
.claude/skills/recurrence-prevention/SKILL.md 40b8e5a14136cecf12a63cc2f709de2d80290e352aee88aa9a482200a3fd7295
|
|
1171
|
+
.claude/skills/recurrence-prevention/SKILL.md 8a26b9d530305497fe11b39e31eb7806d835953c2585fc15fcf51488d7fe6279
|
|
1172
|
+
.claude/skills/recurrence-prevention/SKILL.md 62fe94e2cd34d9c3c40871766619d5c37c957e89247c5d281e62c85de51326de
|
|
1173
|
+
.claude/skills/recurrence-prevention/SKILL.md a626f5760ffb7446695a578104baef9ba9259b3b41115b00d699c43d260c0295
|
|
1174
|
+
.claude/skills/recurrence-prevention/SKILL.md 9e44542d54006e02ae1d906346a90c0ad0e26c1797496e791c83f7bb0e867cc6
|
|
1175
|
+
.claude/skills/recurrence-prevention/SKILL.md c7c163aceb457535adb3c3052fe41355048716db2cbb0b4cc768ca6fd4533f26
|
|
1176
|
+
.claude/skills/recurrence-prevention/SKILL.md 46614922e61e79235493c80664da2f9e7d95d034c58c9a646b948a7c2a1f70b2
|
|
1177
|
+
.claude/skills/recurrence-prevention/references/failure-analysis.md 1dd840db9a2bc662ec9688833988d93e80d0be245e7edd727c2d065a9d7d9eca
|
|
1178
|
+
.claude/skills/recurrence-prevention/references/failure-analysis.md 5fc80d28b3f52e92843e9ef431a9dab74d8b43cb3cfd7ed5d2aa359ad00586bc
|
|
1179
|
+
.claude/skills/self-hosted-github-runner/SKILL.md 4e5b86b9c7c8527599cfd8be61f4ed3ab67d439bb791f4068d85e52c9327e5df
|
|
1180
|
+
.claude/skills/self-hosted-github-runner/SKILL.md a1394fde762c88fddc88db1502b15aabe88bdfc1c565e77bd3cdbb0512352d10
|
|
1181
|
+
.claude/skills/spec-scaling/SKILL.md fd28afb5558e2ba4168b0b16bc19b1c4d2fb732741649010a1601f751f9eafc5
|
|
1182
|
+
.claude/skills/spec-scaling/SKILL.md 93fe3ed443754bd368a45e71145434c1fd7efd349e25b0179bbb63774ac4ca0e
|
|
1183
|
+
.claude/skills/strategic-compact/SKILL.md c8e861a39fb84968aefa82783c1b25e61d1b625c29c0f5b2bb301f4652c93e9d
|
|
1184
|
+
.claude/skills/strategic-compact/SKILL.md 6bfc63c380eb89886335ad033f759a4ff3f1b1ae2c5a143598bb628e38c6e769
|
|
1185
|
+
.claude/skills/strategic-compact/suggest-compact.sh 62af1630b000713842e363447675ad5a94f72cddf47241df68fc9883de686689
|
|
1186
|
+
.claude/skills/task-brief/SKILL.md 69125822c0c7da8daa6e67117f0845e3388284b0d4b7cc2b69f440c9b865b454
|
|
1187
|
+
.claude/skills/task-brief/SKILL.md 0859fc0b6cf760edb83b4c41cb8156cc90b7c62f1d5b5dd364acd4c5f7935cc2
|
|
1188
|
+
.claude/skills/ui-visual-review/SKILL.md 4016297b69844f05a51c4669e62083b8d27a734f0daa24b3a03039979d6a28c7
|
|
1189
|
+
.claude/skills/ui-visual-review/SKILL.md 4c92c01e4d437150fe115406044d2ea9b8c942c2026f9e0d8d446667c4db7912
|
|
1190
|
+
.claude/skills/ui-visual-review/SKILL.md e9689dadb419979e2b62a3f1c84069f90b91ae95dd0a061dc759b3a60598aa32
|
|
1191
|
+
.claude/skills/ui-visual-review/SKILL.md 39371f46b46b7d8f51da0b9a28ca710156de634b6e066217e9618b1ecbe3f5ee
|
|
1192
|
+
.claude/skills/ui-visual-review/SKILL.md 2e23c9ba4e40a13db152ee750a33cadb6e32169daf51417c9a0a97b0ed021e45
|
|
1193
|
+
.claude/skills/ui-visual-review/SKILL.md 8d5c23460b4ba78c9b8077d9e6de59af5a38ea3035ca65f5cf645140ba523741
|
|
1194
|
+
.claude/skills/ultracode-service-audit/SKILL.md bdb3d151ca74e6129e547339b17192ba415701b46d889e0a1bf9f7fd0195663c
|
|
1195
|
+
.claude/skills/ultracode-service-audit/SKILL.md c7ca76cbda2f8d6b5750b68f524c92927ea375fb47a910ed02332e3a6fa1bca0
|
|
1196
|
+
.claude/skills/user-centered-explanation/SKILL.md eab47a91badce5d6314f63889950c69c43fa5ea4660d544828794ada3684e0b8
|
|
1197
|
+
.claude/skills/verification-loop/SKILL.md 01a9ae310ad4426bb05660dda6cefdeaac9513417585c09c8bb1b94738649a78
|
|
1198
|
+
.claude/skills/verification-loop/SKILL.md 41f481c1146b0b29ecbcf5c633090a6db3749ca4a814499d72b5b8941db694f5
|
|
1199
|
+
.claude/skills/verification-loop/SKILL.md 566fc81da559464d70af80a125dac60991ba5e26464643886c1dee04dd78db95
|
|
1200
|
+
.claude/skills/verification-loop/SKILL.md 1744f867f7868b83b480341c2e8d08bff3848c2408255871d3aba0c2f7eff2f2
|
|
1201
|
+
.claude/skills/verification-loop/agents/openai.yaml 1907fd04fea5c83d15faf14acfc978de90076d4351341cf9259639aa0c3b7bd3
|
|
1202
|
+
.claude/skills/verification-loop/references/tracks.md de11792d447c2e8ea67e8367c6655bd94646b1ba3f29184c4521cae01facc6ec
|
|
1203
|
+
`;
|
|
1204
|
+
var LEGACY_HARNESS_FILES = (() => {
|
|
1205
|
+
const m = /* @__PURE__ */ new Map();
|
|
1206
|
+
for (const [path = "", sha256 = ""] of rows(FILES)) {
|
|
1207
|
+
const s = m.get(path) ?? /* @__PURE__ */ new Set();
|
|
1208
|
+
s.add(sha256);
|
|
1209
|
+
m.set(path, s);
|
|
1210
|
+
}
|
|
1211
|
+
return m;
|
|
1212
|
+
})();
|
|
1213
|
+
function isLegacyHarnessFile(path, sha256) {
|
|
1214
|
+
const key = path.startsWith(".agents/skills/") ? `.claude/skills/${path.slice(".agents/skills/".length)}` : path;
|
|
1215
|
+
return LEGACY_HARNESS_FILES.get(key)?.has(sha256) === true;
|
|
1216
|
+
}
|
|
1217
|
+
var LEGACY_AGENTS_MD_SECTION_KEYS = keySet(`
|
|
1218
|
+
241678cd4951efaf8ee7bb0059e739c397af6b90b75fea636361501b7ae1cbe7 ## Workflow Gates (26.70.0)
|
|
1219
|
+
1e19e112dc2c9c85f31d7b8c1b65b5e35e8563db7f31115ba03af8c6ef1d5ea6 ## Command Reference (Antigravity workflows) (26.70.0)
|
|
1220
|
+
fe66384910daab3a0275c7c98d9a944f5f771d58ec2a9addcaf5f16a8d001ef9 ## Protected Files (DO NOT EDIT) (26.70.0)
|
|
1221
|
+
f7fbcaa082ffb260b11f48813a8f97f243663082aadb37e2137d2a99a143f65f ## Scopes (26.70.0)
|
|
1222
|
+
62225c82dd65fc0c01dba1fd6dbe8e9accb8d46d0f580f4d2a281dead3346997 ## Workflow Gates (26.70.0)
|
|
1223
|
+
0d509a214b74e5b3966722390279fe84fa20c8337fa7c9853c31fef0b42bf85f ## Session Start (26.70.0)
|
|
1224
|
+
fd29a37cc8231393739123a79728b31c0c4acde371ce502709550ed43837a2d4 ## Protected Files (DO NOT EDIT) (26.70.0)
|
|
1225
|
+
9c4a901cbad93ba04a5d511952e2e47213130c92ae2122e5f5649a17328d8915 ## Git Policy (26.70.0)
|
|
1226
|
+
c24a96fd321a9286debd618c9d95684c344c061d6a8e0558dce1595aa84e3a9f ## Command Reference (Codex slash) (26.70.0)
|
|
1227
|
+
23c25f2516a46dec187877d5d85f2e92257752193e287978650b3b112df083dd ## Agents (subagent, multi_agent stable) (26.70.0)
|
|
1228
|
+
dc230c795b307261ea4ee23126e6a209cc73ed474c97857d59e03a134232c4ec ## Hooks \uD604\uD669 (Codex 0.124.0 \uC2E4\uCE21 \uC81C\uC57D) (26.70.0)
|
|
1229
|
+
462ce33464e58a8ebd95ea5ed0f4cce167153fb2805ea6ba609734174a9027a2 ## Experience Accumulation (26.70.0)
|
|
1230
|
+
dc5629ad55f9800e4898a698650c8dbef5578505e7d5891745f0065f01d650a3 ## Context Management (26.70.0)
|
|
1231
|
+
c7d793aa3bf374b8bd390baf25bfc2c23c2d050377f673e72e53fe14f821c1f4 ## Workflow Gates (26.70.0)
|
|
1232
|
+
cf4cf430b633cb68b4128b03797999ed325f76ed92132fb8adcb60cccbc4e0c2 ## Session Start (26.70.0)
|
|
1233
|
+
ef2c745821688a463d4435affaaa6baf404feaec69f081c68a794d847f72a9e7 ## Protected Files (DO NOT EDIT) (26.70.0)
|
|
1234
|
+
f328397dafd8eaff1eeff91dcda315db3da289e646eca49a6b977725867cea3d ## Command Reference (OpenCode slash) (26.70.0)
|
|
1235
|
+
e1dd38e41e5df06efea65b349376a1ea668ce74a408efaf5c1ce91f08063a666 ## Agents (subagent) (26.70.0)
|
|
1236
|
+
1ca6e8025be0d099df42fce9248673722fe327be2a77a0d9971bacc18a99a10e ## Hooks (Plugin lifecycle) (26.70.0)
|
|
1237
|
+
ad834e2800b86a486d50efb9526657898a03919ee1b3fbf0cb0aaa89c9a6c095 ## Experience Accumulation (26.70.0)
|
|
1238
|
+
2cade5a88d6241fa7a50289fe0336b64cccd08d2c81b65e2df72acbdbc436a62 ## Context Management (26.70.0)
|
|
1239
|
+
b2532f7ae8302ee8aa5e0316f7bd9755abe06abeaa9639f7a9a062fc7d89b47f ## Scopes (26.89.0)
|
|
1240
|
+
c144f72dc32d524ae00b6026322439a5a3f2083d4e1781b927f374fe2b20d7c8 ## Session Start (26.89.0)
|
|
1241
|
+
0c719706bef388d3ac81a62431659bf817b0d4384846a0068d5768c8b3965e36 ## Protected Files (DO NOT EDIT) (26.89.0)
|
|
1242
|
+
6502c5abcf4cb9148c6dc5227401f7046b7dc8ab97ff7c292824de568b603942 ## Experience Accumulation (26.89.0)
|
|
1243
|
+
37106505641d9de7ae9e3ac5cc86efc3221abe5c969323325acc11e9b7d7cd04 ## Experience Accumulation (26.115.0)
|
|
1244
|
+
25baf8cc482b473d7f61e13ff95232484f95cc22063bb2ce9587f43ad242d5dc ## Scopes (26.141.0)
|
|
1245
|
+
d48603cb329fce58fd7ca9eb3b01dde3b223bdbfe79ee583627fbc15e22ba703 ## Session Start (26.141.0)
|
|
1246
|
+
29cb109e9a2cb4e3037a470d25d7dce4928d0e690c2c7c478d452f2133b65cd5 ## Git Policy (26.141.0)
|
|
1247
|
+
d1affcbe314d8ccd39ca956d467fbd43bcc859b4ffc23bf1d1f8f2f0a3e10f4e ## Context Management (26.141.0)
|
|
1248
|
+
9203c6d359a7ffc5a968be0645e1b827d6b4940312c27edb1c5fad6a68c9ca7e ## Session Start (26.141.0)
|
|
1249
|
+
39fdaaed39e0a39c537ebc3dcf5d349fb867740b126822eaa9333833d0de68eb ## Context Management (26.141.0)
|
|
1250
|
+
6f4bae4fb31bc54074d1fed021f4fd6dc3939844ac701eac8427904404b6daf3 ## Context Management (26.147.0)
|
|
1251
|
+
0569e0fb18d55a474fc8239dd60bb5684d22245c1ffa6f198cf6af468b5a3794 ## Protected Files (26.151.0)
|
|
1252
|
+
624b8878a9a17a5d4046b180297c53b27270ea75ed7d892d527939a7580adb19 ## Session Start (26.151.0)
|
|
1253
|
+
0f6658376e8bba3c31ffca010f24e9acee9f32953c00a41183dca9eaaa4f7913 ## Protected Files (26.151.0)
|
|
1254
|
+
55412b2ae275e9660f09c7cc286d3e92236e4ae61626cbf68727ae222edcb0e0 ## Protected Files (26.151.0)
|
|
1255
|
+
`);
|
|
1256
|
+
var LEGACY_AGENTS_MD_NAMED_KEYS = keySet(`
|
|
1257
|
+
92dce1a73d484490c943ec3418f10b2370079ae42aa8d93159596f45d12e699a ## Project Rules (26.70.0)
|
|
1258
|
+
f59bdc7177a12aa86f235ada16b2407c40bd55ae9de8e96a851b77571bdde989 ## Command Reference (Antigravity workflows) (26.70.0)
|
|
1259
|
+
c7f9fa755bd66d80c2df496c6c759e8accd736cd8fef64460feb7ae9cd4c8006 ## Context Management (26.70.0)
|
|
1260
|
+
dc030a35a6e638aba5447b4d4e79ae028fafd1419fbae872b902661fa7787a58 ## Command Reference (Codex slash) (26.70.0)
|
|
1261
|
+
df73823c02e6eee000388444964acfec233ffeec0e20fdc5d31eb018d2ca93c1 ## Context Management (26.77.0)
|
|
1262
|
+
6c900db77cb104f400091b44a7414e96427003860306a3007651b7a8b91a547c ## Project Rules (26.140.0)
|
|
1263
|
+
d9e3680462e64506ba4ef2df4f12e666855c3f458c1feeeeb623d62de2a5fa17 ## Project Rules (26.145.0)
|
|
1264
|
+
2da8ca3600045d85a9607ce270f9bc2d77b5ee54fe80cd0765caf7658f51127c ## Harness Rules (26.147.0)
|
|
1265
|
+
bbe5e1d9d368b15221269319b53dde4f87424904b80cd5af46a28de3d8ac923d ## Harness Rules (26.147.0)
|
|
1266
|
+
41eae7d6a8bb327e71cea2dbaa331d808f879b5ff4074c0bbdbb90bcfe066d9f ## Change Boundaries (rule 26.147.0)
|
|
1267
|
+
bef15b624ea34d08dc5833ceacd710f3c687385050958e5cd103378cf2fcf457 ## Change Boundaries (rule 26.147.0)
|
|
1268
|
+
9648c5a118c77a23a1a04ddcacd7708be162d65587769d47f51d2405b74c2f72 ## Shell Safety (rule 26.147.0)
|
|
1269
|
+
c2dee88e05c98e1482c99c1c01f59cafc6c6816fda1269d68179707f4ede0b8f ## Shell Safety (rule 26.147.0)
|
|
1270
|
+
a6c3b31f60c80906e8bdb7a5ba699a4c1062b2e2f3e94f9f56b5064f74a722ef ## Documentation Boundaries (rule 26.147.0)
|
|
1271
|
+
b8fbe3bb2d5d790015ddbcff85c68922a122d91705e1cc946a14b30480bfb22b ## Documentation Boundaries (rule 26.147.0)
|
|
1272
|
+
0a0b44e4c8d10aca52f63a4dba40d9166ea067eb1599886f850dc37ec2bba2f2 ## Git Safety (rule 26.147.0)
|
|
1273
|
+
05efdb03d3e9d9fbcfd652ddf778d25bb1ab5ce237dd33f17b0be82cad08db5b ## Session Cleanup (rule 26.147.0)
|
|
1274
|
+
10bdfa993f15639a319e852cf59f7b279b7397d26a94c54e6ca6a94416cc6834 ## Enforcement (rule 26.147.0)
|
|
1275
|
+
b72afd685f3c63e481dc856890c8a9d89c4e36ca3163ab172661e9fd5c3658a5 ## Enforcement (rule 26.147.0)
|
|
1276
|
+
126a9a57aa42007c9c0bd3cb7f0ce75f2ad6a7497b464e7f6c7f45f3ae5f40d2 ## Delivery (rule 26.147.0)
|
|
1277
|
+
edfa8459a9863e355a080c759419f6f5ffb0ebd5fc418914fd38d79622e73131 ## Delivery (rule 26.147.0)
|
|
1278
|
+
55295cda2a572e0aab061449248123d9d43543b3045b1b156b95fe2fb6aae509 ## Testing (rule 26.147.0)
|
|
1279
|
+
6364a5d8727d33db914c7d7a1ac4108cff9ed1dbefffb212bd84c1fcd7584284 ## Testing (rule 26.147.0)
|
|
1280
|
+
8d407c73c2de630d77d605447f605a6a2511fc4598d500ac7a1ff1374e2e457d ## Delivery (rule 26.148.0)
|
|
1281
|
+
2c3f8e7c8408f103006e4ef8029dce4da1995bca01bd1e6baf7ca3f4e46e58fa ## Delivery (rule 26.148.0)
|
|
1282
|
+
ae930fa7c8fa6f942d20715a51de43f33461aa5589f469f13a31ab90da1904e7 ## Delivery (rule 26.149.0)
|
|
1283
|
+
5b97fa550beb24e86c04af7fba2c97d8ff51702fd25abf223d97350db2a19ff1 ## Delivery (rule 26.149.0)
|
|
1284
|
+
e9b5814787b1e1cc066c217da0e344604477edfc0eb17304a5aeca73b0846637 ## Testing (rule 26.149.0)
|
|
1285
|
+
bafced984a2acf13f6fc7a3ca7c79edb99b5cecd4b21e351bd093f260d32fb02 ## Testing (rule 26.149.0)
|
|
1286
|
+
4972faf000e3433c0c07f7bb36e6b0463453be308dea31cfc177d692e23e3700 ## Project Rules (26.151.0)
|
|
1287
|
+
381a1d00394f803118575ecde42946585466c2da2ec36239fd6208a3c1b6bab8 ## Change Boundaries (rule 26.151.0)
|
|
1288
|
+
1a9dda0c66c7d82bdeb29c169f749a44c03b9bc112b3a1146898826b7d77b04e ## Change Boundaries (rule 26.151.0)
|
|
1289
|
+
e0d9ecb6916b563cfd0eaaf3f977106826136c4aaef518e705508c60f17b3cac ## Shell Safety (rule 26.151.0)
|
|
1290
|
+
053642f8951a2da28bca7d8d985a01c8fc2a6a91223a8cdfcd5e7ba5ef78af62 ## Shell Safety (rule 26.151.0)
|
|
1291
|
+
6543ff93b6c1f27f6d76f2a2a7599fd7ed0d1004f5419d5082321d1f4729bd1e ## Documentation Boundaries (rule 26.151.0)
|
|
1292
|
+
1741bf4e931d799c850ae45944ac2a9985800240d011a670ddb9400013b14856 ## Documentation Boundaries (rule 26.151.0)
|
|
1293
|
+
e527b3630786a074e321e1375b44f0870df3f7d4f124d5fdca9bbbd7e66f9315 ## Session Cleanup (rule 26.151.0)
|
|
1294
|
+
8ec2a06cfe3fa51e8187b218c290cf9ddc7680eac85427e2f6cf2a4a1a03ed4c ## Delivery (rule 26.151.0)
|
|
1295
|
+
d7fad0202a32aedb45717177ef9d3647109a0e77ee13f37b4c4a42f892182d4c ## Delivery (rule 26.151.0)
|
|
1296
|
+
2332b78bb1eb206ba1b08e28b3114d4919fb1384a9a5378f55dead61fdc3105a ## Testing (rule 26.151.0)
|
|
1297
|
+
d172feb48f54338d5d81e8b390debe3537538f0d2214f51e590272547e113cd2 ## Testing (rule 26.151.0)
|
|
1298
|
+
99bdd67b5ae37c10588f4ff852525ebe2ab59368723f56bd317818a89161c59a ## Change Boundaries (rule 26.152.0)
|
|
1299
|
+
a07c989310055284328b4ca441e201740fc8158a38572e56ec9968dac44ced13 ## Change Boundaries (rule 26.152.0)
|
|
1300
|
+
e4d2c89e6c2189748bef2dccf8eb506b7f8cf264d5bf8626fbe4446c330e0b63 ## Shell Safety (rule 26.152.0)
|
|
1301
|
+
028c8514fa466e7f053088e37968ef07ce1bcb08d4c224e76ec807d0f01e4449 ## Shell Safety (rule 26.152.0)
|
|
1302
|
+
9f0ac9e1c32c486e4f318061e3be3c853217d03b3f837b6c6e425f016c8707e9 ## Documentation Boundaries (rule 26.152.0)
|
|
1303
|
+
992ca24bd1f15314fb53943af2856af73f0d31ad8c6cf98b25b840ebd017b86a ## Documentation Boundaries (rule 26.152.0)
|
|
1304
|
+
49ec458da7c57727c16ec8ffa01cb2e2631eb769f6041b3bc07d912ec1a2994b ## Project Rules (26.153.0)
|
|
1305
|
+
155abf346fea6c63a081d4db1a1e44d537c4a94a479a2affc96345b18928fde3 ## Testing (rule 26.157.0)
|
|
1306
|
+
675da728d15da072c17fe5e9ba3ca8b21811e99a09f390fed4a53f19dd12c555 ## Testing (rule 26.157.0)
|
|
1307
|
+
`);
|
|
1308
|
+
var LEGACY_AGENTS_MD_PREAMBLE_KEYS = keySet(`
|
|
1309
|
+
720645dd313be16e6204290bfe0451fb237f77b8a7498a8a8af77dfc44ac0828 > **Generated from**: '.claude/CLAUDE.md' via TS CLI 'src/antigravity/transform.ts' (26.70.0)
|
|
1310
|
+
f95170e7780965de8562db0b5c7846d8e75ac7902a4fab695373c691333c7ff4 > **Generated from**: '.claude/CLAUDE.md' via 'scripts/claude-to-codex.sh' (Phase C) (26.70.0)
|
|
1311
|
+
fe621e2687dd489f3e9fb6ca1b97d480a83af435d99117315c24534d9c4bc169 > **Generated from**: '.claude/CLAUDE.md' via TS CLI 'src/opencode/transform.ts' (Phase C) (26.70.0)
|
|
1312
|
+
0d05490eb1360e2601d7e63b79c901a10da1dcfd6c9437151e4fb1ce00416bfc > **Generated from**: 'templates/CLAUDE.md' (4-CLI \uB2E8\uC77C \uC6D0\uBCF8) via TS CLI 'src/antigravity/transform.ts' (26.141.0)
|
|
1313
|
+
1979722e483fba4441ffd4818134b3942cc97f21e39689316d6143e4732c98a7 > **Generated from**: 'templates/CLAUDE.md' (4-CLI \uB2E8\uC77C \uC6D0\uBCF8) via 'scripts/claude-to-codex.sh' (Phase C) (26.141.0)
|
|
1314
|
+
230413c8211b1a9c3b204e315ff63f6ac3a7d7e5d01c8dd3d4ed294bf3c49f5c > **Generated from**: 'templates/CLAUDE.md' (4-CLI \uB2E8\uC77C \uC6D0\uBCF8) via TS CLI 'src/opencode/transform.ts' (Phase C) (26.141.0)
|
|
1315
|
+
`);
|
|
1316
|
+
var RETIRED_ANCHOR_SECTION_KEYS = keySet(`
|
|
1317
|
+
522bac15bc17949697e291b837c0d9624f5e0c7666400a3baf94cdef7cfab8b5 ## Rule 1 \u2014 Think Before Coding (26.70.0)
|
|
1318
|
+
ea10b7cd9b84a71949a071fae15256f490b3fe407159d7bddcf3f882310fa835 ## Rule 2 \u2014 Simplicity First (26.70.0)
|
|
1319
|
+
c486465d9554f2de1711cd056437f6a95a5d3243264b82d29a6957f24b5a6de3 ## Rule 3 \u2014 Surgical Changes (26.70.0)
|
|
1320
|
+
3d080574cc7ae81eda75c4aa019445b38b6f69c5f9eeeda9097e10b6041e7e94 ## Rule 4 \u2014 Goal-Driven Execution (26.70.0)
|
|
1321
|
+
11e43547f6b1613a5dabb3edaf5131d696a3fd375b3c22558f03555a0f5cf2ef ## Rule 5 \u2014 Use the model only for judgment calls (26.70.0)
|
|
1322
|
+
60d91718de6ae16ec86b50e7c9a939a6ca5fc0721422b592700cc9972f55aca2 ## Rule 6 \u2014 Token budgets are not advisory (26.70.0)
|
|
1323
|
+
9d482c7307cbcb02acc6fb35cd57b24baa9fce04528e2bd21e1e877603f8b85b ## Rule 7 \u2014 Surface conflicts, don't average them (26.70.0)
|
|
1324
|
+
abca09f13833ce18bd0ffc0793d59780c35447ca79c2a512afcbc9d7a7116ed8 ## Rule 8 \u2014 Read before you write (26.70.0)
|
|
1325
|
+
5b4eae6c3dc2d92cfb1772889650882a4a2115f08a36602da9a1d96697059b91 ## Rule 9 \u2014 Tests verify intent, not just behavior (26.70.0)
|
|
1326
|
+
632670b8897dc373d4a12f611c2436d9a8e86d8cdab917eecabc4bf2a56f8030 ## Rule 10 \u2014 Checkpoint after every significant step (26.70.0)
|
|
1327
|
+
252e99f25b05a47e5ce884ac9f1e1d34156116b9a76331e2510b1354a6c98cd4 ## Rule 11 \u2014 Match the codebase's conventions, even if you disagree (26.70.0)
|
|
1328
|
+
c28a12b589b6576379793c51fd01dbfaf91d391ac773f84ae0477ddb60a1e3e8 ## Rule 12 \u2014 Fail loud (26.70.0)
|
|
1329
|
+
72feaf96f998989351f8083edb891c7b0c3bccca65dbea2732fb2864b8f98bd4 ## \uC758\uC0AC\uACB0\uC815 \uBC0F \uCEE8\uD38C \uC694\uCCAD \uC2DC (26.70.0)
|
|
1330
|
+
95c932ecb4f4fdcdd8d483f9d02166b906f6eb045ef33ee474a16913d0c3e6cd ## Phase/\uC791\uC5C5 \uC644\uB8CC \uC2DC Self-Audit \uC2E4\uD589: (26.70.0)
|
|
1331
|
+
c7f9fa755bd66d80c2df496c6c759e8accd736cd8fef64460feb7ae9cd4c8006 ## Context Management (26.70.0)
|
|
1332
|
+
6ec0b415a8f86c9940bccd3e6db895ea4a110185e76fef223a348f9553fd897c ## Rule 12 \u2014 Fail loud (26.77.0)
|
|
1333
|
+
a78f0ffa6b51c9b45c964ecb92db951534336f7e558a3d39d11f015ee6c3466c ## Anti-Patterns (Forbidden) (26.77.0)
|
|
1334
|
+
50d00a511e87571d7ff85f6584b87b9f5c2eef06122d8ac5fdccf3f047643f12 ## When Requesting Decisions or Confirmation (26.77.0)
|
|
1335
|
+
574519e07f48bcc04f0e3d505c0f9c157ddd426b5eda2baa99656cd4712dad2b ## Run Self-Audit on Phase/Task Completion (26.77.0)
|
|
1336
|
+
df73823c02e6eee000388444964acfec233ffeec0e20fdc5d31eb018d2ca93c1 ## Context Management (26.77.0)
|
|
1337
|
+
8f49f0a592575a65eadd3e33950c96616223aa8bb116707103affeef71db28c6 ## Delegate the Building, Keep the Deciding (26.139.0)
|
|
1338
|
+
6115eccc3b2702f436a9db7d6af9803fa7b1fbf7b9ff1110ea658fadd67ec5ea ## 1. Think before coding (26.140.0)
|
|
1339
|
+
15b120395ec8e757ecbe3e65775371a9120953617fb37eb062e0c176b52f045a ## 2. Prefer the simplest sufficient solution (26.140.0)
|
|
1340
|
+
cc466b4781444ca54aedebd20ba3aa531c3aa84cc438953df84b133bd32a0e1e ## 3. Make surgical changes and preserve existing work (26.140.0)
|
|
1341
|
+
f6d1f6f02cb3c19e61becf329f20335c54e684bccb06b33e4b7f66eb49f9c6b6 ## 4. Define success before editing (26.140.0)
|
|
1342
|
+
372bf30b282b861c6a89e355c94ffd239bb0202e2ef928f8af99d640579710f0 ## 5. Report evidence, not confidence (26.140.0)
|
|
1343
|
+
66ca0e3aae98d24c65afbc418645df29d8c570be81918c42192eb1beecd21f23 ## 6. Do not cross high-impact boundaries alone (26.140.0)
|
|
1344
|
+
9c6c27eb57a9790273fa3fdf0df3628d927b025f870f09933692d1b522d73a25 ## Decisions and explanations (26.140.0)
|
|
1345
|
+
922d100c2dc6ef8a53989a920c3554afa7efd148255bc144412403c0289439e6 ## Decisions and explanations (26.141.0)
|
|
1346
|
+
330a67775a28557431aebf36a44018fc5194a4b929bf2cf95184b1f0828a6360 ## 1. Understand First (26.145.0)
|
|
1347
|
+
3b2f0147dc7bd0f01fd12485790199ef4ee96a6b723e244ffbf3dc96933a1ab8 ## 2. Define Success and Keep It Simple (26.145.0)
|
|
1348
|
+
8802fb25c05879c98dbf8407001d239c410d25b4fa2521b11d9d7cc108f73b29 ## 3. Preserve Sound Boundaries (26.145.0)
|
|
1349
|
+
1d0d9bf05d8870dd0dc62e388ceffc98923f1dd2074ef8038f80a50c9b5b9a81 ## 4. Make Surgical Changes (26.145.0)
|
|
1350
|
+
05e08e2318061141464ae714d6770d35527576affa787740d9c6d9345d3462dd ## 5. Verify and Review (26.145.0)
|
|
1351
|
+
7b39f1f92a72517d6ae52599becfef29f675e48185a3483dc993d7accd4aee7c ## 6. Protect High-Impact Boundaries (26.145.0)
|
|
1352
|
+
d5d93c55de33e4cdcb38f76c6d6d70a6e0beac7a176c8aa1daa09905ccc5fe39 ## 7. Report Evidence (26.145.0)
|
|
1353
|
+
cefc8bb6194d4f1b6302345e96ffb3a28b8b992032fd40f9f5b4f18997657e7a ## Presenting a decision (26.145.0)
|
|
1354
|
+
7385ff5df34148278a8f4b164c11ba5f9355626abcc13a822dd1ebb206321c2f ## Skills that apply continuously (26.145.0)
|
|
1355
|
+
ad9fd1ff225c57c9801a7d7472bf4ddf9c952c602f4a93eae86fbcb3bcf468bc ## 7. Report Evidence (26.146.0)
|
|
1356
|
+
868fe823fc40011d08816c9f1105ef6df7ca7f2479779303ce9583bba1ce6e0d ## Skills that apply continuously (26.146.0)
|
|
1357
|
+
3f8259ca7c92d79cca1a36bba38f36d4ef5a96fd6cafbd0edb5a79492082f46f ## Presenting a decision (26.147.0)
|
|
1358
|
+
ecfdcd50e97723af77cfe6889bbad784cdeb86dd0c52af3ff98ddf6adf80f445 ## 1. Resolve what matters, then act (26.151.0)
|
|
1359
|
+
9321cb1312a080bcf560940b8f86d3d59b39c667add4b8f3ad785ddae9bc8b20 ## 2. Choose the simplest sufficient solution (26.151.0)
|
|
1360
|
+
a4c345996a8578cc24b62fde27084e5848a61e4a40d91b0c72a95da46203b43c ## 3. Keep changes focused and preserve existing work (26.151.0)
|
|
1361
|
+
1adbf1bf88bb8288744e1c1d73518ffdec12a5b668d5a225e2bedd006844466c ## 4. Define success and verify proportionally (26.151.0)
|
|
1362
|
+
7636e57a877d54039f0c2829fde84202c65378bd36b8c8abb7274a29eaa5f8ac ## 5. Report evidence and stop unproductive loops (26.151.0)
|
|
1363
|
+
ddf2be9e04c04bf53ad9b5476e45639b33a60bf49bd3a83835796632052b17b4 ## 6. Keep authority explicit (26.151.0)
|
|
1364
|
+
16b0edc0f4886a9f9ec94e6fb97206c385286b2c9d5563b2324b7a2f4a434435 ## 1. Understand what success means (26.153.0)
|
|
1365
|
+
b10ab1eafe25bb7ba3b20b907b1d7eedde03e52fbd49905f24e192e30b4e1b9a ## 2. Choose and adapt the approach (26.153.0)
|
|
1366
|
+
69bcfb8b37ac184b1a30945a0dea59108ef1242c2f40fb778be118cbd524aea7 ## 3. Keep changes focused and coherent (26.153.0)
|
|
1367
|
+
f22a5a13c5ed8460c9370212d91354d0fea2fefc7f420a1eb3088504ae8da6c0 ## 4. Verify outcomes in proportion to consequences (26.153.0)
|
|
1368
|
+
7a335cde69e8055ee5e137a9a5c09fd7f7c2e551ab099a2cda87f0c3dcd95a19 ## 5. Let evidence determine readiness (26.153.0)
|
|
1369
|
+
79797568bb71bd0f7b14393f72e61721a4bfe99ecfb6126ffa38a6c03c53d765 ## 6. Act within clear authority (26.153.0)
|
|
1370
|
+
`);
|
|
1371
|
+
var LEGACY_HOOK_COMMANDS = /* @__PURE__ */ new Set([
|
|
1372
|
+
'bash "$CLAUDE_PROJECT_DIR/.claude/hooks/agentshield-gate.sh"',
|
|
1373
|
+
'bash "$CLAUDE_PROJECT_DIR/.claude/hooks/gate-check.sh"',
|
|
1374
|
+
'bash "$CLAUDE_PROJECT_DIR/.claude/hooks/hito-counter.sh"',
|
|
1375
|
+
'bash "$CLAUDE_PROJECT_DIR/.claude/hooks/mcp-pre-exec.sh"',
|
|
1376
|
+
'bash "$CLAUDE_PROJECT_DIR/.claude/hooks/protect-files.sh"',
|
|
1377
|
+
'bash "$CLAUDE_PROJECT_DIR/.claude/hooks/session-start.sh"',
|
|
1378
|
+
'bash "$CLAUDE_PROJECT_DIR/.claude/hooks/task-brief-nudge.sh"',
|
|
1379
|
+
'bash "$CLAUDE_PROJECT_DIR/.claude/skills/strategic-compact/suggest-compact.sh"'
|
|
1380
|
+
]);
|
|
1381
|
+
var LEGACY_STATUSLINE_VALUES = keySet(`
|
|
1382
|
+
f3de524065fd30f26e2d14b31fad0edc4c6689fb95b8ea6c59b1d48c5a90adc5 statusLine (26.70.0)
|
|
1383
|
+
94442f9703e367a12f6dc16612ad65ae5f0cd0c73b96dd683e584a18ac91eaea statusLine (26.164.0)
|
|
1384
|
+
`);
|
|
1385
|
+
|
|
1386
|
+
// src/hook-ref.ts
|
|
805
1387
|
function projectAnchoredRef(command, claudeDir) {
|
|
806
1388
|
const anchors = [
|
|
807
1389
|
"$CLAUDE_PROJECT_DIR/.claude/",
|
|
@@ -820,12 +1402,21 @@ function projectAnchoredRef(command, claudeDir) {
|
|
|
820
1402
|
}
|
|
821
1403
|
return void 0;
|
|
822
1404
|
}
|
|
1405
|
+
var LEGACY_HOOK_REFS = [...LEGACY_HOOK_COMMANDS].flatMap(
|
|
1406
|
+
(c3) => projectAnchoredRef(c3) ?? []
|
|
1407
|
+
);
|
|
1408
|
+
function isLegacyHookLine(command, claudeDir) {
|
|
1409
|
+
if (typeof command !== "string") return false;
|
|
1410
|
+
const ref = projectAnchoredRef(command, claudeDir);
|
|
1411
|
+
if (ref === void 0) return false;
|
|
1412
|
+
return !LEGACY_HOOK_REFS.includes(ref) || LEGACY_HOOK_COMMANDS.has(command);
|
|
1413
|
+
}
|
|
823
1414
|
function keepHookRef(hook, claudeDir, removed) {
|
|
824
1415
|
const relPath = projectAnchoredRef(hook?.command ?? "", claudeDir);
|
|
825
1416
|
if (relPath === void 0) return true;
|
|
826
|
-
const
|
|
827
|
-
if (!
|
|
828
|
-
return
|
|
1417
|
+
const exists2 = existsSync(join(claudeDir, relPath));
|
|
1418
|
+
if (!exists2 && !removed.includes(relPath)) removed.push(relPath);
|
|
1419
|
+
return exists2;
|
|
829
1420
|
}
|
|
830
1421
|
function findStaleHookRefs(settingsPath, claudeDir, spare) {
|
|
831
1422
|
let settings;
|
|
@@ -858,6 +1449,7 @@ function removeRetiredHookRefs(settingsPath, claudeDir, refs, opts = {}) {
|
|
|
858
1449
|
const isRetiredDead = (hook) => {
|
|
859
1450
|
const rel = projectAnchoredRef(hook?.command ?? "", claudeDir);
|
|
860
1451
|
if (rel === void 0 || !refs.includes(rel)) return false;
|
|
1452
|
+
if (!isLegacyHookLine(hook?.command, claudeDir)) return false;
|
|
861
1453
|
if (opts.evenIfScriptExists !== true && existsSync(join(claudeDir, rel))) return false;
|
|
862
1454
|
if (!removed.includes(rel)) removed.push(rel);
|
|
863
1455
|
return true;
|
|
@@ -1438,125 +2030,6 @@ init_esm_shims();
|
|
|
1438
2030
|
|
|
1439
2031
|
// src/agents-md-merge.ts
|
|
1440
2032
|
init_esm_shims();
|
|
1441
|
-
|
|
1442
|
-
// src/retired-anchor-sections.ts
|
|
1443
|
-
init_esm_shims();
|
|
1444
|
-
import { createHash } from "crypto";
|
|
1445
|
-
function retiredAnchorSectionKey(lines2) {
|
|
1446
|
-
const out = lines2.map((l) => l.replace(/\r$/, "").trimEnd());
|
|
1447
|
-
while (out.length > 1 && out.at(-1) === "") out.pop();
|
|
1448
|
-
return createHash("sha256").update(out.join("\n")).digest("hex");
|
|
1449
|
-
}
|
|
1450
|
-
var RETIRED_ANCHOR_SECTION_KEYS = /* @__PURE__ */ new Set([
|
|
1451
|
-
"522bac15bc17949697e291b837c0d9624f5e0c7666400a3baf94cdef7cfab8b5",
|
|
1452
|
-
// ## Rule 1 — Think Before Coding
|
|
1453
|
-
"ea10b7cd9b84a71949a071fae15256f490b3fe407159d7bddcf3f882310fa835",
|
|
1454
|
-
// ## Rule 2 — Simplicity First
|
|
1455
|
-
"c486465d9554f2de1711cd056437f6a95a5d3243264b82d29a6957f24b5a6de3",
|
|
1456
|
-
// ## Rule 3 — Surgical Changes
|
|
1457
|
-
"3d080574cc7ae81eda75c4aa019445b38b6f69c5f9eeeda9097e10b6041e7e94",
|
|
1458
|
-
// ## Rule 4 — Goal-Driven Execution
|
|
1459
|
-
"11e43547f6b1613a5dabb3edaf5131d696a3fd375b3c22558f03555a0f5cf2ef",
|
|
1460
|
-
// ## Rule 5 — Use the model only for judgment calls
|
|
1461
|
-
"60d91718de6ae16ec86b50e7c9a939a6ca5fc0721422b592700cc9972f55aca2",
|
|
1462
|
-
// ## Rule 6 — Token budgets are not advisory
|
|
1463
|
-
"9d482c7307cbcb02acc6fb35cd57b24baa9fce04528e2bd21e1e877603f8b85b",
|
|
1464
|
-
// ## Rule 7 — Surface conflicts, don't average them
|
|
1465
|
-
"abca09f13833ce18bd0ffc0793d59780c35447ca79c2a512afcbc9d7a7116ed8",
|
|
1466
|
-
// ## Rule 8 — Read before you write
|
|
1467
|
-
"5b4eae6c3dc2d92cfb1772889650882a4a2115f08a36602da9a1d96697059b91",
|
|
1468
|
-
// ## Rule 9 — Tests verify intent, not just behavior
|
|
1469
|
-
"632670b8897dc373d4a12f611c2436d9a8e86d8cdab917eecabc4bf2a56f8030",
|
|
1470
|
-
// ## Rule 10 — Checkpoint after every significant step
|
|
1471
|
-
"252e99f25b05a47e5ce884ac9f1e1d34156116b9a76331e2510b1354a6c98cd4",
|
|
1472
|
-
// ## Rule 11 — Match the codebase's conventions, even if you disagree
|
|
1473
|
-
"c28a12b589b6576379793c51fd01dbfaf91d391ac773f84ae0477ddb60a1e3e8",
|
|
1474
|
-
// ## Rule 12 — Fail loud
|
|
1475
|
-
"72feaf96f998989351f8083edb891c7b0c3bccca65dbea2732fb2864b8f98bd4",
|
|
1476
|
-
// ## 의사결정 및 컨펌 요청 시
|
|
1477
|
-
"95c932ecb4f4fdcdd8d483f9d02166b906f6eb045ef33ee474a16913d0c3e6cd",
|
|
1478
|
-
// ## Phase/작업 완료 시 Self-Audit 실행:
|
|
1479
|
-
"c7f9fa755bd66d80c2df496c6c759e8accd736cd8fef64460feb7ae9cd4c8006",
|
|
1480
|
-
// ## Context Management
|
|
1481
|
-
"6ec0b415a8f86c9940bccd3e6db895ea4a110185e76fef223a348f9553fd897c",
|
|
1482
|
-
// ## Rule 12 — Fail loud
|
|
1483
|
-
"a78f0ffa6b51c9b45c964ecb92db951534336f7e558a3d39d11f015ee6c3466c",
|
|
1484
|
-
// ## Anti-Patterns (Forbidden)
|
|
1485
|
-
"50d00a511e87571d7ff85f6584b87b9f5c2eef06122d8ac5fdccf3f047643f12",
|
|
1486
|
-
// ## When Requesting Decisions or Confirmation
|
|
1487
|
-
"574519e07f48bcc04f0e3d505c0f9c157ddd426b5eda2baa99656cd4712dad2b",
|
|
1488
|
-
// ## Run Self-Audit on Phase/Task Completion
|
|
1489
|
-
"df73823c02e6eee000388444964acfec233ffeec0e20fdc5d31eb018d2ca93c1",
|
|
1490
|
-
// ## Context Management
|
|
1491
|
-
"8f49f0a592575a65eadd3e33950c96616223aa8bb116707103affeef71db28c6",
|
|
1492
|
-
// ## Delegate the Building, Keep the Deciding
|
|
1493
|
-
"6115eccc3b2702f436a9db7d6af9803fa7b1fbf7b9ff1110ea658fadd67ec5ea",
|
|
1494
|
-
// ## 1. Think before coding
|
|
1495
|
-
"15b120395ec8e757ecbe3e65775371a9120953617fb37eb062e0c176b52f045a",
|
|
1496
|
-
// ## 2. Prefer the simplest sufficient solution
|
|
1497
|
-
"cc466b4781444ca54aedebd20ba3aa531c3aa84cc438953df84b133bd32a0e1e",
|
|
1498
|
-
// ## 3. Make surgical changes and preserve existing work
|
|
1499
|
-
"f6d1f6f02cb3c19e61becf329f20335c54e684bccb06b33e4b7f66eb49f9c6b6",
|
|
1500
|
-
// ## 4. Define success before editing
|
|
1501
|
-
"372bf30b282b861c6a89e355c94ffd239bb0202e2ef928f8af99d640579710f0",
|
|
1502
|
-
// ## 5. Report evidence, not confidence
|
|
1503
|
-
"66ca0e3aae98d24c65afbc418645df29d8c570be81918c42192eb1beecd21f23",
|
|
1504
|
-
// ## 6. Do not cross high-impact boundaries alone
|
|
1505
|
-
"9c6c27eb57a9790273fa3fdf0df3628d927b025f870f09933692d1b522d73a25",
|
|
1506
|
-
// ## Decisions and explanations
|
|
1507
|
-
"922d100c2dc6ef8a53989a920c3554afa7efd148255bc144412403c0289439e6",
|
|
1508
|
-
// ## Decisions and explanations
|
|
1509
|
-
"330a67775a28557431aebf36a44018fc5194a4b929bf2cf95184b1f0828a6360",
|
|
1510
|
-
// ## 1. Understand First
|
|
1511
|
-
"3b2f0147dc7bd0f01fd12485790199ef4ee96a6b723e244ffbf3dc96933a1ab8",
|
|
1512
|
-
// ## 2. Define Success and Keep It Simple
|
|
1513
|
-
"8802fb25c05879c98dbf8407001d239c410d25b4fa2521b11d9d7cc108f73b29",
|
|
1514
|
-
// ## 3. Preserve Sound Boundaries
|
|
1515
|
-
"1d0d9bf05d8870dd0dc62e388ceffc98923f1dd2074ef8038f80a50c9b5b9a81",
|
|
1516
|
-
// ## 4. Make Surgical Changes
|
|
1517
|
-
"05e08e2318061141464ae714d6770d35527576affa787740d9c6d9345d3462dd",
|
|
1518
|
-
// ## 5. Verify and Review
|
|
1519
|
-
"7b39f1f92a72517d6ae52599becfef29f675e48185a3483dc993d7accd4aee7c",
|
|
1520
|
-
// ## 6. Protect High-Impact Boundaries
|
|
1521
|
-
"d5d93c55de33e4cdcb38f76c6d6d70a6e0beac7a176c8aa1daa09905ccc5fe39",
|
|
1522
|
-
// ## 7. Report Evidence
|
|
1523
|
-
"cefc8bb6194d4f1b6302345e96ffb3a28b8b992032fd40f9f5b4f18997657e7a",
|
|
1524
|
-
// ## Presenting a decision
|
|
1525
|
-
"7385ff5df34148278a8f4b164c11ba5f9355626abcc13a822dd1ebb206321c2f",
|
|
1526
|
-
// ## Skills that apply continuously
|
|
1527
|
-
"ad9fd1ff225c57c9801a7d7472bf4ddf9c952c602f4a93eae86fbcb3bcf468bc",
|
|
1528
|
-
// ## 7. Report Evidence
|
|
1529
|
-
"868fe823fc40011d08816c9f1105ef6df7ca7f2479779303ce9583bba1ce6e0d",
|
|
1530
|
-
// ## Skills that apply continuously
|
|
1531
|
-
"3f8259ca7c92d79cca1a36bba38f36d4ef5a96fd6cafbd0edb5a79492082f46f",
|
|
1532
|
-
// ## Presenting a decision
|
|
1533
|
-
"ecfdcd50e97723af77cfe6889bbad784cdeb86dd0c52af3ff98ddf6adf80f445",
|
|
1534
|
-
// ## 1. Resolve what matters, then act
|
|
1535
|
-
"9321cb1312a080bcf560940b8f86d3d59b39c667add4b8f3ad785ddae9bc8b20",
|
|
1536
|
-
// ## 2. Choose the simplest sufficient solution
|
|
1537
|
-
"a4c345996a8578cc24b62fde27084e5848a61e4a40d91b0c72a95da46203b43c",
|
|
1538
|
-
// ## 3. Keep changes focused and preserve existing work
|
|
1539
|
-
"1adbf1bf88bb8288744e1c1d73518ffdec12a5b668d5a225e2bedd006844466c",
|
|
1540
|
-
// ## 4. Define success and verify proportionally
|
|
1541
|
-
"7636e57a877d54039f0c2829fde84202c65378bd36b8c8abb7274a29eaa5f8ac",
|
|
1542
|
-
// ## 5. Report evidence and stop unproductive loops
|
|
1543
|
-
"ddf2be9e04c04bf53ad9b5476e45639b33a60bf49bd3a83835796632052b17b4",
|
|
1544
|
-
// ## 6. Keep authority explicit
|
|
1545
|
-
"16b0edc0f4886a9f9ec94e6fb97206c385286b2c9d5563b2324b7a2f4a434435",
|
|
1546
|
-
// ## 1. Understand what success means
|
|
1547
|
-
"b10ab1eafe25bb7ba3b20b907b1d7eedde03e52fbd49905f24e192e30b4e1b9a",
|
|
1548
|
-
// ## 2. Choose and adapt the approach
|
|
1549
|
-
"69bcfb8b37ac184b1a30945a0dea59108ef1242c2f40fb778be118cbd524aea7",
|
|
1550
|
-
// ## 3. Keep changes focused and coherent
|
|
1551
|
-
"f22a5a13c5ed8460c9370212d91354d0fea2fefc7f420a1eb3088504ae8da6c0",
|
|
1552
|
-
// ## 4. Verify outcomes in proportion to consequences
|
|
1553
|
-
"7a335cde69e8055ee5e137a9a5c09fd7f7c2e551ab099a2cda87f0c3dcd95a19",
|
|
1554
|
-
// ## 5. Let evidence determine readiness
|
|
1555
|
-
"79797568bb71bd0f7b14393f72e61721a4bfe99ecfb6126ffa38a6c03c53d765"
|
|
1556
|
-
// ## 6. Act within clear authority
|
|
1557
|
-
]);
|
|
1558
|
-
|
|
1559
|
-
// src/agents-md-merge.ts
|
|
1560
2033
|
var marker = (name) => ({
|
|
1561
2034
|
start: `<!-- uzys-harness:${name}:start -->`,
|
|
1562
2035
|
end: `<!-- uzys-harness:${name}:end -->`
|
|
@@ -1627,6 +2100,29 @@ function trimTrailingBlanks(lines2) {
|
|
|
1627
2100
|
while (out.length > 0 && (out.at(-1) ?? "").trim() === "") out.pop();
|
|
1628
2101
|
return out;
|
|
1629
2102
|
}
|
|
2103
|
+
function isLegacyHarnessSection(lines2) {
|
|
2104
|
+
const key = legacySectionKey(lines2);
|
|
2105
|
+
return RETIRED_ANCHOR_SECTION_KEYS.has(key) || LEGACY_AGENTS_MD_SECTION_KEYS.has(key) || LEGACY_AGENTS_MD_NAMED_KEYS.has(key);
|
|
2106
|
+
}
|
|
2107
|
+
function withoutAgentsBlock(text) {
|
|
2108
|
+
const lines2 = text.split("\n");
|
|
2109
|
+
const at5 = blockRange(lines2, AGENTS_BLOCK);
|
|
2110
|
+
if (at5 === null) return text;
|
|
2111
|
+
const head = trimTrailingBlanks(lines2.slice(0, at5[0]));
|
|
2112
|
+
const tail = lines2.slice(at5[1] + 1);
|
|
2113
|
+
while (tail.length > 0 && (tail[0] ?? "").trim() === "") tail.shift();
|
|
2114
|
+
return tail.length > 0 ? [...head, "", ...tail].join("\n") : `${head.join("\n")}
|
|
2115
|
+
`;
|
|
2116
|
+
}
|
|
2117
|
+
function isLegacyHarnessAgentsMd(text) {
|
|
2118
|
+
const body = withoutAgentsBlock(text);
|
|
2119
|
+
const lines2 = body.split("\n");
|
|
2120
|
+
if (blockRange(lines2, ANCHOR_BLOCK) !== null || blockRange(lines2, SKILLS_BLOCK) !== null) {
|
|
2121
|
+
return false;
|
|
2122
|
+
}
|
|
2123
|
+
const key = legacyPreambleKey(body);
|
|
2124
|
+
return key !== null && LEGACY_AGENTS_MD_PREAMBLE_KEYS.has(key);
|
|
2125
|
+
}
|
|
1630
2126
|
function refreshBlock(existing, rendered, m, legacyHeading) {
|
|
1631
2127
|
const at5 = blockRange(rendered, m);
|
|
1632
2128
|
const fresh = at5 === null ? null : rendered.slice(at5[0], at5[1] + 1);
|
|
@@ -1679,9 +2175,11 @@ function renderAgentsBlock(params) {
|
|
|
1679
2175
|
trimBlankEdges(harness)
|
|
1680
2176
|
].filter((part) => part.length > 0).map((part) => part.join("\n")).join("\n\n");
|
|
1681
2177
|
}
|
|
1682
|
-
function
|
|
2178
|
+
function mergeAgentsMdDetailed(params) {
|
|
1683
2179
|
const { rendered, existing, template } = params;
|
|
1684
|
-
if (existing === null)
|
|
2180
|
+
if (existing === null) {
|
|
2181
|
+
return { text: rendered, droppedLegacySections: 0, editedLegacySections: [] };
|
|
2182
|
+
}
|
|
1685
2183
|
const names = sectionNames(template);
|
|
1686
2184
|
const bodies = /* @__PURE__ */ new Map();
|
|
1687
2185
|
const contextNow = sectionBody(existing, names, CONTEXT_SECTION);
|
|
@@ -1703,18 +2201,32 @@ function mergeAgentsMd(params) {
|
|
|
1703
2201
|
}
|
|
1704
2202
|
const merged = bodies.size === 0 ? rendered : assemble(rendered, names, bodies);
|
|
1705
2203
|
const mergedText = merged.replace(/\r/g, "");
|
|
1706
|
-
const
|
|
2204
|
+
const candidates = extraTopLevelSections(
|
|
1707
2205
|
existing,
|
|
1708
2206
|
names,
|
|
1709
2207
|
rendered,
|
|
1710
2208
|
params.harnessRuleHeadings ?? /* @__PURE__ */ new Set(),
|
|
1711
2209
|
replacedRulesHeadings
|
|
1712
|
-
).filter((e2) => !mergedText.includes(e2.join("\n").replace(/\r/g, "")));
|
|
1713
|
-
if (extras.length === 0) return merged;
|
|
1714
|
-
return `${merged.replace(/\n+$/, "\n")}${extras.map((e2) => e2.join("\n")).join("\n")}`.replace(
|
|
1715
|
-
/\n+$/,
|
|
1716
|
-
"\n"
|
|
1717
2210
|
);
|
|
2211
|
+
const droppedLegacySections = candidates.legacy;
|
|
2212
|
+
const editedLegacySections = isLegacyHarnessAgentsMd(existing) ? installerSectionsInHarnessArea(
|
|
2213
|
+
existing,
|
|
2214
|
+
names,
|
|
2215
|
+
/* @__PURE__ */ new Set([...params.harnessRuleHeadings ?? [], ...renderedRuleHeadings(rendered, names)]),
|
|
2216
|
+
true
|
|
2217
|
+
).keptEdited : [];
|
|
2218
|
+
const extras = candidates.sections.filter(
|
|
2219
|
+
(e2) => !mergedText.includes(e2.join("\n").replace(/\r/g, ""))
|
|
2220
|
+
);
|
|
2221
|
+
if (extras.length === 0) return { text: merged, droppedLegacySections, editedLegacySections };
|
|
2222
|
+
return {
|
|
2223
|
+
text: `${merged.replace(/\n+$/, "\n")}${extras.map((e2) => e2.join("\n")).join("\n")}`.replace(
|
|
2224
|
+
/\n+$/,
|
|
2225
|
+
"\n"
|
|
2226
|
+
),
|
|
2227
|
+
droppedLegacySections,
|
|
2228
|
+
editedLegacySections
|
|
2229
|
+
};
|
|
1718
2230
|
}
|
|
1719
2231
|
function headingOwner(bare, ctx) {
|
|
1720
2232
|
const name = /^## (.+?)\s*$/.exec(bare)?.[1];
|
|
@@ -1737,7 +2249,6 @@ function extraTopLevelSections(existing, names, rendered, harnessRuleHeadings, r
|
|
|
1737
2249
|
...renderedRuleHeadings(rendered, names)
|
|
1738
2250
|
]);
|
|
1739
2251
|
const out = [];
|
|
1740
|
-
const replacedSections = /* @__PURE__ */ new Set();
|
|
1741
2252
|
let current = null;
|
|
1742
2253
|
let region = null;
|
|
1743
2254
|
for (const line of existing.split("\n")) {
|
|
@@ -1749,19 +2260,18 @@ function extraTopLevelSections(existing, names, rendered, harnessRuleHeadings, r
|
|
|
1749
2260
|
const owner = headingOwner(bare, { region, names, harnessHeadings });
|
|
1750
2261
|
const replacedBody = owner === "body" && region === RULES_SECTION && replacedRulesHeadings !== null && !replacedRulesHeadings.has(bare.trim());
|
|
1751
2262
|
current = owner === "installer" || replacedBody ? [line] : null;
|
|
1752
|
-
if (replacedBody && current !== null) replacedSections.add(current);
|
|
1753
2263
|
continue;
|
|
1754
2264
|
}
|
|
1755
2265
|
if (current !== null) current.push(line);
|
|
1756
2266
|
}
|
|
1757
2267
|
if (current !== null) out.push(current);
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
).map((lines2) => {
|
|
2268
|
+
const legacy = out.filter(isLegacyHarnessSection).length;
|
|
2269
|
+
const sections = out.filter((lines2) => !isLegacyHarnessSection(lines2)).map((lines2) => {
|
|
1761
2270
|
const trimmed = [...lines2];
|
|
1762
2271
|
while (trimmed.length > 1 && (trimmed.at(-1) ?? "").trim() === "") trimmed.pop();
|
|
1763
2272
|
return trimmed;
|
|
1764
2273
|
}).filter((lines2) => lines2.length > 1 || /^## /.test(lines2[0] ?? ""));
|
|
2274
|
+
return { sections, legacy };
|
|
1765
2275
|
}
|
|
1766
2276
|
function installerLines(body, m) {
|
|
1767
2277
|
if (body === null) return [];
|
|
@@ -1781,7 +2291,7 @@ function projectContextInstallerLines(params) {
|
|
|
1781
2291
|
const body = sectionBody(existing, sectionNames(template), CONTEXT_SECTION);
|
|
1782
2292
|
return body === null ? null : installerLines(body, SKILLS_BLOCK);
|
|
1783
2293
|
}
|
|
1784
|
-
function installerSectionsInHarnessArea(existing, names, harnessRuleHeadings) {
|
|
2294
|
+
function installerSectionsInHarnessArea(existing, names, harnessRuleHeadings, legacyFile = false) {
|
|
1785
2295
|
const out = [];
|
|
1786
2296
|
let current = null;
|
|
1787
2297
|
let region = null;
|
|
@@ -1792,31 +2302,60 @@ function installerSectionsInHarnessArea(existing, names, harnessRuleHeadings) {
|
|
|
1792
2302
|
if (current !== null) out.push(current);
|
|
1793
2303
|
if (names.has(name)) region = name;
|
|
1794
2304
|
const owner = headingOwner(bare, { region, names, harnessHeadings: harnessRuleHeadings });
|
|
1795
|
-
current = owner === "installer" ? [bare] : null;
|
|
2305
|
+
if (!legacyFile) current = owner === "installer" ? { lines: [bare], named: false } : null;
|
|
2306
|
+
else if (region === CONTEXT_SECTION) current = null;
|
|
2307
|
+
else current = { lines: [bare], named: owner === "harness" };
|
|
1796
2308
|
continue;
|
|
1797
2309
|
}
|
|
1798
|
-
if (current !== null) current.push(bare);
|
|
2310
|
+
if (current !== null) current.lines.push(bare);
|
|
1799
2311
|
}
|
|
1800
2312
|
if (current !== null) out.push(current);
|
|
1801
|
-
|
|
2313
|
+
const sections = [];
|
|
2314
|
+
const keptEdited = [];
|
|
2315
|
+
let legacy = 0;
|
|
2316
|
+
for (const { lines: lines2, named } of out) {
|
|
2317
|
+
if (isLegacyHarnessSection(lines2)) {
|
|
2318
|
+
legacy++;
|
|
2319
|
+
continue;
|
|
2320
|
+
}
|
|
2321
|
+
if (named) {
|
|
2322
|
+
if (lines2.slice(1).every((l) => l.trim() === "")) continue;
|
|
2323
|
+
keptEdited.push((lines2[0] ?? "").replace(/^## /, "").trim());
|
|
2324
|
+
}
|
|
2325
|
+
sections.push(trimTrailingBlanks(lines2));
|
|
2326
|
+
}
|
|
2327
|
+
return { sections, legacy, keptEdited };
|
|
1802
2328
|
}
|
|
1803
|
-
function
|
|
2329
|
+
function stripAgentsMd(params) {
|
|
1804
2330
|
const { existing, template } = params;
|
|
1805
2331
|
const lines2 = existing.split("\n");
|
|
2332
|
+
const names = sectionNames(template);
|
|
2333
|
+
const headings = params.harnessRuleHeadings ?? /* @__PURE__ */ new Set();
|
|
1806
2334
|
if (blockRange(lines2, ANCHOR_BLOCK) === null && blockRange(lines2, SKILLS_BLOCK) === null) {
|
|
1807
|
-
|
|
2335
|
+
if (!isLegacyHarnessAgentsMd(existing)) {
|
|
2336
|
+
return {
|
|
2337
|
+
remainder: null,
|
|
2338
|
+
legacyRemoved: false,
|
|
2339
|
+
legacySections: 0,
|
|
2340
|
+
keptEdited: []
|
|
2341
|
+
};
|
|
2342
|
+
}
|
|
2343
|
+
const body = withoutAgentsBlock(existing);
|
|
2344
|
+
return stripLegacyAgentsMd(body, names, headings);
|
|
1808
2345
|
}
|
|
1809
|
-
const names = sectionNames(template);
|
|
1810
2346
|
const context = installerLines(sectionBody(existing, names, CONTEXT_SECTION), SKILLS_BLOCK);
|
|
1811
2347
|
const rules = installerLines(sectionBody(existing, names, RULES_SECTION), ANCHOR_BLOCK);
|
|
1812
2348
|
const contextFilled = !isUnfilledScaffold(context);
|
|
1813
2349
|
const rulesFilled = compact(rules).length > 0;
|
|
1814
|
-
const extras = installerSectionsInHarnessArea(
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
2350
|
+
const extras = installerSectionsInHarnessArea(existing, names, headings);
|
|
2351
|
+
const legacy = {
|
|
2352
|
+
legacyRemoved: extras.legacy > 0,
|
|
2353
|
+
legacySections: extras.legacy,
|
|
2354
|
+
keptEdited: []
|
|
2355
|
+
};
|
|
2356
|
+
if (!contextFilled && !rulesFilled && extras.sections.length === 0) {
|
|
2357
|
+
return { remainder: null, ...legacy };
|
|
2358
|
+
}
|
|
1820
2359
|
const out = [];
|
|
1821
2360
|
const title = (lines2[0] ?? "").replace(/\r$/, "");
|
|
1822
2361
|
if (/^# /.test(title)) out.push(title, "");
|
|
@@ -1824,8 +2363,26 @@ function stripHarnessFromAgentsMd(params) {
|
|
|
1824
2363
|
out.push(`## ${CONTEXT_SECTION}`, "", ...trimBlankEdges(context), "");
|
|
1825
2364
|
}
|
|
1826
2365
|
if (rulesFilled) out.push(`## ${RULES_SECTION}`, "", ...trimBlankEdges(rules), "");
|
|
1827
|
-
for (const section of extras) out.push(...section, "");
|
|
1828
|
-
return out.join("\n");
|
|
2366
|
+
for (const section of extras.sections) out.push(...section, "");
|
|
2367
|
+
return { remainder: out.join("\n"), ...legacy };
|
|
2368
|
+
}
|
|
2369
|
+
function stripLegacyAgentsMd(existing, names, headings) {
|
|
2370
|
+
const contextBody = sectionBody(existing, names, CONTEXT_SECTION);
|
|
2371
|
+
const context = dropHarnessQuoteBlocks(contextBody ?? []);
|
|
2372
|
+
const contextFilled = contextBody !== null && !isUnfilledScaffold(context);
|
|
2373
|
+
const extras = installerSectionsInHarnessArea(existing, names, headings, true);
|
|
2374
|
+
const result = {
|
|
2375
|
+
legacyRemoved: true,
|
|
2376
|
+
legacySections: extras.legacy,
|
|
2377
|
+
keptEdited: extras.keptEdited
|
|
2378
|
+
};
|
|
2379
|
+
if (!contextFilled && extras.sections.length === 0) return { remainder: null, ...result };
|
|
2380
|
+
const out = [];
|
|
2381
|
+
const title = (existing.split("\n")[0] ?? "").replace(/\r$/, "");
|
|
2382
|
+
if (/^# /.test(title)) out.push(title, "");
|
|
2383
|
+
if (contextFilled) out.push(`## ${CONTEXT_SECTION}`, "", ...trimBlankEdges(context), "");
|
|
2384
|
+
for (const section of extras.sections) out.push(...section, "");
|
|
2385
|
+
return { remainder: out.join("\n"), ...result };
|
|
1829
2386
|
}
|
|
1830
2387
|
|
|
1831
2388
|
// src/adapters/marker-md.ts
|
|
@@ -3402,7 +3959,7 @@ function parseRemote(raw) {
|
|
|
3402
3959
|
return { type: "http", url, auth: { bearerEnv } };
|
|
3403
3960
|
}
|
|
3404
3961
|
function parseTrackMcpMap(raw) {
|
|
3405
|
-
const
|
|
3962
|
+
const rows2 = [];
|
|
3406
3963
|
for (const line of raw.split(/\r?\n/)) {
|
|
3407
3964
|
const trimmed = line.trim();
|
|
3408
3965
|
if (!trimmed || trimmed.startsWith("#")) {
|
|
@@ -3418,7 +3975,7 @@ function parseTrackMcpMap(raw) {
|
|
|
3418
3975
|
}
|
|
3419
3976
|
if (command === "url") {
|
|
3420
3977
|
const server = parseRemote(argsJson ?? "");
|
|
3421
|
-
if (server !== null)
|
|
3978
|
+
if (server !== null) rows2.push({ name, pattern, server });
|
|
3422
3979
|
continue;
|
|
3423
3980
|
}
|
|
3424
3981
|
let args;
|
|
@@ -3430,9 +3987,9 @@ function parseTrackMcpMap(raw) {
|
|
|
3430
3987
|
if (!Array.isArray(args) || !args.every((a) => typeof a === "string")) {
|
|
3431
3988
|
continue;
|
|
3432
3989
|
}
|
|
3433
|
-
|
|
3990
|
+
rows2.push({ name, pattern, server: { type: "stdio", command, args } });
|
|
3434
3991
|
}
|
|
3435
|
-
return
|
|
3992
|
+
return rows2;
|
|
3436
3993
|
}
|
|
3437
3994
|
function toClaudeServer(cfg) {
|
|
3438
3995
|
if (cfg.type === "http") {
|
|
@@ -3450,12 +4007,12 @@ function toClaudeServer(cfg) {
|
|
|
3450
4007
|
if (cfg.env && Object.keys(cfg.env).length > 0) out.env = { ...cfg.env };
|
|
3451
4008
|
return out;
|
|
3452
4009
|
}
|
|
3453
|
-
function mergeMcpServers(base,
|
|
4010
|
+
function mergeMcpServers(base, rows2, tracks, chosen = [], dropped = []) {
|
|
3454
4011
|
const out = {
|
|
3455
4012
|
...base,
|
|
3456
4013
|
mcpServers: { ...base.mcpServers }
|
|
3457
4014
|
};
|
|
3458
|
-
for (const row of
|
|
4015
|
+
for (const row of rows2) {
|
|
3459
4016
|
if (dropped.includes(row.name)) {
|
|
3460
4017
|
continue;
|
|
3461
4018
|
}
|
|
@@ -3473,27 +4030,27 @@ function mergeMcpServers(base, rows, tracks, chosen = [], dropped = []) {
|
|
|
3473
4030
|
function composeMcpJson(opts) {
|
|
3474
4031
|
const base = JSON.parse(readFileSync3(opts.templateMcpPath, "utf8"));
|
|
3475
4032
|
const mapRaw = existsSync4(opts.trackMapPath) ? readFileSync3(opts.trackMapPath, "utf8") : "";
|
|
3476
|
-
const
|
|
3477
|
-
return mergeMcpServers(base,
|
|
4033
|
+
const rows2 = parseTrackMcpMap(mapRaw);
|
|
4034
|
+
return mergeMcpServers(base, rows2, opts.tracks, opts.chosen(rows2), opts.dropped?.(rows2) ?? []);
|
|
3478
4035
|
}
|
|
3479
|
-
function selectableMcpServers(
|
|
3480
|
-
const names = new Set(
|
|
4036
|
+
function selectableMcpServers(rows2) {
|
|
4037
|
+
const names = new Set(rows2.map((r) => r.name));
|
|
3481
4038
|
const out = /* @__PURE__ */ new Map();
|
|
3482
4039
|
for (const a of EXTERNAL_ASSETS) {
|
|
3483
4040
|
if (a.method.kind === "internal" && names.has(a.method.key)) out.set(a.method.key, a.id);
|
|
3484
4041
|
}
|
|
3485
4042
|
return out;
|
|
3486
4043
|
}
|
|
3487
|
-
function selectedMcpServers(
|
|
4044
|
+
function selectedMcpServers(rows2, choice) {
|
|
3488
4045
|
const recorded2 = new Set(
|
|
3489
4046
|
(choice.previousLog?.portions ?? []).filter((p2) => p2.path === ".mcp.json").map((p2) => p2.key)
|
|
3490
4047
|
);
|
|
3491
4048
|
const legacy = new Set(
|
|
3492
|
-
choice.projectDir === void 0 ? [] : legacyMcpServers(choice.projectDir, choice.previousLog,
|
|
4049
|
+
choice.projectDir === void 0 ? [] : legacyMcpServers(choice.projectDir, choice.previousLog, rows2)
|
|
3493
4050
|
);
|
|
3494
|
-
const dropped = new Set(droppedMcpServers(
|
|
4051
|
+
const dropped = new Set(droppedMcpServers(rows2, choice.excluded));
|
|
3495
4052
|
const out = [];
|
|
3496
|
-
for (const [name, assetId] of selectableMcpServers(
|
|
4053
|
+
for (const [name, assetId] of selectableMcpServers(rows2)) {
|
|
3497
4054
|
if (dropped.has(name)) continue;
|
|
3498
4055
|
const key = `mcpServers.${name}`;
|
|
3499
4056
|
if (isAssetSelected(assetId, choice.spec) || recorded2.has(key) || legacy.has(name)) {
|
|
@@ -3502,7 +4059,7 @@ function selectedMcpServers(rows, choice) {
|
|
|
3502
4059
|
}
|
|
3503
4060
|
return out;
|
|
3504
4061
|
}
|
|
3505
|
-
function legacyMcpServers(projectDir, previousLog,
|
|
4062
|
+
function legacyMcpServers(projectDir, previousLog, rows2) {
|
|
3506
4063
|
if (previousLog === null || previousLog.records === "writer") return [];
|
|
3507
4064
|
if ((previousLog.portions ?? []).some((p2) => p2.path === ".mcp.json")) return [];
|
|
3508
4065
|
const created = (previousLog.rootFiles ?? []).some(
|
|
@@ -3512,10 +4069,10 @@ function legacyMcpServers(projectDir, previousLog, rows) {
|
|
|
3512
4069
|
const servers = readMcpServers(join5(projectDir, ".mcp.json"));
|
|
3513
4070
|
if (servers === null) return [];
|
|
3514
4071
|
const out = [];
|
|
3515
|
-
for (const name of selectableMcpServers(
|
|
4072
|
+
for (const name of selectableMcpServers(rows2).keys()) {
|
|
3516
4073
|
if (!Object.hasOwn(servers, name)) continue;
|
|
3517
4074
|
const disk = jsonSha(servers[name]);
|
|
3518
|
-
const row =
|
|
4075
|
+
const row = rows2.find((r) => r.name === name);
|
|
3519
4076
|
const known = [...row ? [row.server] : [], ...priorMcpValues(name)];
|
|
3520
4077
|
if (known.some((v2) => jsonSha(toClaudeServer(v2)) === disk)) out.push(name);
|
|
3521
4078
|
}
|
|
@@ -3533,8 +4090,8 @@ function readMcpServers(path) {
|
|
|
3533
4090
|
return null;
|
|
3534
4091
|
}
|
|
3535
4092
|
}
|
|
3536
|
-
function droppedMcpServers(
|
|
3537
|
-
return [...selectableMcpServers(
|
|
4093
|
+
function droppedMcpServers(rows2, excluded) {
|
|
4094
|
+
return [...selectableMcpServers(rows2)].filter(([name, assetId]) => {
|
|
3538
4095
|
const id = keyId(".mcp.json", `mcpServers.${name}`);
|
|
3539
4096
|
return excluded.has(assetId) || id !== null && excluded.has(id);
|
|
3540
4097
|
}).map(([name]) => name);
|
|
@@ -4088,7 +4645,7 @@ function hookScript(handler, claudeDir) {
|
|
|
4088
4645
|
const script = ref.slice("hooks/".length);
|
|
4089
4646
|
return script.includes("/") ? null : script;
|
|
4090
4647
|
}
|
|
4091
|
-
function legacySettingsSeed(text, render, projectDir) {
|
|
4648
|
+
function legacySettingsSeed(text, render, projectDir, opts = {}) {
|
|
4092
4649
|
const seed = /* @__PURE__ */ new Map();
|
|
4093
4650
|
let root;
|
|
4094
4651
|
try {
|
|
@@ -4098,6 +4655,7 @@ function legacySettingsSeed(text, render, projectDir) {
|
|
|
4098
4655
|
}
|
|
4099
4656
|
const claudeDir = join7(projectDir, ".claude");
|
|
4100
4657
|
const candidates = new Set([...render.keys()].filter((k2) => k2.startsWith("hooks.")));
|
|
4658
|
+
const legacyLines = /* @__PURE__ */ new Set();
|
|
4101
4659
|
const hooks = isObject2(root) && isObject2(root.hooks) ? root.hooks : {};
|
|
4102
4660
|
for (const [event, groups] of Object.entries(hooks)) {
|
|
4103
4661
|
if (!Array.isArray(groups)) continue;
|
|
@@ -4105,14 +4663,16 @@ function legacySettingsSeed(text, render, projectDir) {
|
|
|
4105
4663
|
if (!isObject2(group) || !Array.isArray(group.hooks)) continue;
|
|
4106
4664
|
for (const handler of group.hooks) {
|
|
4107
4665
|
const script = hookScript(handler, claudeDir);
|
|
4108
|
-
if (script
|
|
4109
|
-
|
|
4110
|
-
}
|
|
4666
|
+
if (script === null) continue;
|
|
4667
|
+
const key = `hooks.${event}#${script}`;
|
|
4668
|
+
if (RETIRED_PATHS.includes(`hooks/${script}`)) candidates.add(key);
|
|
4669
|
+
if (isObject2(handler) && isLegacyHookLine(handler.command, claudeDir)) legacyLines.add(key);
|
|
4111
4670
|
}
|
|
4112
4671
|
}
|
|
4113
4672
|
}
|
|
4114
4673
|
const present2 = ADAPTERS["json-keys"].read(text, candidates, projectDir) ?? /* @__PURE__ */ new Map();
|
|
4115
4674
|
for (const [key, sha] of present2) {
|
|
4675
|
+
if (!legacyLines.has(key) && opts.edited !== true) continue;
|
|
4116
4676
|
const rendered = render.get(key);
|
|
4117
4677
|
const handler = isObject2(rendered) && Array.isArray(rendered.hooks) ? rendered.hooks[0] : void 0;
|
|
4118
4678
|
seed.set(key, handler === void 0 ? sha : jsonSha(handler));
|
|
@@ -4209,8 +4769,8 @@ function legacyGitignoreSeed(text, render, previous) {
|
|
|
4209
4769
|
|
|
4210
4770
|
// src/installer.ts
|
|
4211
4771
|
init_esm_shims();
|
|
4212
|
-
import { chmodSync as chmodSync3, existsSync as existsSync22, readdirSync as
|
|
4213
|
-
import { basename as basename4, join as
|
|
4772
|
+
import { chmodSync as chmodSync3, existsSync as existsSync22, readdirSync as readdirSync5, readFileSync as readFileSync22, writeFileSync as writeFileSync8 } from "fs";
|
|
4773
|
+
import { basename as basename4, join as join31, relative as relative4, resolve, sep as sep5 } from "path";
|
|
4214
4774
|
|
|
4215
4775
|
// src/anchor-seed.ts
|
|
4216
4776
|
init_esm_shims();
|
|
@@ -4513,6 +5073,10 @@ function createOwnedWriter(projectDir, baseline, options = {}) {
|
|
|
4513
5073
|
const backupRel = relative2(projectDir, backup).split(sep3).join("/");
|
|
4514
5074
|
displace({ path: rel, change: "displaced", notes: [backupRel] });
|
|
4515
5075
|
} else backedUp.push(rel);
|
|
5076
|
+
} else if (opts?.backupFirst === true) {
|
|
5077
|
+
const backup = backupFile(absPath, now);
|
|
5078
|
+
backupPaths.push(backup);
|
|
5079
|
+
journal?.backup(backup);
|
|
4516
5080
|
}
|
|
4517
5081
|
writeFileSync4(absPath, content);
|
|
4518
5082
|
updated++;
|
|
@@ -4723,28 +5287,43 @@ function hasMarkerLine(disk, markers) {
|
|
|
4723
5287
|
}
|
|
4724
5288
|
function agentsMdModel(disk, recordedByHarness, recordedBlock = false) {
|
|
4725
5289
|
if (disk === null) return recordedBlock && !recordedByHarness ? "block" : "sections";
|
|
4726
|
-
|
|
5290
|
+
const legacy = isLegacyHarnessAgentsMd(disk);
|
|
5291
|
+
if (hasMarkerLine(disk, [AGENTS_BLOCK.start, AGENTS_BLOCK.end]) && !legacy) return "block";
|
|
4727
5292
|
if (recordedByHarness) return "sections";
|
|
4728
5293
|
if (hasMarkerLine(disk, [ANCHOR_BLOCK.start, SKILLS_BLOCK.start])) return "sections";
|
|
5294
|
+
if (legacy) return "sections";
|
|
4729
5295
|
return "block";
|
|
4730
5296
|
}
|
|
4731
5297
|
function writeAgentsMd(params) {
|
|
4732
5298
|
const abs = join13(params.projectDir, AGENTS_MD);
|
|
4733
5299
|
const disk = existsSync11(abs) ? readFileSync8(abs, "utf8") : null;
|
|
4734
5300
|
const recordedBlock = (params.record.portions ?? []).some((p2) => p2.path === AGENTS_MD);
|
|
4735
|
-
|
|
4736
|
-
|
|
4737
|
-
|
|
4738
|
-
|
|
4739
|
-
|
|
4740
|
-
|
|
4741
|
-
|
|
4742
|
-
|
|
4743
|
-
|
|
4744
|
-
}
|
|
4745
|
-
|
|
4746
|
-
|
|
4747
|
-
|
|
5301
|
+
const recordedByHarness = params.baseline.has(AGENTS_MD);
|
|
5302
|
+
if (agentsMdModel(disk, recordedByHarness, recordedBlock) === "sections") {
|
|
5303
|
+
const legacyUnrecorded = disk !== null && !recordedByHarness && isLegacyHarnessAgentsMd(disk);
|
|
5304
|
+
const merged = mergeAgentsMdDetailed({
|
|
5305
|
+
rendered: params.rendered,
|
|
5306
|
+
// N2 — 첫 접촉 블록은 떼고 병합한다(블록 안은 지금 렌더가 다시 쓴다)
|
|
5307
|
+
existing: disk === null ? null : withoutAgentsBlock(disk),
|
|
5308
|
+
template: params.template,
|
|
5309
|
+
...params.replaceUnfilledContext === true || legacyUnrecorded ? { replaceUnfilledContext: true } : {},
|
|
5310
|
+
...params.harnessRuleHeadings === void 0 ? {} : { harnessRuleHeadings: params.harnessRuleHeadings }
|
|
5311
|
+
});
|
|
5312
|
+
const dropped = merged.droppedLegacySections;
|
|
5313
|
+
const edited = merged.editedLegacySections;
|
|
5314
|
+
params.writer.write(abs, merged.text, {
|
|
5315
|
+
...params.createInRefresh === true ? { createInRefresh: true } : {},
|
|
5316
|
+
// ADR-111 — 떨어뜨린 절은 현행 번들에 없는 바이트다 · 고친 이름 절은 설치자 글이다: 기준선 그대로인 파일이라도 1회 백업
|
|
5317
|
+
...dropped > 0 || edited.length > 0 ? { backupFirst: true } : {}
|
|
5318
|
+
});
|
|
5319
|
+
if (recordedBlock) params.writer.journal?.portions(AGENTS_MD, []);
|
|
5320
|
+
return {
|
|
5321
|
+
model: "sections",
|
|
5322
|
+
shared: null,
|
|
5323
|
+
...dropped > 0 ? { droppedLegacySections: dropped } : {},
|
|
5324
|
+
...edited.length > 0 ? { editedLegacySections: edited } : {},
|
|
5325
|
+
...recordedBlock ? { blockRecordDropped: true } : {}
|
|
5326
|
+
};
|
|
4748
5327
|
}
|
|
4749
5328
|
const shared2 = writeShared({
|
|
4750
5329
|
projectDir: params.projectDir,
|
|
@@ -4834,10 +5413,15 @@ function runAgentsMdTransform(params) {
|
|
|
4834
5413
|
const { harnessRoot, projectDir, baseline, shared: shared2 = {} } = params;
|
|
4835
5414
|
const refreshOnly = params.refreshOnly === true;
|
|
4836
5415
|
const clis = agentsMdClis(params.clis);
|
|
5416
|
+
const agentsMdPath = join14(projectDir, "AGENTS.md");
|
|
5417
|
+
const exists2 = existsSync12(agentsMdPath);
|
|
5418
|
+
const diskBefore = exists2 ? readFileSync9(agentsMdPath, "utf8") : null;
|
|
5419
|
+
const legacyAgentsMd = diskBefore !== null && isLegacyHarnessAgentsMd(diskBefore);
|
|
5420
|
+
const owned = (rel) => params.owned?.(rel) === true || rel === "AGENTS.md" && legacyAgentsMd;
|
|
4837
5421
|
const writer = createOwnedWriter(projectDir, baseline, {
|
|
4838
5422
|
refreshOnly,
|
|
4839
5423
|
...params.journal === void 0 ? {} : { journal: params.journal },
|
|
4840
|
-
|
|
5424
|
+
owned
|
|
4841
5425
|
});
|
|
4842
5426
|
const claudeMd = readRequired(join14(harnessRoot, "templates/CLAUDE.md"));
|
|
4843
5427
|
const template = readRequired(join14(harnessRoot, AGENTS_MD_TEMPLATE));
|
|
@@ -4847,9 +5431,7 @@ function runAgentsMdTransform(params) {
|
|
|
4847
5431
|
refreshOnly,
|
|
4848
5432
|
writer
|
|
4849
5433
|
});
|
|
4850
|
-
const
|
|
4851
|
-
const exists = existsSync12(agentsMdPath);
|
|
4852
|
-
const creates = !exists && (!refreshOnly || params.installedByRecord === true);
|
|
5434
|
+
const creates = !exists2 && (!refreshOnly || params.installedByRecord === true);
|
|
4853
5435
|
const legacy = params.legacyContext ?? null;
|
|
4854
5436
|
const fromRoot = creates ? seedAgentsMdProjectContext(projectDir) : null;
|
|
4855
5437
|
const seed = fromRoot ?? legacy;
|
|
@@ -4867,7 +5449,6 @@ function runAgentsMdTransform(params) {
|
|
|
4867
5449
|
harnessRules: renderRulesBlock(portRules(harnessRoot, params.rules)),
|
|
4868
5450
|
clis
|
|
4869
5451
|
});
|
|
4870
|
-
const diskBefore = exists ? readFileSync9(agentsMdPath, "utf8") : null;
|
|
4871
5452
|
const agentsMd = writeAgentsMd({
|
|
4872
5453
|
projectDir,
|
|
4873
5454
|
rendered,
|
|
@@ -5564,14 +6145,14 @@ function renderHarnessMcp(harnessRoot, choice) {
|
|
|
5564
6145
|
return composeMcpJson({
|
|
5565
6146
|
...mcpSources(harnessRoot),
|
|
5566
6147
|
tracks: choice.spec.tracks,
|
|
5567
|
-
chosen: (
|
|
5568
|
-
dropped: (
|
|
6148
|
+
chosen: (rows2) => selectedMcpServers(rows2, choice),
|
|
6149
|
+
dropped: (rows2) => droppedMcpServers(rows2, choice.excluded)
|
|
5569
6150
|
});
|
|
5570
6151
|
}
|
|
5571
6152
|
function trackDefaultMcpAssetIds(harnessRoot, tracks) {
|
|
5572
|
-
const
|
|
5573
|
-
const selectable = selectableMcpServers(
|
|
5574
|
-
return
|
|
6153
|
+
const rows2 = trackRows(harnessRoot);
|
|
6154
|
+
const selectable = selectableMcpServers(rows2);
|
|
6155
|
+
return rows2.flatMap((r) => {
|
|
5575
6156
|
const id = selectable.get(r.name);
|
|
5576
6157
|
return id !== void 0 && anyTrack(tracks, r.pattern) ? [id] : [];
|
|
5577
6158
|
});
|
|
@@ -5592,13 +6173,13 @@ function renderEverySelectableMcp(harnessRoot, tracks) {
|
|
|
5592
6173
|
return composeMcpJson({
|
|
5593
6174
|
...mcpSources(harnessRoot),
|
|
5594
6175
|
tracks,
|
|
5595
|
-
chosen: (
|
|
6176
|
+
chosen: (rows2) => [...selectableMcpServers(rows2).keys()]
|
|
5596
6177
|
});
|
|
5597
6178
|
}
|
|
5598
6179
|
function adapterExcluded(harnessRoot, excluded) {
|
|
5599
|
-
const
|
|
6180
|
+
const rows2 = trackRows(harnessRoot);
|
|
5600
6181
|
const out = new Set(excluded);
|
|
5601
|
-
for (const [name, assetId] of selectableMcpServers(
|
|
6182
|
+
for (const [name, assetId] of selectableMcpServers(rows2)) {
|
|
5602
6183
|
const id = keyId(".mcp.json", `mcpServers.${name}`);
|
|
5603
6184
|
if (excluded.has(assetId) && id !== null) out.add(id);
|
|
5604
6185
|
}
|
|
@@ -5770,15 +6351,62 @@ function runCliTransforms(params) {
|
|
|
5770
6351
|
externalOutside,
|
|
5771
6352
|
sharedFiles,
|
|
5772
6353
|
portions: sharedFiles.flatMap((r) => r.portions ?? []),
|
|
5773
|
-
|
|
6354
|
+
// #774 (N2) — 블록 모델이던 `AGENTS.md` 를 절 모델로 바꿨으면 그 파일의 몫 기록을 비운다(판정한 경로 · 몫 없음)
|
|
6355
|
+
portionPaths: [
|
|
6356
|
+
...sharedFiles.filter((r) => r.portions !== null).map((r) => r.path),
|
|
6357
|
+
...agentsMd?.agentsMd.blockRecordDropped === true ? ["AGENTS.md"] : []
|
|
6358
|
+
],
|
|
5774
6359
|
restoredFiles
|
|
5775
6360
|
};
|
|
5776
6361
|
}
|
|
5777
6362
|
|
|
6363
|
+
// src/displaced.ts
|
|
6364
|
+
init_esm_shims();
|
|
6365
|
+
import { lstatSync as lstatSync3, mkdirSync as mkdirSync5, renameSync } from "fs";
|
|
6366
|
+
import { dirname as dirname5, join as join23 } from "path";
|
|
6367
|
+
function exists(abs) {
|
|
6368
|
+
try {
|
|
6369
|
+
lstatSync3(abs);
|
|
6370
|
+
return true;
|
|
6371
|
+
} catch {
|
|
6372
|
+
return false;
|
|
6373
|
+
}
|
|
6374
|
+
}
|
|
6375
|
+
function restoreDisplaced(log, projectDir, opts) {
|
|
6376
|
+
const out = [];
|
|
6377
|
+
for (const f of log.rootFiles ?? []) {
|
|
6378
|
+
if (f.change !== "displaced" || !opts.has(f.path)) continue;
|
|
6379
|
+
const slot = join23(projectDir, f.path);
|
|
6380
|
+
if (outsideProjectTarget(projectDir, slot) !== null) continue;
|
|
6381
|
+
const backup = f.notes[0] ?? null;
|
|
6382
|
+
const d2 = judgeDisplaced({
|
|
6383
|
+
backup,
|
|
6384
|
+
backupExists: backup !== null && exists(join23(projectDir, backup)),
|
|
6385
|
+
slotEmpty: !exists(slot) || !opts.write && opts.willBeGone?.has(f.path) === true
|
|
6386
|
+
});
|
|
6387
|
+
if (opts.write && d2.verdict === "restore" && backup !== null) {
|
|
6388
|
+
mkdirSync5(dirname5(slot), { recursive: true });
|
|
6389
|
+
renameSync(join23(projectDir, backup), slot);
|
|
6390
|
+
}
|
|
6391
|
+
out.push({
|
|
6392
|
+
path: f.path,
|
|
6393
|
+
backup,
|
|
6394
|
+
verdict: d2.verdict,
|
|
6395
|
+
line: d2.line,
|
|
6396
|
+
forget: d2.record === "forget"
|
|
6397
|
+
});
|
|
6398
|
+
}
|
|
6399
|
+
return out;
|
|
6400
|
+
}
|
|
6401
|
+
function withoutRestored(rootFiles, outcomes) {
|
|
6402
|
+
const settled = new Set(outcomes.filter((d2) => d2.forget).map((d2) => d2.path));
|
|
6403
|
+
return (rootFiles ?? []).filter((f) => !(f.change === "displaced" && settled.has(f.path)));
|
|
6404
|
+
}
|
|
6405
|
+
|
|
5778
6406
|
// src/excluded-still-there.ts
|
|
5779
6407
|
init_esm_shims();
|
|
5780
6408
|
import { existsSync as existsSync18 } from "fs";
|
|
5781
|
-
import { join as
|
|
6409
|
+
import { join as join24 } from "path";
|
|
5782
6410
|
function excludedStillThere(projectDir, excluded, baselineOnDisk, previousLog) {
|
|
5783
6411
|
const out = [];
|
|
5784
6412
|
const add = (id, catalog) => {
|
|
@@ -5791,7 +6419,7 @@ function excludedStillThere(projectDir, excluded, baselineOnDisk, previousLog) {
|
|
|
5791
6419
|
for (const id of excluded) {
|
|
5792
6420
|
if (INTERNAL_BUNDLED_SKILL_IDS.includes(id)) {
|
|
5793
6421
|
const there = [".claude/skills", ".agents/skills"].some(
|
|
5794
|
-
(d2) => existsSync18(
|
|
6422
|
+
(d2) => existsSync18(join24(projectDir, d2, id))
|
|
5795
6423
|
);
|
|
5796
6424
|
if (there) add(id, false);
|
|
5797
6425
|
} else {
|
|
@@ -5805,17 +6433,27 @@ function excludedStillThere(projectDir, excluded, baselineOnDisk, previousLog) {
|
|
|
5805
6433
|
function assetStillThere(projectDir, asset) {
|
|
5806
6434
|
if (asset.method !== "skill" || asset.scope === "global") return true;
|
|
5807
6435
|
if (asset.files !== void 0)
|
|
5808
|
-
return asset.files.some((f) => existsSync18(
|
|
6436
|
+
return asset.files.some((f) => existsSync18(join24(projectDir, f.path)));
|
|
5809
6437
|
const dir = asset.detail.skill ?? asset.id;
|
|
5810
|
-
return [".claude/skills", ".agents/skills"].some((d2) => existsSync18(
|
|
6438
|
+
return [".claude/skills", ".agents/skills"].some((d2) => existsSync18(join24(projectDir, d2, dir)));
|
|
5811
6439
|
}
|
|
5812
6440
|
|
|
5813
6441
|
// src/external-installer.ts
|
|
5814
6442
|
init_esm_shims();
|
|
5815
6443
|
import { spawnSync } from "child_process";
|
|
5816
|
-
import {
|
|
6444
|
+
import {
|
|
6445
|
+
accessSync,
|
|
6446
|
+
existsSync as existsSync19,
|
|
6447
|
+
constants as fsConstants,
|
|
6448
|
+
mkdirSync as mkdirSync6,
|
|
6449
|
+
readdirSync as readdirSync3,
|
|
6450
|
+
readFileSync as readFileSync17,
|
|
6451
|
+
renameSync as renameSync2,
|
|
6452
|
+
rmdirSync,
|
|
6453
|
+
rmSync as rmSync3
|
|
6454
|
+
} from "fs";
|
|
5817
6455
|
import { homedir as homedir2 } from "os";
|
|
5818
|
-
import { dirname as
|
|
6456
|
+
import { dirname as dirname6, join as join25, relative as relative3, sep as sep4 } from "path";
|
|
5819
6457
|
var SKILL_ROOTS = [".claude/skills", ".agents/skills"];
|
|
5820
6458
|
function skillRootOf(cli) {
|
|
5821
6459
|
return cli === "claude" ? ".claude/skills" : ".agents/skills";
|
|
@@ -5823,11 +6461,11 @@ function skillRootOf(cli) {
|
|
|
5823
6461
|
function snapshotSkillRoots(projectDir) {
|
|
5824
6462
|
const out = /* @__PURE__ */ new Map();
|
|
5825
6463
|
for (const root of SKILL_ROOTS) {
|
|
5826
|
-
if (outsideProjectTarget(projectDir,
|
|
5827
|
-
for (const rel of listFilesRecursive(
|
|
6464
|
+
if (outsideProjectTarget(projectDir, join25(projectDir, root)) !== null) continue;
|
|
6465
|
+
for (const rel of listFilesRecursive(join25(projectDir, root))) {
|
|
5828
6466
|
const path = `${root}/${rel}`;
|
|
5829
6467
|
try {
|
|
5830
|
-
out.set(path, hashContent(readFileSync17(
|
|
6468
|
+
out.set(path, hashContent(readFileSync17(join25(projectDir, path), "utf8")));
|
|
5831
6469
|
} catch {
|
|
5832
6470
|
}
|
|
5833
6471
|
}
|
|
@@ -5904,7 +6542,7 @@ function installOne(asset, ctx) {
|
|
|
5904
6542
|
return runSpawn(asset, ctx.spawn, "npx", buildSkillArgs(method, ctx.cli, ctx.scope), cwd);
|
|
5905
6543
|
}
|
|
5906
6544
|
const outside = SKILL_ROOTS.flatMap((root) => {
|
|
5907
|
-
const hit = outsideProjectTarget(cwd,
|
|
6545
|
+
const hit = outsideProjectTarget(cwd, join25(cwd, root));
|
|
5908
6546
|
return hit === null ? [] : [{ root, target: hit.target }];
|
|
5909
6547
|
});
|
|
5910
6548
|
const outRoots = new Set(outside.map((o) => o.root));
|
|
@@ -5982,32 +6620,46 @@ function refreshExternalSkills(projectDir, deps = {}) {
|
|
|
5982
6620
|
return { ...none, notInCatalog, unknown: false };
|
|
5983
6621
|
}
|
|
5984
6622
|
const targetIds = new Set(targets.map((a) => a.id));
|
|
5985
|
-
const
|
|
5986
|
-
|
|
5987
|
-
log.assets.filter((a) => targetIds.has(a.id))
|
|
5988
|
-
|
|
5989
|
-
|
|
5990
|
-
|
|
5991
|
-
|
|
5992
|
-
|
|
5993
|
-
|
|
5994
|
-
|
|
5995
|
-
|
|
5996
|
-
|
|
5997
|
-
|
|
5998
|
-
|
|
5999
|
-
|
|
6000
|
-
|
|
6001
|
-
|
|
6002
|
-
|
|
6003
|
-
|
|
6004
|
-
|
|
6005
|
-
|
|
6006
|
-
|
|
6623
|
+
const clis = [...installedClis(log)];
|
|
6624
|
+
const settle = holdSkillSlots(projectDir, {
|
|
6625
|
+
recorded: log.assets.filter((a) => targetIds.has(a.id)),
|
|
6626
|
+
slots: skillSlotsFor(targets, clis, { log, scope: log.scope }),
|
|
6627
|
+
log,
|
|
6628
|
+
clis,
|
|
6629
|
+
scope: log.scope
|
|
6630
|
+
});
|
|
6631
|
+
const run = deps.run ?? runExternalInstall;
|
|
6632
|
+
let ran;
|
|
6633
|
+
try {
|
|
6634
|
+
ran = run(
|
|
6635
|
+
{
|
|
6636
|
+
tracks: log.spec.tracks,
|
|
6637
|
+
// `forceInclude` 가 조건 판정을 앞지르므로 옵션 값은 결과에 영향을 주지 않는다.
|
|
6638
|
+
options: DEFAULT_OPTIONS,
|
|
6639
|
+
// #528 — 대상 CLI 는 **깔린 집합**(`installedClis`)이다. `spec.cli` 는 마지막 install 의
|
|
6640
|
+
// 요청이라 `uninstall --cli` 뒤에도 뺀 CLI 를 말하고, 반대로 그걸 비우면 `buildSkillArgs` 가
|
|
6641
|
+
// `--agent`·`--copy` 를 못 붙여 Claude 몫이 조용히 빠진다(재리뷰 BLOCKER-3).
|
|
6642
|
+
cli: clis,
|
|
6643
|
+
userOverride: { forceInclude: [...installedIds], forceExclude: [] },
|
|
6644
|
+
scope: log.scope,
|
|
6645
|
+
projectDir
|
|
6646
|
+
},
|
|
6647
|
+
{
|
|
6648
|
+
assets: targets,
|
|
6649
|
+
...deps.spawn ? { spawn: deps.spawn } : {},
|
|
6650
|
+
...deps.log ? { log: deps.log } : {},
|
|
6651
|
+
...deps.warn ? { warn: deps.warn } : {}
|
|
6652
|
+
}
|
|
6653
|
+
);
|
|
6654
|
+
} catch (e2) {
|
|
6655
|
+
try {
|
|
6656
|
+
settle(null);
|
|
6657
|
+
} catch {
|
|
6007
6658
|
}
|
|
6008
|
-
|
|
6009
|
-
|
|
6010
|
-
|
|
6659
|
+
throw e2;
|
|
6660
|
+
}
|
|
6661
|
+
const { report, displaced } = settle(ran);
|
|
6662
|
+
recordRefreshedFiles(projectDir, log, report, displaced, deps.writeLog ?? writeInstallLog);
|
|
6011
6663
|
return {
|
|
6012
6664
|
attempted: report.attempted.length,
|
|
6013
6665
|
refreshed: report.succeeded,
|
|
@@ -6016,53 +6668,160 @@ function refreshExternalSkills(projectDir, deps = {}) {
|
|
|
6016
6668
|
unknown: false
|
|
6017
6669
|
};
|
|
6018
6670
|
}
|
|
6019
|
-
function holdSkillSlots(projectDir,
|
|
6020
|
-
const
|
|
6021
|
-
|
|
6671
|
+
function holdSkillSlots(projectDir, hold) {
|
|
6672
|
+
const now = /* @__PURE__ */ new Date();
|
|
6673
|
+
const asides = /* @__PURE__ */ new Map();
|
|
6674
|
+
const moved = [];
|
|
6675
|
+
try {
|
|
6676
|
+
for (const f of slotFilesToKeep(projectDir, hold)) {
|
|
6677
|
+
const root = dirname6(f.slot);
|
|
6678
|
+
let dir = asides.get(root);
|
|
6679
|
+
if (dir === void 0) {
|
|
6680
|
+
dir = claimBackupDir(join25(projectDir, root), now);
|
|
6681
|
+
asides.set(root, dir);
|
|
6682
|
+
}
|
|
6683
|
+
const aside = join25(dir, f.rel.slice(root.length + 1));
|
|
6684
|
+
mkdirSync6(dirname6(aside), { recursive: true });
|
|
6685
|
+
renameSync2(f.abs, aside);
|
|
6686
|
+
moved.push({ ...f, aside });
|
|
6687
|
+
}
|
|
6688
|
+
} catch (e2) {
|
|
6689
|
+
for (const f of moved) renameSync2(f.aside, f.abs);
|
|
6690
|
+
for (const dir of asides.values()) pruneEmptyDirs(dir);
|
|
6691
|
+
throw new Error(
|
|
6692
|
+
`could not move your files aside before the skill tool runs \u2014 nothing was changed: ${e2 instanceof Error ? e2.message : String(e2)}`
|
|
6693
|
+
);
|
|
6694
|
+
}
|
|
6695
|
+
return (report) => {
|
|
6696
|
+
const failedSlots = report === null ? null : skillSlotsFor(
|
|
6697
|
+
report.attempted.filter((r) => !r.ok).map((r) => r.asset),
|
|
6698
|
+
hold.clis,
|
|
6699
|
+
{ log: hold.log, scope: hold.scope }
|
|
6700
|
+
);
|
|
6701
|
+
const out = { backups: [], displaced: [] };
|
|
6702
|
+
const back = /* @__PURE__ */ new Set();
|
|
6703
|
+
const failed = [];
|
|
6704
|
+
for (const f of moved) {
|
|
6705
|
+
const restore = failedSlots === null || failedSlots.some((s) => f.rel === s || f.rel.startsWith(`${s}/`));
|
|
6706
|
+
try {
|
|
6707
|
+
const r = settleAside(projectDir, f, restore);
|
|
6708
|
+
if (r === "back") {
|
|
6709
|
+
back.add(f.rel);
|
|
6710
|
+
continue;
|
|
6711
|
+
}
|
|
6712
|
+
out.backups.push(r.backup);
|
|
6713
|
+
if (r.displaced !== null) out.displaced.push(r.displaced);
|
|
6714
|
+
} catch (e2) {
|
|
6715
|
+
failed.push(`${f.rel} (${e2 instanceof Error ? e2.message : String(e2)})`);
|
|
6716
|
+
}
|
|
6717
|
+
}
|
|
6718
|
+
for (const dir of asides.values()) pruneEmptyDirs(dir);
|
|
6719
|
+
if (failed.length > 0) {
|
|
6720
|
+
const at5 = [...asides.values()].map((d2) => `${toProjectRel(projectDir, d2)}/`).join(", ");
|
|
6721
|
+
throw new Error(
|
|
6722
|
+
`could not put back ${failed.length} file(s) moved aside before the skill tool ran \u2014 they stay in ${at5}: ${failed.join(", ")}`
|
|
6723
|
+
);
|
|
6724
|
+
}
|
|
6725
|
+
return { ...out, report: report === null ? null : withoutCreated(report, back) };
|
|
6726
|
+
};
|
|
6022
6727
|
}
|
|
6023
|
-
function
|
|
6024
|
-
if (
|
|
6025
|
-
const
|
|
6026
|
-
const
|
|
6728
|
+
function skillSlotsFor(assets, clis, ctx) {
|
|
6729
|
+
if (resolveScope(ctx.scope) === "global") return [];
|
|
6730
|
+
const roots = clis.length === 0 ? [...SKILL_ROOTS] : [...new Set(clis.map(skillRootOf))];
|
|
6731
|
+
const out = /* @__PURE__ */ new Set();
|
|
6732
|
+
for (const a of assets) {
|
|
6733
|
+
if (a.method.kind !== "skill") continue;
|
|
6734
|
+
const prior = ctx.log?.assets.find((r) => r.id === a.id);
|
|
6735
|
+
if (prior !== void 0 && prior.files === void 0) continue;
|
|
6736
|
+
const skill = a.method.skill;
|
|
6737
|
+
for (const root of roots) out.add(skill === void 0 ? root : `${root}/${skill}`);
|
|
6738
|
+
}
|
|
6739
|
+
return [...out];
|
|
6740
|
+
}
|
|
6741
|
+
function slotFilesToKeep(projectDir, hold) {
|
|
6742
|
+
const mine = hold.recorded.flatMap((a) => a.files ?? []);
|
|
6743
|
+
const sha = new Map(mine.map((f) => [f.path, f.sha256]));
|
|
6744
|
+
const targetIds = new Set(hold.recorded.map((a) => a.id));
|
|
6745
|
+
const others = new Set(
|
|
6746
|
+
(hold.log?.assets ?? []).filter((a) => !targetIds.has(a.id)).flatMap((a) => (a.files ?? []).map((f) => f.path))
|
|
6747
|
+
);
|
|
6748
|
+
const slots = /* @__PURE__ */ new Set([
|
|
6749
|
+
...mine.map((f) => f.path.split("/").slice(0, 3).join("/")),
|
|
6750
|
+
...hold.slots
|
|
6751
|
+
]);
|
|
6027
6752
|
const out = [];
|
|
6753
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6028
6754
|
for (const slot of slots) {
|
|
6029
|
-
if (outsideProjectTarget(projectDir,
|
|
6030
|
-
for (const rel of listFilesRecursive(
|
|
6755
|
+
if (outsideProjectTarget(projectDir, join25(projectDir, slot)) !== null) continue;
|
|
6756
|
+
for (const rel of listFilesRecursive(join25(projectDir, slot))) {
|
|
6031
6757
|
const path = `${slot}/${rel}`;
|
|
6032
|
-
|
|
6033
|
-
|
|
6758
|
+
if (seen.has(path)) continue;
|
|
6759
|
+
seen.add(path);
|
|
6760
|
+
const recordedSha = sha.get(path);
|
|
6761
|
+
if (recordedSha === void 0 && (others.has(path) || recorded(hold.log, path).state !== "none"))
|
|
6762
|
+
continue;
|
|
6763
|
+
const abs = join25(projectDir, path);
|
|
6034
6764
|
try {
|
|
6035
|
-
|
|
6765
|
+
if (recordedSha !== void 0 && hashContent(readFileSync17(abs, "utf8")) === recordedSha)
|
|
6766
|
+
continue;
|
|
6767
|
+
accessSync(abs, fsConstants.R_OK);
|
|
6036
6768
|
} catch {
|
|
6037
6769
|
continue;
|
|
6038
6770
|
}
|
|
6039
|
-
|
|
6040
|
-
if (recordedSha === void 0) out.push({ abs, content, recorded: false });
|
|
6041
|
-
else if (hashContent(content.toString("utf8")) !== recordedSha)
|
|
6042
|
-
out.push({ abs, content, recorded: true });
|
|
6771
|
+
out.push({ abs, rel: path, slot, recorded: recordedSha !== void 0 });
|
|
6043
6772
|
}
|
|
6044
6773
|
}
|
|
6045
6774
|
return out;
|
|
6046
6775
|
}
|
|
6047
|
-
function
|
|
6776
|
+
function settleAside(projectDir, f, restore) {
|
|
6048
6777
|
let now = null;
|
|
6049
6778
|
try {
|
|
6050
|
-
now = readFileSync17(
|
|
6051
|
-
} catch {
|
|
6779
|
+
now = readFileSync17(f.abs);
|
|
6780
|
+
} catch (e2) {
|
|
6781
|
+
const code = e2.code;
|
|
6782
|
+
if (code !== "ENOENT" && code !== "ENOTDIR") throw e2;
|
|
6052
6783
|
}
|
|
6053
|
-
if (now
|
|
6054
|
-
|
|
6055
|
-
|
|
6056
|
-
|
|
6057
|
-
|
|
6784
|
+
if (restore || (now === null ? !f.recorded : now.equals(readFileSync17(f.aside)))) {
|
|
6785
|
+
mkdirSync6(dirname6(f.abs), { recursive: true });
|
|
6786
|
+
renameSync2(f.aside, f.abs);
|
|
6787
|
+
return "back";
|
|
6788
|
+
}
|
|
6789
|
+
const backup = backupFromCopy(f.abs, f.aside);
|
|
6790
|
+
rmSync3(f.aside, { force: true });
|
|
6791
|
+
if (f.recorded || now === null) return { backup, displaced: null };
|
|
6792
|
+
return {
|
|
6793
|
+
backup,
|
|
6794
|
+
displaced: { path: f.rel, change: "displaced", notes: [toProjectRel(projectDir, backup)] }
|
|
6795
|
+
};
|
|
6796
|
+
}
|
|
6797
|
+
function withoutCreated(report, paths) {
|
|
6798
|
+
if (paths.size === 0) return report;
|
|
6799
|
+
return {
|
|
6800
|
+
...report,
|
|
6801
|
+
attempted: report.attempted.map(
|
|
6802
|
+
(r) => r.files === void 0 ? r : {
|
|
6803
|
+
...r,
|
|
6804
|
+
files: { ...r.files, created: r.files.created.filter((x) => !paths.has(x.path)) }
|
|
6805
|
+
}
|
|
6806
|
+
)
|
|
6807
|
+
};
|
|
6808
|
+
}
|
|
6809
|
+
function pruneEmptyDirs(dir) {
|
|
6810
|
+
try {
|
|
6811
|
+
for (const e2 of readdirSync3(dir, { withFileTypes: true }))
|
|
6812
|
+
if (e2.isDirectory()) pruneEmptyDirs(join25(dir, e2.name));
|
|
6813
|
+
rmdirSync(dir);
|
|
6814
|
+
} catch {
|
|
6058
6815
|
}
|
|
6059
|
-
return backupContent(h2.abs, h2.content);
|
|
6060
6816
|
}
|
|
6061
|
-
function
|
|
6817
|
+
function toProjectRel(projectDir, abs) {
|
|
6818
|
+
return relative3(projectDir, abs).split(sep4).join("/");
|
|
6819
|
+
}
|
|
6820
|
+
function recordRefreshedFiles(projectDir, log, report, displaced, writeLog) {
|
|
6062
6821
|
const next = new Map(
|
|
6063
6822
|
buildAssetEntries(report, log.scope, log.assets).filter((e2) => e2.files !== void 0).map((e2) => [e2.id, e2.files])
|
|
6064
6823
|
);
|
|
6065
|
-
let changed =
|
|
6824
|
+
let changed = displaced.length > 0;
|
|
6066
6825
|
const assets = log.assets.map((a) => {
|
|
6067
6826
|
const files = next.get(a.id);
|
|
6068
6827
|
if (files === void 0 || JSON.stringify(files) === JSON.stringify(a.files)) return a;
|
|
@@ -6071,7 +6830,11 @@ function recordRefreshedFiles(projectDir, log, report, writeLog) {
|
|
|
6071
6830
|
});
|
|
6072
6831
|
if (!changed) return;
|
|
6073
6832
|
try {
|
|
6074
|
-
writeLog(projectDir, {
|
|
6833
|
+
writeLog(projectDir, {
|
|
6834
|
+
...log,
|
|
6835
|
+
assets,
|
|
6836
|
+
...displaced.length > 0 ? { rootFiles: mergeRootFiles(log.rootFiles, displaced) } : {}
|
|
6837
|
+
});
|
|
6075
6838
|
} catch {
|
|
6076
6839
|
}
|
|
6077
6840
|
}
|
|
@@ -6151,7 +6914,7 @@ function detectVersion(method, spawn, scope, projectDir) {
|
|
|
6151
6914
|
case "plugin":
|
|
6152
6915
|
return detectPluginVersion(method.pluginId, scope, projectDir);
|
|
6153
6916
|
case "npm": {
|
|
6154
|
-
const pkgJson = scope === "global" ? detectGlobalNpmPackageJsonPath(method.pkg, spawn) :
|
|
6917
|
+
const pkgJson = scope === "global" ? detectGlobalNpmPackageJsonPath(method.pkg, spawn) : join25(projectDir, "node_modules", method.pkg, "package.json");
|
|
6155
6918
|
if (!pkgJson || !existsSync19(pkgJson)) return void 0;
|
|
6156
6919
|
const parsed = JSON.parse(readFileSync17(pkgJson, "utf8"));
|
|
6157
6920
|
return parsed.version;
|
|
@@ -6165,7 +6928,7 @@ function detectVersion(method, spawn, scope, projectDir) {
|
|
|
6165
6928
|
}
|
|
6166
6929
|
function detectPluginVersion(pluginId, scope, projectDir) {
|
|
6167
6930
|
const claudeScope = scope === "global" ? "user" : "project";
|
|
6168
|
-
const path =
|
|
6931
|
+
const path = join25(homedir2(), ".claude/plugins/installed_plugins.json");
|
|
6169
6932
|
if (!existsSync19(path)) return void 0;
|
|
6170
6933
|
const data = JSON.parse(readFileSync17(path, "utf8"));
|
|
6171
6934
|
const entries = data.plugins?.[pluginId] ?? [];
|
|
@@ -6180,7 +6943,7 @@ function detectPluginVersion(pluginId, scope, projectDir) {
|
|
|
6180
6943
|
}
|
|
6181
6944
|
function detectGlobalNpmPackageJsonPath(pkg, spawn) {
|
|
6182
6945
|
const npmRoot = getNpmGlobalRoot(spawn);
|
|
6183
|
-
return npmRoot ?
|
|
6946
|
+
return npmRoot ? join25(npmRoot, pkg, "package.json") : void 0;
|
|
6184
6947
|
}
|
|
6185
6948
|
var npmGlobalRootCache;
|
|
6186
6949
|
function getNpmGlobalRoot(spawn) {
|
|
@@ -6200,7 +6963,7 @@ function getNpmGlobalRoot(spawn) {
|
|
|
6200
6963
|
// src/key-ids.ts
|
|
6201
6964
|
init_esm_shims();
|
|
6202
6965
|
import { readFileSync as readFileSync18 } from "fs";
|
|
6203
|
-
import { join as
|
|
6966
|
+
import { join as join26 } from "path";
|
|
6204
6967
|
function renderedKeyIds(harnessRoot, input, clis) {
|
|
6205
6968
|
const out = /* @__PURE__ */ new Set();
|
|
6206
6969
|
const add = (path, key) => {
|
|
@@ -6223,7 +6986,7 @@ function renderedKeyIds(harnessRoot, input, clis) {
|
|
|
6223
6986
|
for (const name of Object.keys(mcp.mcpServers)) add(".mcp.json", `mcpServers.${name}`);
|
|
6224
6987
|
for (const key of gitignoreRender().keys()) add(".gitignore", key);
|
|
6225
6988
|
if (clis.includes("claude")) {
|
|
6226
|
-
const template = readFileSync18(
|
|
6989
|
+
const template = readFileSync18(join26(harnessRoot, "templates/settings.json"), "utf8");
|
|
6227
6990
|
for (const key of renderSettingsPortion(template, () => true).keys()) {
|
|
6228
6991
|
add(".claude/settings.json", key);
|
|
6229
6992
|
}
|
|
@@ -6264,7 +7027,7 @@ function withoutAccepts(harnessRoot, spec, previous) {
|
|
|
6264
7027
|
|
|
6265
7028
|
// src/linked-skill-bodies.ts
|
|
6266
7029
|
init_esm_shims();
|
|
6267
|
-
import { join as
|
|
7030
|
+
import { join as join27 } from "path";
|
|
6268
7031
|
function refreshLinkedSkillBodies(params) {
|
|
6269
7032
|
const { harnessRoot, projectDir, ids, baseline, journal } = params;
|
|
6270
7033
|
const bodyKey = (id) => `.agents/skills/${id}/SKILL.md`;
|
|
@@ -6275,7 +7038,7 @@ function refreshLinkedSkillBodies(params) {
|
|
|
6275
7038
|
);
|
|
6276
7039
|
const result = writer.result();
|
|
6277
7040
|
return {
|
|
6278
|
-
updated: ours.filter((id) => written.has(
|
|
7041
|
+
updated: ours.filter((id) => written.has(join27(projectDir, bodyKey(id)))),
|
|
6279
7042
|
notOurs: ids.filter((id) => !baseline.has(bodyKey(id))),
|
|
6280
7043
|
files: result.files,
|
|
6281
7044
|
backupPaths: result.backupPaths,
|
|
@@ -6287,8 +7050,8 @@ function refreshLinkedSkillBodies(params) {
|
|
|
6287
7050
|
|
|
6288
7051
|
// src/out-of-track.ts
|
|
6289
7052
|
init_esm_shims();
|
|
6290
|
-
import { lstatSync as
|
|
6291
|
-
import { join as
|
|
7053
|
+
import { lstatSync as lstatSync4, readFileSync as readFileSync19, rmSync as rmSync4 } from "fs";
|
|
7054
|
+
import { join as join28 } from "path";
|
|
6292
7055
|
var AGENTS_RULE = /^\.agents\/rules\/([^/]+)\.md$/;
|
|
6293
7056
|
var ANCHOR_RULE = "uzys-harness";
|
|
6294
7057
|
function reclaimOutOfTrack(args) {
|
|
@@ -6308,9 +7071,9 @@ function reclaimOutOfTrack(args) {
|
|
|
6308
7071
|
const name = AGENTS_RULE.exec(f.path)?.[1];
|
|
6309
7072
|
if (name === void 0 || name === ANCHOR_RULE || rendered.has(name)) continue;
|
|
6310
7073
|
if (isBaselineExcluded(`.claude/rules/${name}.md`, args.excluded)) continue;
|
|
6311
|
-
const abs =
|
|
7074
|
+
const abs = join28(projectDir, f.path);
|
|
6312
7075
|
if (args.outside.skip(abs)) continue;
|
|
6313
|
-
const stat =
|
|
7076
|
+
const stat = lstatSync4(abs, { throwIfNoEntry: false });
|
|
6314
7077
|
if (stat !== void 0 && !stat.isFile()) continue;
|
|
6315
7078
|
if (stat !== void 0 && claudeCopy.has(`rules/${name}.md`)) {
|
|
6316
7079
|
out.kept.push(f.path);
|
|
@@ -6330,11 +7093,11 @@ function reclaimOutOfTrack(args) {
|
|
|
6330
7093
|
out.bringBack[f.path] = tracksBringing(name);
|
|
6331
7094
|
}
|
|
6332
7095
|
if (verdict.verdict === "remove") {
|
|
6333
|
-
|
|
7096
|
+
rmSync4(abs);
|
|
6334
7097
|
out.removed.push(f.path);
|
|
6335
7098
|
} else if (verdict.verdict === "backup+remove") {
|
|
6336
7099
|
const backup = backupFile(abs, args.now);
|
|
6337
|
-
|
|
7100
|
+
rmSync4(abs);
|
|
6338
7101
|
out.backedUp.push({ path: f.path, backup });
|
|
6339
7102
|
}
|
|
6340
7103
|
}
|
|
@@ -6350,14 +7113,14 @@ function tracksBringing(rule) {
|
|
|
6350
7113
|
// src/state.ts
|
|
6351
7114
|
init_esm_shims();
|
|
6352
7115
|
import { existsSync as existsSync20, readFileSync as readFileSync20 } from "fs";
|
|
6353
|
-
import { join as
|
|
7116
|
+
import { join as join29 } from "path";
|
|
6354
7117
|
var META_FILE = ".claude/.installed-tracks";
|
|
6355
7118
|
var LEGACY_ANCHOR_FILE = ".claude/CLAUDE.md";
|
|
6356
7119
|
var TRACE_RULES = ["htmx", "nextjs", "data-analysis", "pyside6", "cli-development"].map(
|
|
6357
7120
|
(r) => `.claude/rules/${r}.md`
|
|
6358
7121
|
);
|
|
6359
7122
|
function detectInstallState(projectDir) {
|
|
6360
|
-
const hasClaudeDir = existsSync20(
|
|
7123
|
+
const hasClaudeDir = existsSync20(join29(projectDir, ".claude"));
|
|
6361
7124
|
const read = readInstallLogStatus(projectDir);
|
|
6362
7125
|
if (read.status === "ok") {
|
|
6363
7126
|
return {
|
|
@@ -6377,7 +7140,7 @@ function tracksFromLog(tracks) {
|
|
|
6377
7140
|
return [...new Set(tracks.filter(isTrack))].sort();
|
|
6378
7141
|
}
|
|
6379
7142
|
function collectTraces(projectDir) {
|
|
6380
|
-
const at5 = (rel) =>
|
|
7143
|
+
const at5 = (rel) => join29(projectDir, rel);
|
|
6381
7144
|
const contains = (rel, needle) => existsSync20(at5(rel)) && readFileSync20(at5(rel), "utf8").includes(needle);
|
|
6382
7145
|
const traces = [];
|
|
6383
7146
|
if (existsSync20(at5(META_FILE)))
|
|
@@ -6437,16 +7200,16 @@ init_esm_shims();
|
|
|
6437
7200
|
import {
|
|
6438
7201
|
copyFileSync,
|
|
6439
7202
|
existsSync as existsSync21,
|
|
6440
|
-
lstatSync as
|
|
6441
|
-
mkdirSync as
|
|
6442
|
-
readdirSync as
|
|
7203
|
+
lstatSync as lstatSync5,
|
|
7204
|
+
mkdirSync as mkdirSync7,
|
|
7205
|
+
readdirSync as readdirSync4,
|
|
6443
7206
|
readFileSync as readFileSync21,
|
|
6444
|
-
rmdirSync,
|
|
7207
|
+
rmdirSync as rmdirSync2,
|
|
6445
7208
|
statSync as statSync4,
|
|
6446
7209
|
unlinkSync as unlinkSync2,
|
|
6447
|
-
writeFileSync as
|
|
7210
|
+
writeFileSync as writeFileSync7
|
|
6448
7211
|
} from "fs";
|
|
6449
|
-
import { basename as basename3, dirname as
|
|
7212
|
+
import { basename as basename3, dirname as dirname7, join as join30 } from "path";
|
|
6450
7213
|
var LEGACY_ANCHOR_FILE2 = ".claude/CLAUDE.md";
|
|
6451
7214
|
function buildUpdateSpec(projectDir, tracks, only) {
|
|
6452
7215
|
const log = readInstallLog(projectDir);
|
|
@@ -6468,7 +7231,7 @@ function parseUpdateOnly(raw) {
|
|
|
6468
7231
|
return { ok: true, groups: [...new Set(raw)] };
|
|
6469
7232
|
}
|
|
6470
7233
|
function runUpdateMode(projectDir, templatesDir, harnessRoot, deps = {}, only) {
|
|
6471
|
-
const claudeDir =
|
|
7234
|
+
const claudeDir = join30(projectDir, ".claude");
|
|
6472
7235
|
const startedAt = Date.now();
|
|
6473
7236
|
const backupsAtStart = new Set(
|
|
6474
7237
|
collectRunBackups(projectDir, Number.NEGATIVE_INFINITY).map((b2) => b2.backup)
|
|
@@ -6514,10 +7277,11 @@ function runUpdateMode(projectDir, templatesDir, harnessRoot, deps = {}, only) {
|
|
|
6514
7277
|
const claudeDisplaced = [];
|
|
6515
7278
|
report.claudeUnrecorded = !claudeManaged && logAtStart !== null && existsSync21(claudeDir) ? recordClaudeCommand(logAtStart, installedTracks(projectDir)) : null;
|
|
6516
7279
|
const policyBase = policyBaseline(projectDir);
|
|
7280
|
+
const prunedPaths = /* @__PURE__ */ new Set();
|
|
6517
7281
|
for (const { dir, ext } of POLICY_DIRS) {
|
|
6518
7282
|
if (!claudeManaged || !wants(dir === "hooks" ? "hooks" : "rules")) continue;
|
|
6519
|
-
const target =
|
|
6520
|
-
const source =
|
|
7283
|
+
const target = join30(claudeDir, dir);
|
|
7284
|
+
const source = join30(templatesDir, dir);
|
|
6521
7285
|
const label = `.claude/${dir}`;
|
|
6522
7286
|
const ctx = {
|
|
6523
7287
|
prefix: dir,
|
|
@@ -6533,6 +7297,7 @@ function runUpdateMode(projectDir, templatesDir, harnessRoot, deps = {}, only) {
|
|
|
6533
7297
|
report.policyBackedUp.push(...synced.backedUp);
|
|
6534
7298
|
claudeDisplaced.push(...synced.displaced);
|
|
6535
7299
|
report.pruned[label] = pruneOrphans(target, source, ext, ctx);
|
|
7300
|
+
for (const f of report.pruned[label]) prunedPaths.add(`${label}/${f}`);
|
|
6536
7301
|
}
|
|
6537
7302
|
const syncedDirs = POLICY_DIRS.filter((d2) => wants(d2.dir === "hooks" ? "hooks" : "rules")).map(
|
|
6538
7303
|
(d2) => d2.dir
|
|
@@ -6545,10 +7310,11 @@ function runUpdateMode(projectDir, templatesDir, harnessRoot, deps = {}, only) {
|
|
|
6545
7310
|
outsidePaths(outside, ".claude/"),
|
|
6546
7311
|
notOursUnder(claudeDisplaced, ".claude/")
|
|
6547
7312
|
);
|
|
7313
|
+
const prunedRestored = logAtStart === null || prunedPaths.size === 0 ? [] : restoreDisplaced(logAtStart, projectDir, { has: (p2) => prunedPaths.has(p2), write: true });
|
|
6548
7314
|
const skillTargets = logAtStart === null ? void 0 : recordedSkillIds(projectDir, logAtStart);
|
|
6549
7315
|
const skillSync = claudeManaged && wants("skills") ? syncSkills(
|
|
6550
|
-
|
|
6551
|
-
|
|
7316
|
+
join30(claudeDir, "skills"),
|
|
7317
|
+
join30(templatesDir, "skills"),
|
|
6552
7318
|
skillBaseline(projectDir),
|
|
6553
7319
|
/* @__PURE__ */ new Date(),
|
|
6554
7320
|
(relInSkills) => foreignOwnedTarget(projectDir, `.claude/skills/${relInSkills}`),
|
|
@@ -6585,7 +7351,8 @@ function runUpdateMode(projectDir, templatesDir, harnessRoot, deps = {}, only) {
|
|
|
6585
7351
|
);
|
|
6586
7352
|
else if (claudeManaged && copiedSkills.length > 0)
|
|
6587
7353
|
recordNewSkillBaseline(projectDir, templatesDir, copiedSkills);
|
|
6588
|
-
if (claudeDisplaced.length > 0
|
|
7354
|
+
if (claudeDisplaced.length > 0 || prunedRestored.length > 0)
|
|
7355
|
+
recordDisplaced(projectDir, claudeDisplaced, prunedRestored);
|
|
6589
7356
|
if (existsSync21(claudeDir) && claudeManaged) {
|
|
6590
7357
|
if (wants("anchor")) syncHarnessAnchor(projectDir, templatesDir, report, outside);
|
|
6591
7358
|
}
|
|
@@ -6605,7 +7372,7 @@ function runUpdateMode(projectDir, templatesDir, harnessRoot, deps = {}, only) {
|
|
|
6605
7372
|
droppedKeys: legacyDroppedKeys(logAtStart),
|
|
6606
7373
|
harnessMcp
|
|
6607
7374
|
});
|
|
6608
|
-
const settingsPath =
|
|
7375
|
+
const settingsPath = join30(claudeDir, "settings.json");
|
|
6609
7376
|
if (claudeManaged && wants("hooks") && existsSync21(settingsPath) && !outside.skip(settingsPath)) {
|
|
6610
7377
|
report.retiredHookRefsRemoved = removeRetiredHookRefs(
|
|
6611
7378
|
settingsPath,
|
|
@@ -6638,18 +7405,31 @@ function runUpdateMode(projectDir, templatesDir, harnessRoot, deps = {}, only) {
|
|
|
6638
7405
|
restoredFiles: [],
|
|
6639
7406
|
legacyRestored: [],
|
|
6640
7407
|
anchorRetired: null,
|
|
7408
|
+
anchorDisplaced: [],
|
|
6641
7409
|
agentsMd: null,
|
|
7410
|
+
agentsMdLegacyDropped: 0,
|
|
7411
|
+
agentsMdLegacyEdited: [],
|
|
6642
7412
|
excludedKeys: [],
|
|
6643
7413
|
sharedLeft: []
|
|
6644
7414
|
};
|
|
7415
|
+
const outOfTrackRestored = [];
|
|
6645
7416
|
if (wants("external")) {
|
|
6646
|
-
const outOfTrack = reclaimOutOfTrackRecorded(projectDir, outside);
|
|
7417
|
+
const { reclaim: outOfTrack, displaced } = reclaimOutOfTrackRecorded(projectDir, outside);
|
|
6647
7418
|
if (outOfTrack.removed.length + outOfTrack.backedUp.length + outOfTrack.kept.length > 0)
|
|
6648
7419
|
report.outOfTrack = outOfTrack;
|
|
7420
|
+
outOfTrackRestored.push(...displaced);
|
|
6649
7421
|
}
|
|
7422
|
+
const displacedRestored = [...prunedRestored, ...external.anchorDisplaced, ...outOfTrackRestored];
|
|
7423
|
+
if (displacedRestored.length > 0) report.displacedRestored = displacedRestored;
|
|
6650
7424
|
report.externalUpdated = external.externalUpdated;
|
|
6651
7425
|
if (external.anchorRetired !== null) report.anchorRetired = external.anchorRetired;
|
|
6652
7426
|
if (external.agentsMd !== null) report.agentsMd = external.agentsMd;
|
|
7427
|
+
if (external.agentsMdLegacyDropped > 0) {
|
|
7428
|
+
report.agentsMdLegacyDropped = external.agentsMdLegacyDropped;
|
|
7429
|
+
}
|
|
7430
|
+
if (external.agentsMdLegacyEdited.length > 0) {
|
|
7431
|
+
report.agentsMdLegacyEdited = external.agentsMdLegacyEdited;
|
|
7432
|
+
}
|
|
6653
7433
|
if (external.sharedLeft.length > 0) report.sharedLeft = external.sharedLeft;
|
|
6654
7434
|
report.restoredKeys = external.restoredKeys;
|
|
6655
7435
|
report.restoredFiles = external.restoredFiles;
|
|
@@ -6788,18 +7568,21 @@ function reclaimOutOfTrackRecorded(projectDir, outside) {
|
|
|
6788
7568
|
excluded: excludedIds(log),
|
|
6789
7569
|
outside
|
|
6790
7570
|
});
|
|
7571
|
+
const left = /* @__PURE__ */ new Set([...result.removed, ...result.backedUp.map((b2) => b2.path)]);
|
|
7572
|
+
const displaced = log === null || left.size === 0 ? [] : restoreDisplaced(log, projectDir, { has: (p2) => left.has(p2), write: true });
|
|
6791
7573
|
if (log !== null && result.forget.length > 0) {
|
|
6792
7574
|
const forget = new Set(result.forget);
|
|
6793
7575
|
const next = { ...log };
|
|
6794
7576
|
const kept = (log.externalFiles ?? []).filter((f) => !forget.has(f.path));
|
|
6795
7577
|
if (kept.length > 0) next.externalFiles = kept;
|
|
6796
7578
|
else delete next.externalFiles;
|
|
7579
|
+
if (displaced.some((d2) => d2.forget)) next.rootFiles = withoutRestored(log.rootFiles, displaced);
|
|
6797
7580
|
try {
|
|
6798
7581
|
writeInstallLog(projectDir, next);
|
|
6799
7582
|
} catch {
|
|
6800
7583
|
}
|
|
6801
7584
|
}
|
|
6802
|
-
return result;
|
|
7585
|
+
return { reclaim: result, displaced };
|
|
6803
7586
|
}
|
|
6804
7587
|
function checksumOnRecord(log) {
|
|
6805
7588
|
if (log === null) return () => false;
|
|
@@ -6820,7 +7603,7 @@ function retiredFeaturesPart(projectDir, f) {
|
|
|
6820
7603
|
}
|
|
6821
7604
|
function legacyHookOnDisk(projectDir, rel) {
|
|
6822
7605
|
try {
|
|
6823
|
-
return hasLegacyHarnessHook(readFileSync21(
|
|
7606
|
+
return hasLegacyHarnessHook(readFileSync21(join30(projectDir, rel), "utf8"));
|
|
6824
7607
|
} catch {
|
|
6825
7608
|
return false;
|
|
6826
7609
|
}
|
|
@@ -6846,7 +7629,7 @@ function writeUpdateSharedFiles(args) {
|
|
|
6846
7629
|
excluded: adapterExcluded(harnessRoot, excluded)
|
|
6847
7630
|
});
|
|
6848
7631
|
const tracks = installedTracks(projectDir);
|
|
6849
|
-
const settingsSource =
|
|
7632
|
+
const settingsSource = join30(templatesDir, "settings.json");
|
|
6850
7633
|
if (args.claudeManaged && wants("hooks") && existsSync21(settingsSource)) {
|
|
6851
7634
|
const spec = buildAssetSpec({ tracks, options: DEFAULT_OPTIONS });
|
|
6852
7635
|
const manifest = buildManifest(spec);
|
|
@@ -6857,7 +7640,7 @@ function writeUpdateSharedFiles(args) {
|
|
|
6857
7640
|
log,
|
|
6858
7641
|
(script) => {
|
|
6859
7642
|
const target = `.claude/hooks/${script}`;
|
|
6860
|
-
return manifest.some((e2) => e2.target === target && e2.applies(spec)) && !isBaselineExcluded(target, excluded) && existsSync21(
|
|
7643
|
+
return manifest.some((e2) => e2.target === target && e2.applies(spec)) && !isBaselineExcluded(target, excluded) && existsSync21(join30(projectDir, target));
|
|
6861
7644
|
}
|
|
6862
7645
|
// 기록이 claude 를 깔린 CLI 로 말한다 = install 이 이 파일을 썼다 — 없으면 만든다(훅 배선이 여기 산다)
|
|
6863
7646
|
);
|
|
@@ -6921,30 +7704,30 @@ function catalogRemovedOnRecord(log) {
|
|
|
6921
7704
|
}
|
|
6922
7705
|
function staleSkillDirs(projectDir, claudeDir, clis) {
|
|
6923
7706
|
const stale = (id) => RENAMED_SKILL_IDS[id] !== void 0 || RETIRED_SKILL_IDS.includes(id);
|
|
6924
|
-
const dirs = [
|
|
6925
|
-
if (clis.some((cli) => cli !== "claude")) dirs.push(
|
|
7707
|
+
const dirs = [join30(claudeDir, "skills")];
|
|
7708
|
+
if (clis.some((cli) => cli !== "claude")) dirs.push(join30(projectDir, ".agents", "skills"));
|
|
6926
7709
|
const ids = /* @__PURE__ */ new Set();
|
|
6927
7710
|
for (const dir of dirs) {
|
|
6928
7711
|
if (!existsSync21(dir)) continue;
|
|
6929
|
-
for (const e2 of
|
|
7712
|
+
for (const e2 of readdirSync4(dir, { withFileTypes: true })) {
|
|
6930
7713
|
if (e2.isDirectory() && stale(e2.name)) ids.add(e2.name);
|
|
6931
7714
|
}
|
|
6932
7715
|
}
|
|
6933
7716
|
return [...ids];
|
|
6934
7717
|
}
|
|
6935
7718
|
function staleAgentFiles(claudeDir) {
|
|
6936
|
-
const dir =
|
|
7719
|
+
const dir = join30(claudeDir, "agents");
|
|
6937
7720
|
if (!existsSync21(dir)) return [];
|
|
6938
|
-
return
|
|
7721
|
+
return readdirSync4(dir, { withFileTypes: true }).filter((e2) => e2.isFile() && e2.name.endsWith(".md")).map((e2) => basename3(e2.name, ".md")).filter((id) => RETIRED_AGENT_IDS.includes(id));
|
|
6939
7722
|
}
|
|
6940
7723
|
function demotedAgentFiles(claudeDir, tracks) {
|
|
6941
7724
|
if (tracks.length === 0) return [];
|
|
6942
|
-
const dir =
|
|
7725
|
+
const dir = join30(claudeDir, "agents");
|
|
6943
7726
|
if (!existsSync21(dir)) return [];
|
|
6944
7727
|
const demoted = TRACK_AGENTS.filter(([, pattern]) => !anyTrack(tracks, pattern)).map(
|
|
6945
7728
|
([id]) => id
|
|
6946
7729
|
);
|
|
6947
|
-
return
|
|
7730
|
+
return readdirSync4(dir, { withFileTypes: true }).filter((e2) => e2.isFile() && e2.name.endsWith(".md")).map((e2) => basename3(e2.name, ".md")).filter((id) => demoted.includes(id));
|
|
6948
7731
|
}
|
|
6949
7732
|
function installNewAssets(projectDir, templatesDir, wants, outside) {
|
|
6950
7733
|
const installed = [];
|
|
@@ -6962,21 +7745,21 @@ function installNewAssets(projectDir, templatesDir, wants, outside) {
|
|
|
6962
7745
|
if (!wants(group)) continue;
|
|
6963
7746
|
if (entry.target === HARNESS_ANCHOR_FILE) continue;
|
|
6964
7747
|
if (isBaselineExcluded(entry.target, baselineExcluded)) continue;
|
|
6965
|
-
const target =
|
|
7748
|
+
const target = join30(projectDir, entry.target);
|
|
6966
7749
|
const foreign = foreignOwnedTarget(projectDir, entry.target);
|
|
6967
7750
|
if (foreign !== null) {
|
|
6968
7751
|
if (!foreignOwned.includes(foreign)) foreignOwned.push(foreign);
|
|
6969
7752
|
continue;
|
|
6970
7753
|
}
|
|
6971
7754
|
if (existsSync21(target)) continue;
|
|
6972
|
-
const source =
|
|
7755
|
+
const source = join30(templatesDir, entry.source);
|
|
6973
7756
|
if (!existsSync21(source)) continue;
|
|
6974
7757
|
if (outside.skip(target)) continue;
|
|
6975
7758
|
if (entry.target.startsWith(".claude/")) {
|
|
6976
7759
|
if (!claudeSelected) continue;
|
|
6977
7760
|
if (entry.target === SETTINGS_TARGET) continue;
|
|
6978
7761
|
}
|
|
6979
|
-
|
|
7762
|
+
mkdirSync7(dirname7(target), { recursive: true });
|
|
6980
7763
|
copyFileSync(source, target);
|
|
6981
7764
|
const recordedAs = entry.target.startsWith(".claude/") ? entry.target.slice(8) : entry.target;
|
|
6982
7765
|
const wired = entry.target.startsWith(".claude/hooks/") && wiredBefore.has(entry.target.slice(".claude/hooks/".length));
|
|
@@ -6996,27 +7779,27 @@ function collectRunBackups(projectDir, startedAt, exclude) {
|
|
|
6996
7779
|
const consider = (rel) => {
|
|
6997
7780
|
if (!BACKUP_SUFFIX.test(rel)) return;
|
|
6998
7781
|
if (exclude?.has(rel)) return;
|
|
6999
|
-
const abs =
|
|
7782
|
+
const abs = join30(projectDir, rel);
|
|
7000
7783
|
if (statSync4(abs).mtimeMs < startedAt - 1e3) return;
|
|
7001
7784
|
out.push({ path: rel.replace(BACKUP_SUFFIX, ""), backup: rel });
|
|
7002
7785
|
};
|
|
7003
|
-
for (const e2 of
|
|
7786
|
+
for (const e2 of readdirSync4(projectDir, { withFileTypes: true }))
|
|
7004
7787
|
if (e2.isFile()) consider(e2.name);
|
|
7005
7788
|
for (const dir of BACKUP_SCAN_DIRS) {
|
|
7006
|
-
for (const rel of listFilesRecursive(
|
|
7789
|
+
for (const rel of listFilesRecursive(join30(projectDir, dir))) consider(`${dir}/${rel}`);
|
|
7007
7790
|
}
|
|
7008
7791
|
return out.sort((a, b2) => a.path.localeCompare(b2.path));
|
|
7009
7792
|
}
|
|
7010
7793
|
function writeBackupList(projectDir, backups, noChecksum = /* @__PURE__ */ new Set()) {
|
|
7011
|
-
const dir =
|
|
7012
|
-
const file =
|
|
7794
|
+
const dir = join30(projectDir, ".uzys-agent-harness");
|
|
7795
|
+
const file = join30(dir, "update-backups.json");
|
|
7013
7796
|
try {
|
|
7014
7797
|
if (backups.length === 0) {
|
|
7015
7798
|
if (existsSync21(file)) unlinkSync2(file);
|
|
7016
7799
|
return;
|
|
7017
7800
|
}
|
|
7018
7801
|
if (!existsSync21(dir)) return;
|
|
7019
|
-
|
|
7802
|
+
writeFileSync7(
|
|
7020
7803
|
file,
|
|
7021
7804
|
`${JSON.stringify(
|
|
7022
7805
|
{
|
|
@@ -7047,14 +7830,14 @@ function installNewSkillDirs(projectDir, templatesDir, tracks, outside) {
|
|
|
7047
7830
|
if (entry.type !== "dir" || !entry.target.startsWith(".claude/skills/")) continue;
|
|
7048
7831
|
if (!entry.applies(spec) || isBaselineExcluded(entry.target, excluded)) continue;
|
|
7049
7832
|
if (skillExcluded.has(entry.target.slice(".claude/skills/".length))) continue;
|
|
7050
|
-
const target =
|
|
7833
|
+
const target = join30(projectDir, entry.target);
|
|
7051
7834
|
const foreign = foreignOwnedTarget(projectDir, entry.target);
|
|
7052
7835
|
if (foreign !== null) {
|
|
7053
7836
|
if (!foreignOwned.includes(foreign)) foreignOwned.push(foreign);
|
|
7054
7837
|
continue;
|
|
7055
7838
|
}
|
|
7056
7839
|
if (existsSync21(target)) continue;
|
|
7057
|
-
const source =
|
|
7840
|
+
const source = join30(templatesDir, entry.source);
|
|
7058
7841
|
if (!existsSync21(source)) continue;
|
|
7059
7842
|
if (outside.skip(target)) continue;
|
|
7060
7843
|
copyDir(source, target, (rel) => foreignOwnedTarget(projectDir, `${entry.target}/${rel}`));
|
|
@@ -7086,12 +7869,12 @@ function trackOnlyFileAssets(tracks) {
|
|
|
7086
7869
|
);
|
|
7087
7870
|
}
|
|
7088
7871
|
function syncHarnessAnchor(projectDir, templatesDir, report, outside, now = /* @__PURE__ */ new Date()) {
|
|
7089
|
-
if (existsSync21(
|
|
7872
|
+
if (existsSync21(join30(projectDir, LEGACY_ANCHOR_FILE2))) {
|
|
7090
7873
|
report.legacyAnchor = LEGACY_ANCHOR_FILE2;
|
|
7091
7874
|
}
|
|
7092
|
-
const templateMd =
|
|
7875
|
+
const templateMd = join30(templatesDir, "CLAUDE.md");
|
|
7093
7876
|
if (!existsSync21(templateMd)) return;
|
|
7094
|
-
const anchor =
|
|
7877
|
+
const anchor = join30(projectDir, HARNESS_ANCHOR_FILE);
|
|
7095
7878
|
if (outside.skip(anchor)) return;
|
|
7096
7879
|
const existed = existsSync21(anchor);
|
|
7097
7880
|
if (existed) {
|
|
@@ -7117,7 +7900,7 @@ function syncHarnessAnchor(projectDir, templatesDir, report, outside, now = /* @
|
|
|
7117
7900
|
recordAnchorBaseline(projectDir, anchor);
|
|
7118
7901
|
}
|
|
7119
7902
|
function upsertRootImport(projectDir, outside) {
|
|
7120
|
-
const target =
|
|
7903
|
+
const target = join30(projectDir, "CLAUDE.md");
|
|
7121
7904
|
if (outside.skip(target)) return false;
|
|
7122
7905
|
const existing = existsSync21(target) ? readFileSync21(target, "utf8") : null;
|
|
7123
7906
|
const next = upsertHarnessImport(existing, {
|
|
@@ -7126,12 +7909,12 @@ function upsertRootImport(projectDir, outside) {
|
|
|
7126
7909
|
// ADR-085 — update 는 선택 목록을 인자로 받지 않는다. `syncSkills` 와 같은 판정을 쓴다:
|
|
7127
7910
|
// `.claude/skills/<id>` 가 있으면 그 스킬은 이 설치가 고른 것이다.
|
|
7128
7911
|
continuousSkills: CONTINUOUS_SKILLS.map((s) => s.id).filter(
|
|
7129
|
-
(id) => existsSync21(
|
|
7912
|
+
(id) => existsSync21(join30(projectDir, ".claude/skills", id))
|
|
7130
7913
|
)
|
|
7131
7914
|
});
|
|
7132
7915
|
if (next === existing) return false;
|
|
7133
7916
|
if (existing !== null) backupIfLossyUtf8(target);
|
|
7134
|
-
|
|
7917
|
+
writeFileSync7(target, next);
|
|
7135
7918
|
return true;
|
|
7136
7919
|
}
|
|
7137
7920
|
function installedTracks(projectDir) {
|
|
@@ -7161,7 +7944,7 @@ function excludedBaselineOnDisk(projectDir, log) {
|
|
|
7161
7944
|
if (excluded.size === 0) return [];
|
|
7162
7945
|
const spec = buildAssetSpec({ tracks: installedTracks(projectDir), options: DEFAULT_OPTIONS });
|
|
7163
7946
|
return buildManifest(spec).filter(
|
|
7164
|
-
(e2) => e2.applies(spec) && isBaselineExcluded(e2.target, excluded) && existsSync21(
|
|
7947
|
+
(e2) => e2.applies(spec) && isBaselineExcluded(e2.target, excluded) && existsSync21(join30(projectDir, e2.target))
|
|
7165
7948
|
).map((e2) => e2.target);
|
|
7166
7949
|
}
|
|
7167
7950
|
function excludedSkillOf(log) {
|
|
@@ -7189,7 +7972,7 @@ function recordedRenderInputs(projectDir, log) {
|
|
|
7189
7972
|
function recordedBundledSkills(projectDir, log) {
|
|
7190
7973
|
if (log === null) {
|
|
7191
7974
|
return INTERNAL_BUNDLED_SKILL_IDS.filter(
|
|
7192
|
-
(id) => existsSync21(
|
|
7975
|
+
(id) => existsSync21(join30(projectDir, ".claude/skills", id)) || existsSync21(join30(projectDir, ".agents/skills", id))
|
|
7193
7976
|
);
|
|
7194
7977
|
}
|
|
7195
7978
|
const ids = recordedSkillIds(projectDir, log);
|
|
@@ -7236,9 +8019,9 @@ var SHARED_SKILLS_DIR = ".agents/skills";
|
|
|
7236
8019
|
var SHARED_SKILL_FILE = /^\.agents\/skills\/([^/]+)\//;
|
|
7237
8020
|
var SHARED_SKILL_MD = /^\.agents\/skills\/([^/]+)\/SKILL\.md$/;
|
|
7238
8021
|
function sharedSkillIdsOnDisk(projectDir) {
|
|
7239
|
-
const root =
|
|
8022
|
+
const root = join30(projectDir, SHARED_SKILLS_DIR);
|
|
7240
8023
|
if (!existsSync21(root)) return /* @__PURE__ */ new Set();
|
|
7241
|
-
return new Set(
|
|
8024
|
+
return new Set(readdirSync4(root).filter((id) => existsSync21(join30(root, id, "SKILL.md"))));
|
|
7242
8025
|
}
|
|
7243
8026
|
var CREATED_SHARED_HOW = {
|
|
7244
8027
|
"opencode.json": "created from template (harness part + template defaults)",
|
|
@@ -7265,14 +8048,14 @@ function refreshExternalCli(projectDir, harnessRoot, droppedKeys, harnessMcp) {
|
|
|
7265
8048
|
const log = readInstallLog(projectDir);
|
|
7266
8049
|
const presentBefore = sharedSkillIdsOnDisk(projectDir);
|
|
7267
8050
|
const rulesBefore = /* @__PURE__ */ new Set();
|
|
7268
|
-
const rulesDir =
|
|
8051
|
+
const rulesDir = join30(projectDir, ".agents", "rules");
|
|
7269
8052
|
if (existsSync21(rulesDir)) {
|
|
7270
8053
|
try {
|
|
7271
|
-
for (const f of
|
|
8054
|
+
for (const f of readdirSync4(rulesDir)) rulesBefore.add(f);
|
|
7272
8055
|
} catch {
|
|
7273
8056
|
}
|
|
7274
8057
|
}
|
|
7275
|
-
const agentsMdBefore = existsSync21(
|
|
8058
|
+
const agentsMdBefore = existsSync21(join30(projectDir, "AGENTS.md"));
|
|
7276
8059
|
const result = runCliTransforms({
|
|
7277
8060
|
harnessRoot,
|
|
7278
8061
|
projectDir,
|
|
@@ -7293,6 +8076,8 @@ function refreshExternalCli(projectDir, harnessRoot, droppedKeys, harnessMcp) {
|
|
|
7293
8076
|
// 앞 단계(`refreshNeutralHelpers`)가 헬퍼만 든 `externalFiles` 를 적어도 같은 답이다 — 헬퍼는 외부 자리로 세지 않는다(B-2)
|
|
7294
8077
|
owned: recordedOwner(log)
|
|
7295
8078
|
});
|
|
8079
|
+
const anchorPath = result.anchorRetired?.action === "removed" ? result.anchorRetired.path : null;
|
|
8080
|
+
const anchorDisplaced = log === null || anchorPath === null ? [] : restoreDisplaced(log, projectDir, { has: (p2) => p2 === anchorPath, write: true });
|
|
7296
8081
|
if (log) {
|
|
7297
8082
|
const retiredPath = result.anchorRetired?.forget === true ? result.anchorRetired.path : null;
|
|
7298
8083
|
const merged = mergeExternalFiles(log.externalFiles, result.externalFiles).filter(
|
|
@@ -7311,6 +8096,8 @@ function refreshExternalCli(projectDir, harnessRoot, droppedKeys, harnessMcp) {
|
|
|
7311
8096
|
const created = result.sharedFiles.filter((f) => f.createdAsRoot === true).map((f) => ({ path: f.path, change: "created", notes: ["\uD558\uB124\uC2A4 \uBAAB\uB9CC(\uBE14\uB85D)"] }));
|
|
7312
8097
|
const roots = [...created, ...withoutLostBackups(log.rootFiles, result.displaced ?? [])];
|
|
7313
8098
|
if (roots.length > 0) next.rootFiles = mergeRootFiles(log.rootFiles, roots);
|
|
8099
|
+
if (anchorDisplaced.some((d2) => d2.forget))
|
|
8100
|
+
next.rootFiles = withoutRestored(next.rootFiles, anchorDisplaced);
|
|
7314
8101
|
try {
|
|
7315
8102
|
writeInstallLog(projectDir, next);
|
|
7316
8103
|
} catch {
|
|
@@ -7390,7 +8177,10 @@ function refreshExternalCli(projectDir, harnessRoot, droppedKeys, harnessMcp) {
|
|
|
7390
8177
|
)
|
|
7391
8178
|
],
|
|
7392
8179
|
anchorRetired: result.anchorRetired,
|
|
8180
|
+
anchorDisplaced,
|
|
7393
8181
|
agentsMd: agentsMdNews(result.agentsMd, agentsMdBefore, priorPaths),
|
|
8182
|
+
agentsMdLegacyDropped: result.agentsMd?.agentsMd.droppedLegacySections ?? 0,
|
|
8183
|
+
agentsMdLegacyEdited: result.agentsMd?.agentsMd.editedLegacySections ?? [],
|
|
7394
8184
|
// #625 — install 화면(`sharedRow`)이 말하는 "남긴 것" 을 update 도 말한다. 고친 구간과 기록이 없어 모르는 구간은
|
|
7395
8185
|
// 다른 사실이라 기록(`portions`)으로 가른다 — 어댑터는 기록된 키가 고쳐졌으면 남기고 기록 sha 를 잇는다(계약 ⓑ)
|
|
7396
8186
|
sharedLeft: result.sharedFiles.filter((f) => f.action === "left" || f.leftAsIs.length + f.kept.length > 0).map((f) => {
|
|
@@ -7416,10 +8206,10 @@ function updateDir(target, source, ext, ctx, now = /* @__PURE__ */ new Date()) {
|
|
|
7416
8206
|
let updated = 0;
|
|
7417
8207
|
const backedUp = [];
|
|
7418
8208
|
const displaced = [];
|
|
7419
|
-
for (const file of
|
|
8209
|
+
for (const file of readdirSync4(target)) {
|
|
7420
8210
|
if (!file.endsWith(ext)) continue;
|
|
7421
|
-
const targetFile =
|
|
7422
|
-
const sourceFile =
|
|
8211
|
+
const targetFile = join30(target, file);
|
|
8212
|
+
const sourceFile = join30(source, file);
|
|
7423
8213
|
if (!existsSync21(sourceFile)) continue;
|
|
7424
8214
|
if (ctx.outside?.skip(targetFile)) continue;
|
|
7425
8215
|
const projectRel = `.claude/${ctx.prefix}/${file}`;
|
|
@@ -7451,9 +8241,9 @@ function syncSkills(targetDir, sourceDir, baseline, now = /* @__PURE__ */ new Da
|
|
|
7451
8241
|
const foreignOwned = [];
|
|
7452
8242
|
const pruned = [];
|
|
7453
8243
|
const displaced = [];
|
|
7454
|
-
for (const skill of
|
|
8244
|
+
for (const skill of readdirSync4(sourceDir, { withFileTypes: true })) {
|
|
7455
8245
|
if (!skill.isDirectory()) continue;
|
|
7456
|
-
const targetSkill =
|
|
8246
|
+
const targetSkill = join30(targetDir, skill.name);
|
|
7457
8247
|
if (occupiedByNonDirectory(targetSkill)) {
|
|
7458
8248
|
skippedLinks.push(skill.name);
|
|
7459
8249
|
continue;
|
|
@@ -7461,15 +8251,15 @@ function syncSkills(targetDir, sourceDir, baseline, now = /* @__PURE__ */ new Da
|
|
|
7461
8251
|
if (opts.targets !== void 0 && !opts.targets.has(skill.name)) continue;
|
|
7462
8252
|
if (!existsSync21(targetSkill)) continue;
|
|
7463
8253
|
if (excludedSkill?.(skill.name)) continue;
|
|
7464
|
-
for (const rel of listFilesRecursive(
|
|
7465
|
-
const targetFile =
|
|
8254
|
+
for (const rel of listFilesRecursive(join30(sourceDir, skill.name))) {
|
|
8255
|
+
const targetFile = join30(targetSkill, rel);
|
|
7466
8256
|
const foreign = foreignOf(`${skill.name}/${rel}`);
|
|
7467
8257
|
if (foreign !== null) {
|
|
7468
8258
|
if (!foreignOwned.includes(foreign)) foreignOwned.push(foreign);
|
|
7469
8259
|
continue;
|
|
7470
8260
|
}
|
|
7471
8261
|
if (outside?.skip(targetFile)) continue;
|
|
7472
|
-
const next = readFileSync21(
|
|
8262
|
+
const next = readFileSync21(join30(sourceDir, skill.name, rel), "utf8");
|
|
7473
8263
|
const projectRel = `.claude/skills/${skill.name}/${rel}`;
|
|
7474
8264
|
const rec = opts.recordOf?.(projectRel) ?? baselineRecord(baseline, `${skill.name}/${rel}`);
|
|
7475
8265
|
const w3 = judgedUpdateWrite(targetFile, rec, next, now);
|
|
@@ -7478,11 +8268,11 @@ function syncSkills(targetDir, sourceDir, baseline, now = /* @__PURE__ */ new Da
|
|
|
7478
8268
|
const d2 = displacedEntry(w3, projectRel, targetFile);
|
|
7479
8269
|
if (d2 !== null) displaced.push(d2);
|
|
7480
8270
|
}
|
|
7481
|
-
const bundled = new Set(listFilesRecursive(
|
|
8271
|
+
const bundled = new Set(listFilesRecursive(join30(sourceDir, skill.name)));
|
|
7482
8272
|
for (const rel of listFilesRecursive(targetSkill)) {
|
|
7483
8273
|
if (bundled.has(rel) || basename3(rel).includes(".backup-")) continue;
|
|
7484
8274
|
if (foreignOf(`${skill.name}/${rel}`) !== null) continue;
|
|
7485
|
-
const targetFile =
|
|
8275
|
+
const targetFile = join30(targetSkill, rel);
|
|
7486
8276
|
if (outside?.skip(targetFile)) continue;
|
|
7487
8277
|
const rec = opts.recordOf?.(`.claude/skills/${skill.name}/${rel}`) ?? baselineRecord(baseline, `${skill.name}/${rel}`);
|
|
7488
8278
|
if (rec.state !== "sha" || hashContent(readFileSync21(targetFile, "utf8")) !== rec.sha256) {
|
|
@@ -7491,8 +8281,8 @@ function syncSkills(targetDir, sourceDir, baseline, now = /* @__PURE__ */ new Da
|
|
|
7491
8281
|
}
|
|
7492
8282
|
unlinkSync2(targetFile);
|
|
7493
8283
|
pruned.push(`${skill.name}/${rel}`);
|
|
7494
|
-
for (let d2 =
|
|
7495
|
-
|
|
8284
|
+
for (let d2 = dirname7(targetFile); d2 !== targetSkill && readdirSync4(d2).length === 0; d2 = dirname7(d2))
|
|
8285
|
+
rmdirSync2(d2);
|
|
7496
8286
|
}
|
|
7497
8287
|
}
|
|
7498
8288
|
return { updated, backedUp, skippedLinks, foreignOwned, pruned, displaced };
|
|
@@ -7505,15 +8295,15 @@ function judgedUpdateWrite(abs, rec, next, now) {
|
|
|
7505
8295
|
case "leave":
|
|
7506
8296
|
break;
|
|
7507
8297
|
case "create":
|
|
7508
|
-
|
|
7509
|
-
|
|
8298
|
+
mkdirSync7(dirname7(abs), { recursive: true });
|
|
8299
|
+
writeFileSync7(abs, next);
|
|
7510
8300
|
break;
|
|
7511
8301
|
case "overwrite":
|
|
7512
|
-
|
|
8302
|
+
writeFileSync7(abs, next);
|
|
7513
8303
|
break;
|
|
7514
8304
|
case "backup+overwrite":
|
|
7515
8305
|
backup = backupFile(abs, now);
|
|
7516
|
-
|
|
8306
|
+
writeFileSync7(abs, next);
|
|
7517
8307
|
break;
|
|
7518
8308
|
default:
|
|
7519
8309
|
throw new Error(`update: '${j4.verdict}' is not a write verdict (${abs})`);
|
|
@@ -7549,13 +8339,15 @@ function withoutLostBackups(prior, add) {
|
|
|
7549
8339
|
);
|
|
7550
8340
|
return add.filter((f) => f.notes.length > 0 || !backedUp.has(f.path));
|
|
7551
8341
|
}
|
|
7552
|
-
function recordDisplaced(projectDir, displaced) {
|
|
8342
|
+
function recordDisplaced(projectDir, displaced, restored = []) {
|
|
7553
8343
|
const log = readInstallLog(projectDir);
|
|
7554
8344
|
if (!log) return;
|
|
7555
8345
|
const add = withoutLostBackups(log.rootFiles, displaced);
|
|
7556
|
-
|
|
8346
|
+
const settles = restored.some((d2) => d2.forget);
|
|
8347
|
+
if (add.length === 0 && !settles) return;
|
|
8348
|
+
const merged = add.length === 0 ? [...log.rootFiles ?? []] : mergeRootFiles(log.rootFiles, add);
|
|
7557
8349
|
try {
|
|
7558
|
-
writeInstallLog(projectDir, { ...log, rootFiles:
|
|
8350
|
+
writeInstallLog(projectDir, { ...log, rootFiles: withoutRestored(merged, restored) });
|
|
7559
8351
|
} catch {
|
|
7560
8352
|
}
|
|
7561
8353
|
}
|
|
@@ -7615,11 +8407,11 @@ function refreshSkillBaseline(projectDir, templatesDir, outside, targets, notOur
|
|
|
7615
8407
|
function pruneOrphans(target, source, ext, ctx, now = /* @__PURE__ */ new Date()) {
|
|
7616
8408
|
if (!existsSync21(target) || !existsSync21(source)) return [];
|
|
7617
8409
|
const removed = [];
|
|
7618
|
-
for (const file of
|
|
8410
|
+
for (const file of readdirSync4(target)) {
|
|
7619
8411
|
if (!file.endsWith(ext)) continue;
|
|
7620
|
-
const sourceFile =
|
|
8412
|
+
const sourceFile = join30(source, file);
|
|
7621
8413
|
if (!existsSync21(sourceFile)) {
|
|
7622
|
-
const targetFile =
|
|
8414
|
+
const targetFile = join30(target, file);
|
|
7623
8415
|
const key = `${ctx.prefix}/${file}`;
|
|
7624
8416
|
if (!ctx.baseline.has(key)) continue;
|
|
7625
8417
|
if (ctx.outside?.skip(targetFile)) continue;
|
|
@@ -7636,7 +8428,7 @@ function pruneOrphans(target, source, ext, ctx, now = /* @__PURE__ */ new Date()
|
|
|
7636
8428
|
return removed;
|
|
7637
8429
|
}
|
|
7638
8430
|
function retireMcpAllowlist(projectDir, now = /* @__PURE__ */ new Date()) {
|
|
7639
|
-
const target =
|
|
8431
|
+
const target = join30(projectDir, ".mcp-allowlist");
|
|
7640
8432
|
if (!existsSync21(target)) return null;
|
|
7641
8433
|
try {
|
|
7642
8434
|
const backup = backupFile(target, now);
|
|
@@ -7652,12 +8444,12 @@ function refreshNeutralHelpers(projectDir, templatesDir, report) {
|
|
|
7652
8444
|
for (const entry of buildManifest(spec)) {
|
|
7653
8445
|
if (entry.type !== "file" || !isCliNeutralTarget(entry.target)) continue;
|
|
7654
8446
|
if (!entry.applies(spec)) continue;
|
|
7655
|
-
const abs =
|
|
7656
|
-
const source =
|
|
8447
|
+
const abs = join30(projectDir, entry.target);
|
|
8448
|
+
const source = join30(templatesDir, entry.source);
|
|
7657
8449
|
if (!existsSync21(source)) continue;
|
|
7658
8450
|
let st2;
|
|
7659
8451
|
try {
|
|
7660
|
-
st2 =
|
|
8452
|
+
st2 = lstatSync5(abs);
|
|
7661
8453
|
} catch {
|
|
7662
8454
|
continue;
|
|
7663
8455
|
}
|
|
@@ -7676,7 +8468,7 @@ function refreshNeutralHelpers(projectDir, templatesDir, report) {
|
|
|
7676
8468
|
continue;
|
|
7677
8469
|
}
|
|
7678
8470
|
if (recorded2 === void 0 || recorded2.sha256 !== diskSha) backupFile(abs);
|
|
7679
|
-
|
|
8471
|
+
writeFileSync7(abs, freshContent, "utf8");
|
|
7680
8472
|
refreshed.set(entry.target, freshSha);
|
|
7681
8473
|
report.updated[entry.target] = (report.updated[entry.target] ?? 0) + 1;
|
|
7682
8474
|
}
|
|
@@ -7705,11 +8497,11 @@ function recordClaudeCommand(log, tracks) {
|
|
|
7705
8497
|
function runInstall(ctx) {
|
|
7706
8498
|
const { harnessRoot, projectDir } = ctx;
|
|
7707
8499
|
const mode = ctx.mode ?? "fresh";
|
|
7708
|
-
const templatesDir =
|
|
8500
|
+
const templatesDir = join31(harnessRoot, "templates");
|
|
7709
8501
|
if (!existsSync22(templatesDir)) {
|
|
7710
8502
|
throw new Error(`Templates dir not found: ${templatesDir}`);
|
|
7711
8503
|
}
|
|
7712
|
-
const claudeDir =
|
|
8504
|
+
const claudeDir = join31(projectDir, ".claude");
|
|
7713
8505
|
const previousLog = readInstallLog(projectDir);
|
|
7714
8506
|
const legacyAnchor = mode === "update" ? null : legacyAnchorTrace(projectDir, ctx.spec);
|
|
7715
8507
|
if (mode === "update" && previousLog === null) {
|
|
@@ -7734,13 +8526,13 @@ function runInstall(ctx) {
|
|
|
7734
8526
|
const manifestSpec = buildManifestSpec(spec);
|
|
7735
8527
|
const baselineExcluded = new Set(spec.baselineExclude ?? []);
|
|
7736
8528
|
if (spec.cli.includes("claude")) {
|
|
7737
|
-
const settingsPath =
|
|
8529
|
+
const settingsPath = join31(projectDir, ".claude", "settings.json");
|
|
7738
8530
|
if (existsSync22(settingsPath)) {
|
|
7739
8531
|
try {
|
|
7740
8532
|
JSON.parse(readFileSync22(settingsPath, "utf8"));
|
|
7741
8533
|
} catch {
|
|
7742
8534
|
throw new Error(
|
|
7743
|
-
`${
|
|
8535
|
+
`${relative4(process.cwd(), settingsPath)} is not valid JSON \u2014 left untouched, so no hooks were wired. Fix or delete that file, then run the install again`
|
|
7744
8536
|
);
|
|
7745
8537
|
}
|
|
7746
8538
|
}
|
|
@@ -7874,10 +8666,17 @@ function runInstallStages(ctx, args) {
|
|
|
7874
8666
|
...outOfTrack.forget,
|
|
7875
8667
|
...anchorRetired?.forget === true ? [anchorRetired.path] : []
|
|
7876
8668
|
]);
|
|
8669
|
+
const left = /* @__PURE__ */ new Set([
|
|
8670
|
+
...outOfTrack.removed,
|
|
8671
|
+
...outOfTrack.backedUp.map((b2) => b2.path),
|
|
8672
|
+
...anchorRetired?.action === "removed" ? [anchorRetired.path] : []
|
|
8673
|
+
]);
|
|
8674
|
+
const displacedRestored = previousLog === null || left.size === 0 ? [] : restoreDisplaced(previousLog, projectDir, { has: (p2) => left.has(p2), write: true });
|
|
7877
8675
|
const logBase = previousLog === null || forgotten.size === 0 ? previousLog : {
|
|
7878
8676
|
...previousLog,
|
|
7879
8677
|
spec: { ...previousLog.spec, clis: [...installedClis(previousLog)] },
|
|
7880
|
-
externalFiles: (previousLog.externalFiles ?? []).filter((f) => !forgotten.has(f.path))
|
|
8678
|
+
externalFiles: (previousLog.externalFiles ?? []).filter((f) => !forgotten.has(f.path)),
|
|
8679
|
+
...displacedRestored.some((d2) => d2.forget) ? { rootFiles: withoutRestored(previousLog.rootFiles, displacedRestored) } : {}
|
|
7881
8680
|
};
|
|
7882
8681
|
stage.envExampleCreated = writeEnvExample(projectDir, spec.tracks);
|
|
7883
8682
|
const envFiles = writeEnvironmentFiles(writer, stage.envExampleCreated, previousLog);
|
|
@@ -7937,10 +8736,15 @@ function runInstallStages(ctx, args) {
|
|
|
7937
8736
|
linked.outside,
|
|
7938
8737
|
reclaimOutside.list()
|
|
7939
8738
|
),
|
|
7940
|
-
...outOfTrack.removed.length + outOfTrack.backedUp.length + outOfTrack.kept.length > 0 ? { outOfTrack } : {}
|
|
8739
|
+
...outOfTrack.removed.length + outOfTrack.backedUp.length + outOfTrack.kept.length > 0 ? { outOfTrack } : {},
|
|
8740
|
+
...displacedRestored.length > 0 ? { displacedRestored } : {}
|
|
7941
8741
|
};
|
|
7942
8742
|
ctx.onProgress?.({ type: "baseline-complete", baseline });
|
|
7943
|
-
const {
|
|
8743
|
+
const {
|
|
8744
|
+
report: external,
|
|
8745
|
+
backups: externalSkillBackups,
|
|
8746
|
+
displaced: externalSkillDisplaced
|
|
8747
|
+
} = runExternalPhase(ctx, previousLog);
|
|
7944
8748
|
writeInstallLogSafe(
|
|
7945
8749
|
ctx,
|
|
7946
8750
|
// 링크 본문의 기준선도 같은 필드다 — 같은 경로면 뒤(이번에 쓴 값)가 이긴다.
|
|
@@ -7956,7 +8760,9 @@ function runInstallStages(ctx, args) {
|
|
|
7956
8760
|
...cliSharedFiles.filter((f) => f.createdAsRoot === true).map((f) => ({ path: f.path, change: "created", notes: ["\uD558\uB124\uC2A4 \uBAAB\uB9CC(\uBE14\uB85D)"] })),
|
|
7957
8761
|
// #761 — 외부 변환 · 링크 본문이 첫 접촉으로 비켜 둔 설치자 파일. 하네스가 떠날 때 되돌리는 근거다
|
|
7958
8762
|
...cliDisplaced,
|
|
7959
|
-
...linked.displaced
|
|
8763
|
+
...linked.displaced,
|
|
8764
|
+
// #780 — 외부 스킬 도구가 덮은 설치자 파일. 그 자리의 도구 파일은 `buildAssetEntries` 가 이 경로로 자산 몫에 넣는다
|
|
8765
|
+
...externalSkillDisplaced
|
|
7960
8766
|
],
|
|
7961
8767
|
cliTransforms.codexOptIn
|
|
7962
8768
|
);
|
|
@@ -8018,7 +8824,7 @@ function releasedThisRun(args) {
|
|
|
8018
8824
|
}
|
|
8019
8825
|
if (id.startsWith(BASELINE_PREFIX)) {
|
|
8020
8826
|
const again2 = manifest.some(
|
|
8021
|
-
(e2) => e2.applies(manifestSpec) && classifyBaselineTarget(e2.target)?.id === id && existsSync22(
|
|
8827
|
+
(e2) => e2.applies(manifestSpec) && classifyBaselineTarget(e2.target)?.id === id && existsSync22(join31(projectDir, e2.target))
|
|
8022
8828
|
);
|
|
8023
8829
|
return { id, again: again2, tail: "the harness manages it again" };
|
|
8024
8830
|
}
|
|
@@ -8027,7 +8833,7 @@ function releasedThisRun(args) {
|
|
|
8027
8833
|
options: spec.options,
|
|
8028
8834
|
...spec.userOverride ? { userOverride: spec.userOverride } : {}
|
|
8029
8835
|
});
|
|
8030
|
-
const recorded2 = (previousLog?.assets.some((a) => a.id === id) ?? false) || [".claude/skills", ".agents/skills"].some((d2) => existsSync22(
|
|
8836
|
+
const recorded2 = (previousLog?.assets.some((a) => a.id === id) ?? false) || [".claude/skills", ".agents/skills"].some((d2) => existsSync22(join31(projectDir, d2, id)));
|
|
8031
8837
|
return {
|
|
8032
8838
|
id,
|
|
8033
8839
|
again,
|
|
@@ -8039,10 +8845,10 @@ function pendingKeyExcludes(projectDir, keyExclude, touched) {
|
|
|
8039
8845
|
const done = new Set(touched);
|
|
8040
8846
|
return keyExclude.flatMap((id) => {
|
|
8041
8847
|
const path = sharedPathOfKeyId(id);
|
|
8042
|
-
if (path === null || done.has(path) || !existsSync22(
|
|
8848
|
+
if (path === null || done.has(path) || !existsSync22(join31(projectDir, path))) return [];
|
|
8043
8849
|
const name = adapterFor(path);
|
|
8044
8850
|
const keys = [...excludedKeys(path, [id])];
|
|
8045
|
-
const present2 = name === null ? null : ADAPTERS[name].read(readFileSync22(
|
|
8851
|
+
const present2 = name === null ? null : ADAPTERS[name].read(readFileSync22(join31(projectDir, path), "utf8"), keys, projectDir);
|
|
8046
8852
|
return present2 !== null && present2.size === 0 ? [] : [{ id, path }];
|
|
8047
8853
|
});
|
|
8048
8854
|
}
|
|
@@ -8086,7 +8892,7 @@ function installCliNeutralAssets(manifestSpec, templatesDir, baselineExcluded, w
|
|
|
8086
8892
|
continue;
|
|
8087
8893
|
}
|
|
8088
8894
|
if (!isCliNeutralTarget(entry.target)) continue;
|
|
8089
|
-
const source =
|
|
8895
|
+
const source = join31(templatesDir, entry.source);
|
|
8090
8896
|
if (!existsSync22(source)) {
|
|
8091
8897
|
result.skipped += 1;
|
|
8092
8898
|
continue;
|
|
@@ -8107,13 +8913,13 @@ function installClaudeBaseline(manifestSpec, projectDir, templatesDir, baselineE
|
|
|
8107
8913
|
if (!entry.applies(manifestSpec)) {
|
|
8108
8914
|
continue;
|
|
8109
8915
|
}
|
|
8110
|
-
const target =
|
|
8916
|
+
const target = join31(projectDir, entry.target);
|
|
8111
8917
|
if (isBaselineExcluded(entry.target, baselineExcluded)) {
|
|
8112
8918
|
result.excluded.push(entry.target);
|
|
8113
8919
|
if (existsSync22(target)) result.excludedOnDisk.push(entry.target);
|
|
8114
8920
|
continue;
|
|
8115
8921
|
}
|
|
8116
|
-
const source =
|
|
8922
|
+
const source = join31(templatesDir, entry.source);
|
|
8117
8923
|
if (!existsSync22(source)) {
|
|
8118
8924
|
result.skipped += 1;
|
|
8119
8925
|
continue;
|
|
@@ -8144,18 +8950,18 @@ function installClaudeBaseline(manifestSpec, projectDir, templatesDir, baselineE
|
|
|
8144
8950
|
if (!result.foreignOwned.includes(slot)) result.foreignOwned.push(slot);
|
|
8145
8951
|
continue;
|
|
8146
8952
|
}
|
|
8147
|
-
if (writer.skipOutside(
|
|
8953
|
+
if (writer.skipOutside(join31(projectDir, entry.target, rel))) {
|
|
8148
8954
|
leftOutside += 1;
|
|
8149
8955
|
continue;
|
|
8150
8956
|
}
|
|
8151
|
-
writer.harness(`${entry.target}/${rel}`, { source:
|
|
8957
|
+
writer.harness(`${entry.target}/${rel}`, { source: join31(source, rel) });
|
|
8152
8958
|
}
|
|
8153
8959
|
if (leftOutside > 0) continue;
|
|
8154
8960
|
result.dirsCopied += 1;
|
|
8155
8961
|
}
|
|
8156
8962
|
accumulateCategory(result.categories, entry);
|
|
8157
8963
|
}
|
|
8158
|
-
const hookDir =
|
|
8964
|
+
const hookDir = join31(projectDir, ".claude/hooks");
|
|
8159
8965
|
if (existsSync22(hookDir)) {
|
|
8160
8966
|
chmodHooksSync(hookDir, projectDir);
|
|
8161
8967
|
}
|
|
@@ -8172,12 +8978,12 @@ function installClaudeBaseline(manifestSpec, projectDir, templatesDir, baselineE
|
|
|
8172
8978
|
if (settingsSource !== null) {
|
|
8173
8979
|
writeSettingsPortion(writer, settingsSource, projectDir, previousLog, (script) => {
|
|
8174
8980
|
const target = `${HOOKS_PREFIX}${script}`;
|
|
8175
|
-
return manifest.some((e2) => e2.target === target && e2.applies(manifestSpec)) && !isBaselineExcluded(target, baselineExcluded) && existsSync22(
|
|
8981
|
+
return manifest.some((e2) => e2.target === target && e2.applies(manifestSpec)) && !isBaselineExcluded(target, baselineExcluded) && existsSync22(join31(projectDir, target));
|
|
8176
8982
|
});
|
|
8177
8983
|
result.keptHookRefs.push(
|
|
8178
8984
|
...findStaleHookRefs(
|
|
8179
|
-
|
|
8180
|
-
|
|
8985
|
+
join31(projectDir, ".claude", "settings.json"),
|
|
8986
|
+
join31(projectDir, ".claude")
|
|
8181
8987
|
)
|
|
8182
8988
|
);
|
|
8183
8989
|
}
|
|
@@ -8187,7 +8993,7 @@ function installClaudeBaseline(manifestSpec, projectDir, templatesDir, baselineE
|
|
|
8187
8993
|
// ADR-085 · update(`upsertRootImport`)와 같은 판정 — 실제로 깔린 스킬만 안내한다. 밖 링크라 쓰지 않은
|
|
8188
8994
|
// 스킬(ADR-098)을 "installed" 라 적으면 다음 update 가 그 절을 걷어 내 두 동작이 서로 반대로 쓴다.
|
|
8189
8995
|
(manifestSpec.selectedInternalSkills ?? []).filter(
|
|
8190
|
-
(id) => existsSync22(
|
|
8996
|
+
(id) => existsSync22(join31(projectDir, ".claude", "skills", id))
|
|
8191
8997
|
),
|
|
8192
8998
|
harnessRoot,
|
|
8193
8999
|
writer
|
|
@@ -8228,7 +9034,7 @@ function writeEnvironmentFiles(writer, envExampleCreated, previousLog) {
|
|
|
8228
9034
|
}
|
|
8229
9035
|
function runExternalPhase(ctx, previousLog) {
|
|
8230
9036
|
if (ctx.runExternal === null) {
|
|
8231
|
-
return { report: null, backups: [] };
|
|
9037
|
+
return { report: null, backups: [], displaced: [] };
|
|
8232
9038
|
}
|
|
8233
9039
|
const { projectDir, spec } = ctx;
|
|
8234
9040
|
const runExt = ctx.runExternal ?? runExternalInstall;
|
|
@@ -8251,22 +9057,38 @@ function runExternalPhase(ctx, previousLog) {
|
|
|
8251
9057
|
};
|
|
8252
9058
|
const { targets } = selectExternalTargets(EXTERNAL_ASSETS, { ...filterCtx, cli: spec.cli });
|
|
8253
9059
|
ctx.onProgress?.({ type: "external-start", assetCount: targets.length });
|
|
8254
|
-
const
|
|
8255
|
-
const
|
|
8256
|
-
|
|
8257
|
-
(previousLog?.assets ?? []).filter((a) => a.method === "skill" && skillIds.has(a.id))
|
|
8258
|
-
|
|
8259
|
-
|
|
8260
|
-
|
|
8261
|
-
|
|
8262
|
-
);
|
|
8263
|
-
|
|
9060
|
+
const skills = targets.filter((a) => a.method.kind === "skill");
|
|
9061
|
+
const skillIds = new Set(skills.map((a) => a.id));
|
|
9062
|
+
const settle = holdSkillSlots(projectDir, {
|
|
9063
|
+
recorded: (previousLog?.assets ?? []).filter((a) => a.method === "skill" && skillIds.has(a.id)),
|
|
9064
|
+
slots: skillSlotsFor(skills, spec.cli, { log: previousLog, scope: spec.scope }),
|
|
9065
|
+
log: previousLog,
|
|
9066
|
+
clis: spec.cli,
|
|
9067
|
+
scope: spec.scope
|
|
9068
|
+
});
|
|
9069
|
+
let ran;
|
|
9070
|
+
try {
|
|
9071
|
+
ran = runExt(
|
|
9072
|
+
{ ...filterCtx, cli: spec.cli, projectDir, ...spec.scope ? { scope: spec.scope } : {} },
|
|
9073
|
+
externalDeps
|
|
9074
|
+
);
|
|
9075
|
+
} catch (e2) {
|
|
9076
|
+
try {
|
|
9077
|
+
settle(null);
|
|
9078
|
+
} catch {
|
|
9079
|
+
}
|
|
9080
|
+
throw e2;
|
|
9081
|
+
}
|
|
9082
|
+
const { report: external, backups, displaced } = settle(ran);
|
|
9083
|
+
const displacedBackups = new Set(displaced.map((f) => join31(projectDir, f.notes[0] ?? "")));
|
|
9084
|
+
const editBackups = backups.filter((b2) => !displacedBackups.has(b2));
|
|
8264
9085
|
ctx.onProgress?.({
|
|
8265
9086
|
type: "external-complete",
|
|
8266
9087
|
report: external,
|
|
8267
|
-
...
|
|
9088
|
+
...editBackups.length > 0 ? { backups: editBackups } : {},
|
|
9089
|
+
...displaced.length > 0 ? { displaced: displaced.map((f) => ({ path: f.path, backup: f.notes[0] ?? "" })) } : {}
|
|
8268
9090
|
});
|
|
8269
|
-
return { report: external, backups };
|
|
9091
|
+
return { report: external, backups, displaced };
|
|
8270
9092
|
}
|
|
8271
9093
|
var InstallInterruptedError = class extends Error {
|
|
8272
9094
|
constructor(message, written, record, backups = [], hadInstall = false) {
|
|
@@ -8331,7 +9153,7 @@ function recordInterruptedInstall(ctx, error, run) {
|
|
|
8331
9153
|
const codexTrust = registeredTrust(journal.codexOptIn, ctx.projectDir);
|
|
8332
9154
|
const written = writtenSoFar(ledger, cliFiles, rootFiles, stage.rootImportWritten);
|
|
8333
9155
|
if (codexTrust) written.push(`${codexTrust.configPath} (Codex trust entry for this folder)`);
|
|
8334
|
-
const projectRel = (abs) =>
|
|
9156
|
+
const projectRel = (abs) => relative4(ctx.projectDir, abs).split(sep5).join("/");
|
|
8335
9157
|
const writtenSet = new Set(written);
|
|
8336
9158
|
const backups = [...own.backups, ...journal.backups].map((abs) => {
|
|
8337
9159
|
const original = projectRel(backupOriginal(abs) ?? abs);
|
|
@@ -8471,7 +9293,7 @@ function accumulateCategory(cats, entry) {
|
|
|
8471
9293
|
}
|
|
8472
9294
|
}
|
|
8473
9295
|
function writeRootClaudeMd(projectDir, tracks, continuousSkills, harnessRoot, writer) {
|
|
8474
|
-
const target =
|
|
9296
|
+
const target = join31(projectDir, "CLAUDE.md");
|
|
8475
9297
|
if (writer.skipOutside(target)) return null;
|
|
8476
9298
|
const existing = existsSync22(target) ? readFileSync22(target, "utf-8") : null;
|
|
8477
9299
|
const seeded = existing === null ? seedRootClaudeProjectContext(projectDir, harnessRoot) : null;
|
|
@@ -8483,7 +9305,7 @@ function writeRootClaudeMd(projectDir, tracks, continuousSkills, harnessRoot, wr
|
|
|
8483
9305
|
});
|
|
8484
9306
|
if (content !== existing) {
|
|
8485
9307
|
if (existing !== null) backupIfLossyUtf8(target);
|
|
8486
|
-
|
|
9308
|
+
writeFileSync8(target, content);
|
|
8487
9309
|
}
|
|
8488
9310
|
return {
|
|
8489
9311
|
created: existing === null,
|
|
@@ -8501,14 +9323,14 @@ function chmodHooksSync(hookDir, projectDir) {
|
|
|
8501
9323
|
}
|
|
8502
9324
|
}
|
|
8503
9325
|
function listHookFiles(hookDir) {
|
|
8504
|
-
return
|
|
9326
|
+
return readdirSync5(hookDir, { withFileTypes: true }).filter((e2) => e2.isFile() && e2.name.endsWith(".sh")).map((e2) => resolve(hookDir, e2.name));
|
|
8505
9327
|
}
|
|
8506
9328
|
|
|
8507
9329
|
// src/commands/install-render.ts
|
|
8508
9330
|
init_esm_shims();
|
|
8509
9331
|
import { homedir as homedir3 } from "os";
|
|
8510
|
-
import { existsSync as existsSync24, readdirSync as
|
|
8511
|
-
import { join as
|
|
9332
|
+
import { existsSync as existsSync24, readdirSync as readdirSync6, readFileSync as readFileSync24 } from "fs";
|
|
9333
|
+
import { join as join33, relative as relative5 } from "path";
|
|
8512
9334
|
|
|
8513
9335
|
// src/preset-recommend.ts
|
|
8514
9336
|
init_esm_shims();
|
|
@@ -8545,9 +9367,9 @@ function groupAssetsByCategory(assetIds) {
|
|
|
8545
9367
|
// src/resident-entries.ts
|
|
8546
9368
|
init_esm_shims();
|
|
8547
9369
|
import { existsSync as existsSync23, readFileSync as readFileSync23 } from "fs";
|
|
8548
|
-
import { basename as basename5, join as
|
|
9370
|
+
import { basename as basename5, join as join32 } from "path";
|
|
8549
9371
|
function residentEntries(spec) {
|
|
8550
|
-
const skillThere = (id) => INTERNAL_BUNDLED_SKILL_IDS.includes(id) && [".claude/skills", ".agents/skills"].some((d2) => existsSync23(
|
|
9372
|
+
const skillThere = (id) => INTERNAL_BUNDLED_SKILL_IDS.includes(id) && [".claude/skills", ".agents/skills"].some((d2) => existsSync23(join32(spec.projectDir, d2, id)));
|
|
8551
9373
|
const forceExclude = (spec.userOverride?.forceExclude ?? []).filter((id) => !skillThere(id));
|
|
8552
9374
|
const assetSpec = buildManifestSpec(
|
|
8553
9375
|
spec.userOverride ? { ...spec, userOverride: { ...spec.userOverride, forceExclude } } : spec
|
|
@@ -8573,7 +9395,7 @@ function residentEntries(spec) {
|
|
|
8573
9395
|
function residentCostFor(spec, entries = residentEntries(spec), contextFiles) {
|
|
8574
9396
|
if (contextFiles !== void 0) return residentCost(entries, void 0, spec.cli, contextFiles);
|
|
8575
9397
|
const cost = residentCost(entries, void 0, spec.cli, plannedClaudeContext(spec));
|
|
8576
|
-
if (anchorSurface(spec.cli).scaffold === "agents-md" && existsSync23(
|
|
9398
|
+
if (anchorSurface(spec.cli).scaffold === "agents-md" && existsSync23(join32(spec.projectDir, "AGENTS.md"))) {
|
|
8577
9399
|
return makeResidentCost({
|
|
8578
9400
|
...cost,
|
|
8579
9401
|
contextNote: "planned, not counting text already in AGENTS.md"
|
|
@@ -8584,7 +9406,7 @@ function residentCostFor(spec, entries = residentEntries(spec), contextFiles) {
|
|
|
8584
9406
|
function plannedClaudeContext(spec) {
|
|
8585
9407
|
if (!spec.cli.includes("claude")) return void 0;
|
|
8586
9408
|
const root = resolveBundleRoot();
|
|
8587
|
-
const rootClaude =
|
|
9409
|
+
const rootClaude = join32(spec.projectDir, "CLAUDE.md");
|
|
8588
9410
|
const existing = existsSync23(rootClaude) ? readFileSync23(rootClaude, "utf-8") : null;
|
|
8589
9411
|
const seeded = existing === null ? seedRootClaudeProjectContext(spec.projectDir, root) : null;
|
|
8590
9412
|
if (existing === null && seeded === null) return void 0;
|
|
@@ -8595,14 +9417,14 @@ function plannedClaudeContext(spec) {
|
|
|
8595
9417
|
continuousSkills: manifestSpec.selectedInternalSkills ?? [],
|
|
8596
9418
|
...seeded === null ? {} : { projectContext: seeded }
|
|
8597
9419
|
});
|
|
8598
|
-
return [
|
|
9420
|
+
return [join32(root, "templates", "CLAUDE.md"), { text }];
|
|
8599
9421
|
}
|
|
8600
9422
|
function onDiskTargets(spec, assetSpec) {
|
|
8601
9423
|
const out = /* @__PURE__ */ new Set();
|
|
8602
9424
|
for (const e2 of buildManifest(assetSpec)) {
|
|
8603
9425
|
if (!e2.applies(assetSpec)) continue;
|
|
8604
9426
|
const t = classifyBaselineTarget(e2.target);
|
|
8605
|
-
if (t !== null && existsSync23(
|
|
9427
|
+
if (t !== null && existsSync23(join32(spec.projectDir, e2.target))) out.add(t.id);
|
|
8606
9428
|
}
|
|
8607
9429
|
return out;
|
|
8608
9430
|
}
|
|
@@ -8665,6 +9487,14 @@ function createInstallRenderer(log, spec, verbose) {
|
|
|
8665
9487
|
phase2HeaderPrinted = true;
|
|
8666
9488
|
} else if (event.type === "external-complete") {
|
|
8667
9489
|
for (const b2 of event.backups ?? []) log(assetRow("success", "backup", shortenPath(b2)));
|
|
9490
|
+
for (const d2 of event.displaced ?? [])
|
|
9491
|
+
log(
|
|
9492
|
+
assetRow(
|
|
9493
|
+
"skip",
|
|
9494
|
+
d2.path,
|
|
9495
|
+
`had a file with this name \u2014 saved as ${d2.backup}, put back on uninstall`
|
|
9496
|
+
)
|
|
9497
|
+
);
|
|
8668
9498
|
const excluded = event.report.excludedByCli;
|
|
8669
9499
|
if (excluded.length > 0) {
|
|
8670
9500
|
if (!phase2HeaderPrinted) {
|
|
@@ -8754,23 +9584,23 @@ function residentEntriesOnDisk(spec) {
|
|
|
8754
9584
|
const hasClaude = spec.cli.includes("claude");
|
|
8755
9585
|
const surface = anchorSurface(spec.cli).scaffold;
|
|
8756
9586
|
const mdFiles = (dir, kind, skip) => {
|
|
8757
|
-
const abs =
|
|
8758
|
-
return existsSync24(abs) ?
|
|
9587
|
+
const abs = join33(spec.projectDir, dir);
|
|
9588
|
+
return existsSync24(abs) ? readdirSync6(abs, { withFileTypes: true }).filter((e2) => e2.isFile() && e2.name.endsWith(".md") && e2.name !== skip).map((e2) => ({
|
|
8759
9589
|
source: `${kind}/${e2.name}`,
|
|
8760
9590
|
// `target` 은 `residentCost` 의 분류 키다 — 실제 자리는 `file` 이 말한다.
|
|
8761
9591
|
target: `.claude/${kind}/${e2.name}`,
|
|
8762
9592
|
// 배포판이 아니라 **이 프로젝트의 파일**을 잰다 — 사용자가 고친 본문도,
|
|
8763
9593
|
// 배포판에 더는 없는 파일도 실제로 상주하는 것은 이쪽이다.
|
|
8764
|
-
file:
|
|
9594
|
+
file: join33(abs, e2.name)
|
|
8765
9595
|
})) : [];
|
|
8766
9596
|
};
|
|
8767
|
-
const rules = surface === "claude" ? mdFiles(
|
|
8768
|
-
const slot = hasClaude ?
|
|
9597
|
+
const rules = surface === "claude" ? mdFiles(join33(".claude", "rules"), "rules") : rulesInline(spec.cli) ? planned.filter((e2) => e2.target.startsWith(".claude/rules/")) : mdFiles(join33(".agents", "rules"), "rules", "uzys-harness.md");
|
|
9598
|
+
const slot = hasClaude ? join33(".claude", "skills") : join33(".agents", "skills");
|
|
8769
9599
|
const skills = planned.filter((e2) => e2.target.startsWith(".claude/skills/")).map((e2) => ({
|
|
8770
9600
|
...e2,
|
|
8771
|
-
file:
|
|
9601
|
+
file: join33(spec.projectDir, slot, e2.target.slice(".claude/skills/".length))
|
|
8772
9602
|
})).filter((e2) => existsSync24(e2.file));
|
|
8773
|
-
const agents = hasClaude ? mdFiles(
|
|
9603
|
+
const agents = hasClaude ? mdFiles(join33(".claude", "agents"), "agents") : [];
|
|
8774
9604
|
return [
|
|
8775
9605
|
...planned.filter(
|
|
8776
9606
|
(e2) => !e2.target.startsWith(".claude/rules/") && !e2.target.startsWith(".claude/agents/") && !e2.target.startsWith(".claude/skills/")
|
|
@@ -8782,8 +9612,8 @@ function residentEntriesOnDisk(spec) {
|
|
|
8782
9612
|
}
|
|
8783
9613
|
function contextFilesOnDisk(spec) {
|
|
8784
9614
|
const surface = anchorSurface(spec.cli).scaffold;
|
|
8785
|
-
const files = surface === "claude" ? [HARNESS_ANCHOR_FILE, "CLAUDE.md",
|
|
8786
|
-
return files.map((f) =>
|
|
9615
|
+
const files = surface === "claude" ? [HARNESS_ANCHOR_FILE, "CLAUDE.md", join33(".claude", "CLAUDE.md")] : ["AGENTS.md"];
|
|
9616
|
+
return files.map((f) => join33(spec.projectDir, f));
|
|
8787
9617
|
}
|
|
8788
9618
|
function rulesInsideAgentsMd(spec, cost) {
|
|
8789
9619
|
if (anchorSurface(spec.cli).scaffold !== "agents-md" || !rulesInline(spec.cli)) return cost;
|
|
@@ -9037,8 +9867,8 @@ function renderFinalSummary(log, spec, report, fromWizard) {
|
|
|
9037
9867
|
const codexTrusted = report.codexOptIn?.trustEntry.status === "registered" || report.codexOptIn?.trustEntry.status === "already-present";
|
|
9038
9868
|
const alreadyTrustedGlobally = (() => {
|
|
9039
9869
|
try {
|
|
9040
|
-
const home = process.env.CODEX_HOME ??
|
|
9041
|
-
const configPath =
|
|
9870
|
+
const home = process.env.CODEX_HOME ?? join33(homedir3(), ".codex");
|
|
9871
|
+
const configPath = join33(home, "config.toml");
|
|
9042
9872
|
if (!existsSync24(configPath)) return false;
|
|
9043
9873
|
return hasTrustEntry(readFileSync24(configPath, "utf8"), spec.projectDir);
|
|
9044
9874
|
} catch {
|
|
@@ -9065,7 +9895,7 @@ function renderFinalSummary(log, spec, report, fromWizard) {
|
|
|
9065
9895
|
const remote = (report.shared ?? []).find((f) => f.path === ".mcp.json")?.remote ?? [];
|
|
9066
9896
|
for (const line of remoteMcpNextLines(remote, spec.cli)) log(`${" ".repeat(16)} ${line}`);
|
|
9067
9897
|
const scaffoldFiles = scaffoldFilesForCli(spec.cli).filter(
|
|
9068
|
-
(f) => f === "CLAUDE.md" && report.rootClaudeMd?.created === true || hasFillPrompt(
|
|
9898
|
+
(f) => f === "CLAUDE.md" && report.rootClaudeMd?.created === true || hasFillPrompt(join33(spec.projectDir, f))
|
|
9069
9899
|
);
|
|
9070
9900
|
if (scaffoldFiles.length > 0) {
|
|
9071
9901
|
const auditInstalled = buildManifestSpec(spec).selectedInternalSkills?.includes("audit-harness-fit");
|
|
@@ -9205,6 +10035,7 @@ function renderPhase1Rows(log, baseline, verbose = false) {
|
|
|
9205
10035
|
const retired = anchorRetireRow(baseline.updateMode.anchorRetired ?? null);
|
|
9206
10036
|
if (retired) log(retired);
|
|
9207
10037
|
for (const row of outOfTrackRows(baseline.updateMode.outOfTrack)) log(row);
|
|
10038
|
+
for (const row of displacedRows(baseline.updateMode.displacedRestored)) log(row);
|
|
9208
10039
|
for (const f of baseline.updateMode.sharedWrites ?? []) {
|
|
9209
10040
|
const row = sharedFileRow(f);
|
|
9210
10041
|
if (row !== null) log(row);
|
|
@@ -9411,6 +10242,26 @@ function renderPhase1Rows(log, baseline, verbose = false) {
|
|
|
9411
10242
|
)
|
|
9412
10243
|
);
|
|
9413
10244
|
}
|
|
10245
|
+
const legacyDropped = baseline.updateMode.agentsMdLegacyDropped ?? 0;
|
|
10246
|
+
if (legacyDropped > 0) {
|
|
10247
|
+
log(
|
|
10248
|
+
assetRow(
|
|
10249
|
+
"success",
|
|
10250
|
+
"AGENTS.md",
|
|
10251
|
+
`removed ${legacyDropped} section(s) written by an older harness version (saved a copy as AGENTS.md.backup-<time>)`
|
|
10252
|
+
)
|
|
10253
|
+
);
|
|
10254
|
+
}
|
|
10255
|
+
const legacyEdited = baseline.updateMode.agentsMdLegacyEdited ?? [];
|
|
10256
|
+
if (legacyEdited.length > 0) {
|
|
10257
|
+
log(
|
|
10258
|
+
assetRow(
|
|
10259
|
+
"skip",
|
|
10260
|
+
"AGENTS.md",
|
|
10261
|
+
`${legacyEdited.length} harness section(s) you had edited (${legacyEdited.join(" \xB7 ")}) now hold the current version \u2014 your edit is in the copy AGENTS.md.backup-<time>`
|
|
10262
|
+
)
|
|
10263
|
+
);
|
|
10264
|
+
}
|
|
9414
10265
|
const externalEdited = baseline.updateMode.externalBackedUp.filter((p2) => !noChecksum.has(p2));
|
|
9415
10266
|
if (externalEdited.length > 0) {
|
|
9416
10267
|
log(
|
|
@@ -9499,6 +10350,7 @@ function renderPhase1Rows(log, baseline, verbose = false) {
|
|
|
9499
10350
|
}
|
|
9500
10351
|
for (const row of outsideLinkRows(baseline.outsideLinks ?? [])) log(row);
|
|
9501
10352
|
for (const row of outOfTrackRows(baseline.outOfTrack)) log(row);
|
|
10353
|
+
for (const row of displacedRows(baseline.displacedRestored)) log(row);
|
|
9502
10354
|
if (baseline.backups) {
|
|
9503
10355
|
for (const b2 of baseline.backups) {
|
|
9504
10356
|
if (judgedBackups.has(b2)) continue;
|
|
@@ -9638,6 +10490,11 @@ function renderPhase1Rows(log, baseline, verbose = false) {
|
|
|
9638
10490
|
function judgedRow(j4) {
|
|
9639
10491
|
return j4.backup !== void 0 ? ` ${c.green(symbol.success)} backed up ${j4.path} \u2014 ${j4.line}` : ` ${c.yellow(symbol.skip)} ${j4.path} \u2014 ${j4.line}`;
|
|
9640
10492
|
}
|
|
10493
|
+
function displacedRows(outcomes) {
|
|
10494
|
+
return (outcomes ?? []).flatMap(
|
|
10495
|
+
(d2) => d2.verdict === "restore" ? [assetRow("success", d2.path, `yours \u2014 put back (from ${d2.backup})`)] : d2.verdict === "advise" ? [assetRow("skip", d2.path, d2.line)] : []
|
|
10496
|
+
);
|
|
10497
|
+
}
|
|
9641
10498
|
function outOfTrackRows(r) {
|
|
9642
10499
|
if (r === void 0) return [];
|
|
9643
10500
|
const recorded2 = r.recordedTracks.join(", ");
|
|
@@ -9674,16 +10531,16 @@ function outOfTrackRows(r) {
|
|
|
9674
10531
|
function outsideLinkRows(links) {
|
|
9675
10532
|
const groups = /* @__PURE__ */ new Map();
|
|
9676
10533
|
for (const o of links) groups.set(o.link, [...groups.get(o.link) ?? [], o]);
|
|
9677
|
-
const
|
|
10534
|
+
const rows2 = [];
|
|
9678
10535
|
for (const [link, group] of groups) {
|
|
9679
10536
|
const first = group[0];
|
|
9680
10537
|
if (first === void 0) continue;
|
|
9681
10538
|
const fileLink = group.length === 1 && first.path === link;
|
|
9682
|
-
|
|
10539
|
+
rows2.push(
|
|
9683
10540
|
fileLink ? ` ${c.yellow(symbol.skip)} ${link} \u2014 left as is: the link points outside the project (${first.linkTarget}). Not written; replace the link with a regular file to get the harness version.` : ` ${c.yellow(symbol.skip)} ${link}/ \u2014 left as is: the link points outside the project (${first.linkTarget}), ${group.length} file(s) not written. Replace the link with a regular folder to get the harness version.`
|
|
9684
10541
|
);
|
|
9685
10542
|
}
|
|
9686
|
-
return
|
|
10543
|
+
return rows2;
|
|
9687
10544
|
}
|
|
9688
10545
|
function sharedFileRow(f) {
|
|
9689
10546
|
if (f.line === "") return null;
|
|
@@ -9872,7 +10729,7 @@ function renderInterruptedInstall(err, e2, cwd = process.cwd()) {
|
|
|
9872
10729
|
}
|
|
9873
10730
|
const { path, error } = e2.record;
|
|
9874
10731
|
err(
|
|
9875
|
-
path !== null ? ` Already in place before it stopped \u2014 recorded in ${
|
|
10732
|
+
path !== null ? ` Already in place before it stopped \u2014 recorded in ${relative5(cwd, path) || path}:` : " Already in place before it stopped:"
|
|
9876
10733
|
);
|
|
9877
10734
|
for (const [key, n] of groups) {
|
|
9878
10735
|
err(` ${key.endsWith("/") ? `${key} (${n} file${n === 1 ? "" : "s"})` : key}`);
|
|
@@ -10196,7 +11053,7 @@ function registerInstallCommand(cli) {
|
|
|
10196
11053
|
// src/commands/list.ts
|
|
10197
11054
|
init_esm_shims();
|
|
10198
11055
|
import { existsSync as existsSync25, readFileSync as readFileSync25 } from "fs";
|
|
10199
|
-
import { join as
|
|
11056
|
+
import { join as join34, resolve as resolve3 } from "path";
|
|
10200
11057
|
function listAction(options = {}, deps = {}) {
|
|
10201
11058
|
const log = deps.log ?? console.log;
|
|
10202
11059
|
const err = deps.err ?? console.error;
|
|
@@ -10247,33 +11104,33 @@ function listAction(options = {}, deps = {}) {
|
|
|
10247
11104
|
}
|
|
10248
11105
|
var SELECTIONS_SHOWN = 10;
|
|
10249
11106
|
function formatSelectionRows(log, projectDir) {
|
|
10250
|
-
const
|
|
11107
|
+
const rows2 = [];
|
|
10251
11108
|
const excluded = [...excludedIds(log)].sort();
|
|
10252
|
-
if (excluded.length === 0)
|
|
11109
|
+
if (excluded.length === 0) rows2.push(c.dim(" excluded: (none)"));
|
|
10253
11110
|
const still = new Set(
|
|
10254
11111
|
excludedStillThere(projectDir, new Set(excluded), [], log).map((e2) => e2.id)
|
|
10255
11112
|
);
|
|
10256
11113
|
for (const id of excluded) {
|
|
10257
11114
|
const kind = id.startsWith("baseline:") ? "baseline" : isKeyId(id) ? "harness part" : "asset";
|
|
10258
|
-
|
|
11115
|
+
rows2.push(` \u2298 ${id} ${c.dim(`(${kind}${still.has(id) ? " \xB7 still on disk" : ""})`)}`);
|
|
10259
11116
|
}
|
|
10260
11117
|
const history = (log.selections ?? []).slice(-SELECTIONS_SHOWN);
|
|
10261
|
-
if (history.length > 0)
|
|
11118
|
+
if (history.length > 0) rows2.push(c.dim(` history (latest ${history.length}):`));
|
|
10262
11119
|
for (const ev of history) {
|
|
10263
11120
|
const day = ev.at.slice(0, 10);
|
|
10264
11121
|
const parts = [];
|
|
10265
11122
|
if (ev.by === "migration") {
|
|
10266
11123
|
if (ev.released?.length) parts.push(`released ${ev.released.join(", ")}`);
|
|
10267
11124
|
if (ev.kept?.length) parts.push(`kept ${ev.kept.join(", ")}`);
|
|
10268
|
-
|
|
11125
|
+
rows2.push(` ${day} migration (26.162\u201326.163 record): ${parts.join(" \xB7 ")}`);
|
|
10269
11126
|
continue;
|
|
10270
11127
|
}
|
|
10271
11128
|
if (ev.without?.length) parts.push(`--without ${ev.without.join(", ")}`);
|
|
10272
11129
|
if (ev.with?.length) parts.push(`re-added ${ev.with.join(", ")}`);
|
|
10273
11130
|
const tags = [ev.via === "wizard" ? "wizard" : "", ev.interrupted ? "interrupted" : ""].filter(Boolean).join(", ");
|
|
10274
|
-
|
|
11131
|
+
rows2.push(` ${day} install ${parts.join(" \xB7 ")}${tags ? ` (${tags})` : ""}`);
|
|
10275
11132
|
}
|
|
10276
|
-
return
|
|
11133
|
+
return rows2;
|
|
10277
11134
|
}
|
|
10278
11135
|
function formatAssetRows(assets) {
|
|
10279
11136
|
const idWidth = Math.max(0, ...assets.map((a) => a.id.length));
|
|
@@ -10296,16 +11153,16 @@ function harnessFileTops(log) {
|
|
|
10296
11153
|
}
|
|
10297
11154
|
function formatHarnessFileRows(log, projectDir) {
|
|
10298
11155
|
const tops = harnessFileTops(log);
|
|
10299
|
-
const
|
|
11156
|
+
const rows2 = [` ${c.dim(tops.length > 0 ? tops.join(" ") : "(none recorded)")}`];
|
|
10300
11157
|
const rootMd = log.templates.rootClaudeMd;
|
|
10301
11158
|
if (rootMd) {
|
|
10302
|
-
const path =
|
|
11159
|
+
const path = join34(projectDir, rootMd.path);
|
|
10303
11160
|
const modified = existsSync25(path) && hashContent(readFileSync25(path, "utf8")) !== rootMd.sha256;
|
|
10304
|
-
|
|
11161
|
+
rows2.push(
|
|
10305
11162
|
modified ? ` ${c.dim(rootMd.path)} ${c.yellow("(\uC218\uC815\uB428 \u2014 uninstall \uC2DC \uBCF4\uC874)")}` : ` ${c.dim(rootMd.path)}`
|
|
10306
11163
|
);
|
|
10307
11164
|
}
|
|
10308
|
-
return
|
|
11165
|
+
return rows2;
|
|
10309
11166
|
}
|
|
10310
11167
|
var ROOT_FILE_CHANGE = {
|
|
10311
11168
|
created: "\uC0DD\uC131",
|
|
@@ -10314,7 +11171,7 @@ var ROOT_FILE_CHANGE = {
|
|
|
10314
11171
|
displaced: "\uBE44\uCF1C \uB460"
|
|
10315
11172
|
};
|
|
10316
11173
|
function formatRootFileRows(rootFiles, projectDir) {
|
|
10317
|
-
const present2 = rootFiles.filter((f) => existsSync25(
|
|
11174
|
+
const present2 = rootFiles.filter((f) => existsSync25(join34(projectDir, f.path)));
|
|
10318
11175
|
const width = Math.max(0, ...present2.map((f) => f.path.length));
|
|
10319
11176
|
return present2.map(
|
|
10320
11177
|
(f) => ` ${c.dim(padDisplay(f.path, width))} ${c.dim(ROOT_FILE_CHANGE[f.change])} ${c.dim(f.notes.join(" / "))}`
|
|
@@ -10332,22 +11189,20 @@ function registerListCommand(cli) {
|
|
|
10332
11189
|
init_esm_shims();
|
|
10333
11190
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
10334
11191
|
import {
|
|
10335
|
-
accessSync,
|
|
11192
|
+
accessSync as accessSync2,
|
|
10336
11193
|
existsSync as existsSync26,
|
|
10337
|
-
constants as
|
|
10338
|
-
lstatSync as
|
|
10339
|
-
|
|
10340
|
-
readdirSync as readdirSync6,
|
|
11194
|
+
constants as fsConstants2,
|
|
11195
|
+
lstatSync as lstatSync6,
|
|
11196
|
+
readdirSync as readdirSync7,
|
|
10341
11197
|
readFileSync as readFileSync26,
|
|
10342
11198
|
readlinkSync,
|
|
10343
11199
|
realpathSync as realpathSync3,
|
|
10344
|
-
|
|
10345
|
-
|
|
10346
|
-
rmSync as rmSync4,
|
|
11200
|
+
rmdirSync as rmdirSync3,
|
|
11201
|
+
rmSync as rmSync5,
|
|
10347
11202
|
statSync as statSync5,
|
|
10348
|
-
writeFileSync as
|
|
11203
|
+
writeFileSync as writeFileSync9
|
|
10349
11204
|
} from "fs";
|
|
10350
|
-
import { dirname as
|
|
11205
|
+
import { dirname as dirname8, join as join35, relative as relative6, resolve as resolve4, sep as sep6 } from "path";
|
|
10351
11206
|
|
|
10352
11207
|
// src/uninstall-interactive.ts
|
|
10353
11208
|
init_esm_shims();
|
|
@@ -10537,11 +11392,11 @@ var getClosingCode = (openingCode) => {
|
|
|
10537
11392
|
};
|
|
10538
11393
|
var wrapAnsiCode = (code) => `${ESC}${ANSI_CSI}${code}${ANSI_SGR_TERMINATOR}`;
|
|
10539
11394
|
var wrapAnsiHyperlink = (url) => `${ESC}${ANSI_ESCAPE_LINK}${url}${ANSI_ESCAPE_BELL}`;
|
|
10540
|
-
var wrapWord = (
|
|
11395
|
+
var wrapWord = (rows2, word, columns) => {
|
|
10541
11396
|
const characters = word[Symbol.iterator]();
|
|
10542
11397
|
let isInsideEscape = false;
|
|
10543
11398
|
let isInsideLinkEscape = false;
|
|
10544
|
-
let lastRow =
|
|
11399
|
+
let lastRow = rows2.at(-1);
|
|
10545
11400
|
let visible = lastRow === void 0 ? 0 : dist_default2(lastRow);
|
|
10546
11401
|
let currentCharacter = characters.next();
|
|
10547
11402
|
let nextCharacter = characters.next();
|
|
@@ -10550,9 +11405,9 @@ var wrapWord = (rows, word, columns) => {
|
|
|
10550
11405
|
const character = currentCharacter.value;
|
|
10551
11406
|
const characterLength = dist_default2(character);
|
|
10552
11407
|
if (visible + characterLength <= columns) {
|
|
10553
|
-
|
|
11408
|
+
rows2[rows2.length - 1] += character;
|
|
10554
11409
|
} else {
|
|
10555
|
-
|
|
11410
|
+
rows2.push(character);
|
|
10556
11411
|
visible = 0;
|
|
10557
11412
|
}
|
|
10558
11413
|
if (character === ESC || character === CSI) {
|
|
@@ -10571,7 +11426,7 @@ var wrapWord = (rows, word, columns) => {
|
|
|
10571
11426
|
} else {
|
|
10572
11427
|
visible += characterLength;
|
|
10573
11428
|
if (visible === columns && !nextCharacter.done) {
|
|
10574
|
-
|
|
11429
|
+
rows2.push("");
|
|
10575
11430
|
visible = 0;
|
|
10576
11431
|
}
|
|
10577
11432
|
}
|
|
@@ -10579,9 +11434,9 @@ var wrapWord = (rows, word, columns) => {
|
|
|
10579
11434
|
nextCharacter = characters.next();
|
|
10580
11435
|
rawCharacterIndex += character.length;
|
|
10581
11436
|
}
|
|
10582
|
-
lastRow =
|
|
10583
|
-
if (!visible && lastRow !== void 0 && lastRow.length &&
|
|
10584
|
-
|
|
11437
|
+
lastRow = rows2.at(-1);
|
|
11438
|
+
if (!visible && lastRow !== void 0 && lastRow.length && rows2.length > 1) {
|
|
11439
|
+
rows2[rows2.length - 2] += rows2.pop();
|
|
10585
11440
|
}
|
|
10586
11441
|
};
|
|
10587
11442
|
var stringVisibleTrimSpacesRight = (string) => {
|
|
@@ -10606,25 +11461,25 @@ var exec = (string, columns, options = {}) => {
|
|
|
10606
11461
|
let escapeCode;
|
|
10607
11462
|
let escapeUrl;
|
|
10608
11463
|
const words = string.split(" ");
|
|
10609
|
-
let
|
|
11464
|
+
let rows2 = [""];
|
|
10610
11465
|
let rowLength = 0;
|
|
10611
11466
|
for (let index = 0; index < words.length; index++) {
|
|
10612
11467
|
const word = words[index];
|
|
10613
11468
|
if (options.trim !== false) {
|
|
10614
|
-
const row =
|
|
11469
|
+
const row = rows2.at(-1) ?? "";
|
|
10615
11470
|
const trimmed = row.trimStart();
|
|
10616
11471
|
if (row.length !== trimmed.length) {
|
|
10617
|
-
|
|
11472
|
+
rows2[rows2.length - 1] = trimmed;
|
|
10618
11473
|
rowLength = dist_default2(trimmed);
|
|
10619
11474
|
}
|
|
10620
11475
|
}
|
|
10621
11476
|
if (index !== 0) {
|
|
10622
11477
|
if (rowLength >= columns && (options.wordWrap === false || options.trim === false)) {
|
|
10623
|
-
|
|
11478
|
+
rows2.push("");
|
|
10624
11479
|
rowLength = 0;
|
|
10625
11480
|
}
|
|
10626
11481
|
if (rowLength || options.trim === false) {
|
|
10627
|
-
|
|
11482
|
+
rows2[rows2.length - 1] += " ";
|
|
10628
11483
|
rowLength++;
|
|
10629
11484
|
}
|
|
10630
11485
|
}
|
|
@@ -10634,33 +11489,33 @@ var exec = (string, columns, options = {}) => {
|
|
|
10634
11489
|
const breaksStartingThisLine = 1 + Math.floor((wordLength - remainingColumns - 1) / columns);
|
|
10635
11490
|
const breaksStartingNextLine = Math.floor((wordLength - 1) / columns);
|
|
10636
11491
|
if (breaksStartingNextLine < breaksStartingThisLine) {
|
|
10637
|
-
|
|
11492
|
+
rows2.push("");
|
|
10638
11493
|
}
|
|
10639
|
-
wrapWord(
|
|
10640
|
-
rowLength = dist_default2(
|
|
11494
|
+
wrapWord(rows2, word, columns);
|
|
11495
|
+
rowLength = dist_default2(rows2.at(-1) ?? "");
|
|
10641
11496
|
continue;
|
|
10642
11497
|
}
|
|
10643
11498
|
if (rowLength + wordLength > columns && rowLength && wordLength) {
|
|
10644
11499
|
if (options.wordWrap === false && rowLength < columns) {
|
|
10645
|
-
wrapWord(
|
|
10646
|
-
rowLength = dist_default2(
|
|
11500
|
+
wrapWord(rows2, word, columns);
|
|
11501
|
+
rowLength = dist_default2(rows2.at(-1) ?? "");
|
|
10647
11502
|
continue;
|
|
10648
11503
|
}
|
|
10649
|
-
|
|
11504
|
+
rows2.push("");
|
|
10650
11505
|
rowLength = 0;
|
|
10651
11506
|
}
|
|
10652
11507
|
if (rowLength + wordLength > columns && options.wordWrap === false) {
|
|
10653
|
-
wrapWord(
|
|
10654
|
-
rowLength = dist_default2(
|
|
11508
|
+
wrapWord(rows2, word, columns);
|
|
11509
|
+
rowLength = dist_default2(rows2.at(-1) ?? "");
|
|
10655
11510
|
continue;
|
|
10656
11511
|
}
|
|
10657
|
-
|
|
11512
|
+
rows2[rows2.length - 1] += word;
|
|
10658
11513
|
rowLength += wordLength;
|
|
10659
11514
|
}
|
|
10660
11515
|
if (options.trim !== false) {
|
|
10661
|
-
|
|
11516
|
+
rows2 = rows2.map((row) => stringVisibleTrimSpacesRight(row));
|
|
10662
11517
|
}
|
|
10663
|
-
const preString =
|
|
11518
|
+
const preString = rows2.join("\n");
|
|
10664
11519
|
let inSurrogate = false;
|
|
10665
11520
|
for (let i = 0; i < preString.length; i++) {
|
|
10666
11521
|
const character = preString[i];
|
|
@@ -11544,8 +12399,8 @@ function assertPagesCoverAllCategories(pages) {
|
|
|
11544
12399
|
}
|
|
11545
12400
|
assertPagesCoverAllCategories(INSTALL_TARGET_PAGES);
|
|
11546
12401
|
function viewportItems(itemCount) {
|
|
11547
|
-
const
|
|
11548
|
-
return Math.max(8, Math.min(itemCount,
|
|
12402
|
+
const rows2 = process.stdout.rows ?? 24;
|
|
12403
|
+
return Math.max(8, Math.min(itemCount, rows2 - 10));
|
|
11549
12404
|
}
|
|
11550
12405
|
var defaultPrompts = {
|
|
11551
12406
|
intro: (msg) => ge(msg),
|
|
@@ -11854,11 +12709,11 @@ async function runInteractiveUninstall(projectDir, deps = {}) {
|
|
|
11854
12709
|
const log = readLog(projectDir);
|
|
11855
12710
|
if (!log) return { ok: false, reason: "no-log" };
|
|
11856
12711
|
if (!deps.embedded) prompts.intro("uzys-agent-harness \xB7 uninstall");
|
|
11857
|
-
const
|
|
12712
|
+
const rows2 = buildRemovableRows(log.assets);
|
|
11858
12713
|
const clis = installedClis(log);
|
|
11859
12714
|
const mode = await prompts.selectMode(
|
|
11860
|
-
buildUninstallModeChoices(clis,
|
|
11861
|
-
`uzys-agent-harness \xB7 uninstall installed: ${clis.join(", ") || "(none)"} \xB7 assets ${
|
|
12715
|
+
buildUninstallModeChoices(clis, rows2.length),
|
|
12716
|
+
`uzys-agent-harness \xB7 uninstall installed: ${clis.join(", ") || "(none)"} \xB7 assets ${rows2.length}`
|
|
11862
12717
|
);
|
|
11863
12718
|
if (mode === null) {
|
|
11864
12719
|
prompts.cancel("Cancelled.");
|
|
@@ -11885,7 +12740,7 @@ async function runInteractiveUninstall(projectDir, deps = {}) {
|
|
|
11885
12740
|
}
|
|
11886
12741
|
return { ok: true, options: { projectDir } };
|
|
11887
12742
|
}
|
|
11888
|
-
const picked = await prompts.selectAssets(
|
|
12743
|
+
const picked = await prompts.selectAssets(rows2);
|
|
11889
12744
|
if (picked === null) {
|
|
11890
12745
|
prompts.cancel("Cancelled.");
|
|
11891
12746
|
return { ok: false, reason: "cancelled" };
|
|
@@ -11944,18 +12799,18 @@ function defaultUninstallPrompts() {
|
|
|
11944
12799
|
});
|
|
11945
12800
|
return q(r) ? null : r;
|
|
11946
12801
|
},
|
|
11947
|
-
selectCli: async (
|
|
12802
|
+
selectCli: async (rows2) => {
|
|
11948
12803
|
const r = await Ee({
|
|
11949
12804
|
message: 'Which CLI? (the last remaining CLI cannot be removed this way \u2014 use "Remove everything")',
|
|
11950
|
-
options:
|
|
12805
|
+
options: rows2.map((x) => ({ value: x.value, label: x.label, hint: x.hint }))
|
|
11951
12806
|
});
|
|
11952
12807
|
return q(r) ? null : r;
|
|
11953
12808
|
},
|
|
11954
|
-
selectAssets: async (
|
|
11955
|
-
if (
|
|
12809
|
+
selectAssets: async (rows2) => {
|
|
12810
|
+
if (rows2.length === 0) return [];
|
|
11956
12811
|
const r = await ve({
|
|
11957
12812
|
message: "Assets to remove (Space toggle \xB7 Enter confirm \xB7 ESC cancel)",
|
|
11958
|
-
options:
|
|
12813
|
+
options: rows2.map((x) => ({ value: x.value, label: x.label, hint: x.hint })),
|
|
11959
12814
|
required: false
|
|
11960
12815
|
});
|
|
11961
12816
|
return q(r) ? null : r;
|
|
@@ -12087,9 +12942,20 @@ function uninstallAction(options, deps = {}) {
|
|
|
12087
12942
|
}
|
|
12088
12943
|
const logSurvives = selectedIds !== null;
|
|
12089
12944
|
let reversed;
|
|
12945
|
+
let onlyDisplaced = [];
|
|
12090
12946
|
try {
|
|
12091
12947
|
reversed = executeReverse(plan, log, logSurvives, journal);
|
|
12092
|
-
if (
|
|
12948
|
+
if (assetsOnly) {
|
|
12949
|
+
const removed = new Set(reversed.removedIds);
|
|
12950
|
+
onlyDisplaced = restoreDisplaced(installLog, projectDir, {
|
|
12951
|
+
has: inAssetSlots(installLog.assets.filter((a) => removed.has(a.id))),
|
|
12952
|
+
write: true
|
|
12953
|
+
});
|
|
12954
|
+
for (const d2 of onlyDisplaced) {
|
|
12955
|
+
if (d2.verdict === "restore") journal.push(`put back ${d2.path}`);
|
|
12956
|
+
}
|
|
12957
|
+
for (const line of displacedLines(onlyDisplaced, false)) log(line);
|
|
12958
|
+
} else {
|
|
12093
12959
|
const done = removeHarnessFiles(installLog, projectDir, FULL_SCOPE, {
|
|
12094
12960
|
rm: rmJ,
|
|
12095
12961
|
write: true,
|
|
@@ -12125,7 +12991,7 @@ function uninstallAction(options, deps = {}) {
|
|
|
12125
12991
|
}
|
|
12126
12992
|
const { succeeded, failed, removedIds } = reversed;
|
|
12127
12993
|
const logWriteFailed = settleLog(
|
|
12128
|
-
{ installLog, projectDir, selectedIds, removedIds },
|
|
12994
|
+
{ installLog, projectDir, selectedIds, removedIds, displaced: onlyDisplaced },
|
|
12129
12995
|
{ log, err, rm, writeLog }
|
|
12130
12996
|
);
|
|
12131
12997
|
for (const line of advisoryLines(plan, projectDir, rootFiles, globalTrust)) {
|
|
@@ -12154,11 +13020,11 @@ function unwritablePaths(ctx) {
|
|
|
12154
13020
|
const project = ctx.targetAssets.filter((a) => a.scope === "project");
|
|
12155
13021
|
if (project.some((a) => a.method === "npm")) need.add(".");
|
|
12156
13022
|
const parentOf = (path) => {
|
|
12157
|
-
const abs =
|
|
13023
|
+
const abs = join35(projectDir, path);
|
|
12158
13024
|
if (!safeExists(abs)) return;
|
|
12159
13025
|
const real = safeRealpath(abs);
|
|
12160
13026
|
if (real !== null && isOutsideProject(projectDir, real)) return;
|
|
12161
|
-
need.add(
|
|
13027
|
+
need.add(dirname8(path));
|
|
12162
13028
|
};
|
|
12163
13029
|
for (const a of project)
|
|
12164
13030
|
if (a.method === "skill") for (const f of a.files ?? []) parentOf(f.path);
|
|
@@ -12166,16 +13032,17 @@ function unwritablePaths(ctx) {
|
|
|
12166
13032
|
const recordedShared = new Set((installLog.portions ?? []).map((p2) => p2.path));
|
|
12167
13033
|
const made = new Set((installLog.externalFiles ?? []).map((f) => f.path));
|
|
12168
13034
|
for (const p2 of UNINSTALL_SHARED) {
|
|
12169
|
-
if (recordedShared.has(p2) && existsSync26(
|
|
13035
|
+
if (recordedShared.has(p2) && existsSync26(join35(projectDir, p2))) need.add(p2);
|
|
12170
13036
|
if (made.has(p2)) parentOf(p2);
|
|
12171
13037
|
}
|
|
12172
13038
|
for (const p2 of harnessCandidates(installLog)) parentOf(p2);
|
|
13039
|
+
for (const p2 of legacyFileCandidates()) parentOf(p2);
|
|
12173
13040
|
for (const f of installLog.rootFiles ?? []) if (f.change === "displaced") parentOf(f.path);
|
|
12174
13041
|
if (hasRootImport(projectDir)) need.add("CLAUDE.md");
|
|
12175
13042
|
}
|
|
12176
13043
|
return [...need].filter((p2) => {
|
|
12177
13044
|
try {
|
|
12178
|
-
|
|
13045
|
+
accessSync2(join35(projectDir, p2), fsConstants2.W_OK);
|
|
12179
13046
|
return false;
|
|
12180
13047
|
} catch (e2) {
|
|
12181
13048
|
return e2.code !== "ENOENT";
|
|
@@ -12184,7 +13051,7 @@ function unwritablePaths(ctx) {
|
|
|
12184
13051
|
}
|
|
12185
13052
|
function safeExists(abs) {
|
|
12186
13053
|
try {
|
|
12187
|
-
|
|
13054
|
+
lstatSync6(abs);
|
|
12188
13055
|
return true;
|
|
12189
13056
|
} catch {
|
|
12190
13057
|
return false;
|
|
@@ -12249,8 +13116,9 @@ function settleLog(ctx, io) {
|
|
|
12249
13116
|
const { installLog, projectDir, selectedIds, removedIds } = ctx;
|
|
12250
13117
|
if (selectedIds) {
|
|
12251
13118
|
const remaining = installLog.assets.filter((a) => !removedIds.includes(a.id));
|
|
13119
|
+
const rootFiles = ctx.displaced.some((d2) => d2.forget) ? { rootFiles: withoutRestored(installLog.rootFiles, ctx.displaced) } : {};
|
|
12252
13120
|
try {
|
|
12253
|
-
io.writeLog(projectDir, { ...installLog, assets: remaining });
|
|
13121
|
+
io.writeLog(projectDir, { ...installLog, assets: remaining, ...rootFiles });
|
|
12254
13122
|
io.log(` ${status.success(`install log updated (${remaining.length} asset(s) remain)`)}`);
|
|
12255
13123
|
} catch (e2) {
|
|
12256
13124
|
io.err(status.failure(c.red(`ERROR: install log \uAC31\uC2E0 \uC2E4\uD328 \u2014 ${installLogPath(projectDir)}`)));
|
|
@@ -12259,10 +13127,10 @@ function settleLog(ctx, io) {
|
|
|
12259
13127
|
return true;
|
|
12260
13128
|
}
|
|
12261
13129
|
} else {
|
|
12262
|
-
io.rm(
|
|
13130
|
+
io.rm(join35(projectDir, INSTALL_LOG_DIR));
|
|
12263
13131
|
if (outsideLinkAt(projectDir, LEGACY_INSTALL_LOG_DIR) === null) {
|
|
12264
13132
|
io.rm(legacyInstallLogPath(projectDir));
|
|
12265
|
-
pruneEmptyDirsUpward(projectDir,
|
|
13133
|
+
pruneEmptyDirsUpward(projectDir, join35(projectDir, LEGACY_INSTALL_LOG_DIR));
|
|
12266
13134
|
}
|
|
12267
13135
|
io.log(` ${status.success("install log removed")}`);
|
|
12268
13136
|
}
|
|
@@ -12286,9 +13154,17 @@ function dryRunLines(plan, installLog, projectDir, assetsOnly, rootFiles, harnes
|
|
|
12286
13154
|
rm: () => {
|
|
12287
13155
|
},
|
|
12288
13156
|
write: false,
|
|
12289
|
-
harnessRoot
|
|
13157
|
+
harnessRoot,
|
|
13158
|
+
assetFilesGone: plannedAssetFiles(plan, installLog)
|
|
12290
13159
|
});
|
|
12291
13160
|
lines2.push(...harnessRemovalLines(preview, installLog, projectDir, FULL_SCOPE, true));
|
|
13161
|
+
} else {
|
|
13162
|
+
const preview = restoreDisplaced(installLog, projectDir, {
|
|
13163
|
+
has: inAssetSlots(plannedAssets(plan, installLog)),
|
|
13164
|
+
willBeGone: new Set(plannedAssetFiles(plan, installLog)),
|
|
13165
|
+
write: false
|
|
13166
|
+
});
|
|
13167
|
+
lines2.push(...displacedLines(preview, true));
|
|
12292
13168
|
}
|
|
12293
13169
|
lines2.push(...advisoryLines(plan, projectDir, rootFiles, globalTrust), "");
|
|
12294
13170
|
return lines2;
|
|
@@ -12320,7 +13196,7 @@ function advisoryLines(plan, projectDir, rootFiles, globalTrust) {
|
|
|
12320
13196
|
}
|
|
12321
13197
|
function backupArtifactAdvisoryLines(projectDir) {
|
|
12322
13198
|
const found = [];
|
|
12323
|
-
for (const e2 of
|
|
13199
|
+
for (const e2 of readdirSync7(projectDir, { withFileTypes: true })) {
|
|
12324
13200
|
if (CLI_FOLDERS2.some((d2) => e2.name.startsWith(`${d2}.backup-`))) {
|
|
12325
13201
|
found.push(e2.name);
|
|
12326
13202
|
} else if (e2.isFile() && BACKUP_SUFFIX.test(e2.name)) {
|
|
@@ -12329,7 +13205,7 @@ function backupArtifactAdvisoryLines(projectDir) {
|
|
|
12329
13205
|
}
|
|
12330
13206
|
for (const dir of BACKUP_SCAN_DIRS) {
|
|
12331
13207
|
if (dir === INSTALL_LOG_DIR) continue;
|
|
12332
|
-
const abs =
|
|
13208
|
+
const abs = join35(projectDir, dir);
|
|
12333
13209
|
if (!existsSync26(abs) || outsideLinkAt(projectDir, dir) !== null) continue;
|
|
12334
13210
|
for (const rel of listFilesRecursive(abs)) {
|
|
12335
13211
|
if (BACKUP_SUFFIX.test(rel)) found.push(`${dir}/${rel}`);
|
|
@@ -12345,11 +13221,11 @@ function backupArtifactAdvisoryLines(projectDir) {
|
|
|
12345
13221
|
}
|
|
12346
13222
|
function rootFileAdvisoryLines(rootFiles, projectDir) {
|
|
12347
13223
|
const header = "[ROOT] `.claude/` \uBC16\uC5D0 \uB0A8\uB294 \uAC83 (\uC790\uB3D9\uC73C\uB85C \uC9C0\uC6B0\uC9C0 \uC54A\uB294\uB2E4):";
|
|
12348
|
-
const present2 = rootFiles.filter((f) => existsSync26(
|
|
13224
|
+
const present2 = rootFiles.filter((f) => existsSync26(join35(projectDir, f.path)));
|
|
12349
13225
|
if (present2.length === 0) return [];
|
|
12350
13226
|
const outside = /* @__PURE__ */ new Map();
|
|
12351
13227
|
const inside = present2.filter((f) => {
|
|
12352
|
-
const o = outsideProjectTarget(projectDir,
|
|
13228
|
+
const o = outsideProjectTarget(projectDir, join35(projectDir, f.path));
|
|
12353
13229
|
if (o === null) return true;
|
|
12354
13230
|
const group = outside.get(o.link) ?? { link: o, files: [] };
|
|
12355
13231
|
group.files.push(f.path);
|
|
@@ -12388,7 +13264,7 @@ function rootFileMeaning(f, projectDir) {
|
|
|
12388
13264
|
case "displaced": {
|
|
12389
13265
|
const backup = f.notes[0];
|
|
12390
13266
|
if (backup === void 0) return "\uD558\uB124\uC2A4 \uD310\uACFC \uAC19\uC740 \uC124\uCE58\uC790 \uD30C\uC77C\uC774 \uC788\uB358 \uC790\uB9AC (\uADF8\uB300\uB85C \uB450\uC5C8\uB2E4)";
|
|
12391
|
-
return existsSync26(
|
|
13267
|
+
return existsSync26(join35(projectDir, backup)) ? `\uD558\uB124\uC2A4\uAC00 \uC4F4 \uC790\uB9AC \u2014 \uC6D0\uB798 \uC788\uB358 \uC124\uCE58\uC790 \uD30C\uC77C\uC740 ${backup} \uC5D0 \uC788\uB2E4` : `\uD558\uB124\uC2A4\uAC00 \uC4F4 \uC790\uB9AC \u2014 \uC6D0\uB798 \uC788\uB358 \uC124\uCE58\uC790 \uD30C\uC77C\uC758 \uBC31\uC5C5(${backup})\uC774 \uB354\uB294 \uC5C6\uB2E4`;
|
|
12392
13268
|
}
|
|
12393
13269
|
}
|
|
12394
13270
|
}
|
|
@@ -12491,9 +13367,19 @@ function agentsMdRerenderSet(target, remaining, log, projectDir) {
|
|
|
12491
13367
|
const set = agentsMdClis(remaining);
|
|
12492
13368
|
if (set.length === 0) return null;
|
|
12493
13369
|
const recorded2 = (log.externalFiles ?? []).some((f) => f.path === AGENTS_MD2) || (log.portions ?? []).some((p2) => p2.path === AGENTS_MD2);
|
|
12494
|
-
if (!
|
|
13370
|
+
if (!existsSync26(join35(projectDir, AGENTS_MD2))) return null;
|
|
13371
|
+
if (!recorded2 && !isLegacyHarnessAgentsMd(readTextOrEmpty(join35(projectDir, AGENTS_MD2)))) {
|
|
13372
|
+
return null;
|
|
13373
|
+
}
|
|
12495
13374
|
return set;
|
|
12496
13375
|
}
|
|
13376
|
+
function readTextOrEmpty(abs) {
|
|
13377
|
+
try {
|
|
13378
|
+
return readFileSync26(abs, "utf8");
|
|
13379
|
+
} catch {
|
|
13380
|
+
return "";
|
|
13381
|
+
}
|
|
13382
|
+
}
|
|
12497
13383
|
function rerenderAgentsMd(ctx, set) {
|
|
12498
13384
|
const { installLog, projectDir, harnessRoot } = ctx;
|
|
12499
13385
|
return runAgentsMdTransform({
|
|
@@ -12512,10 +13398,11 @@ function withRerender(next, r) {
|
|
|
12512
13398
|
const files = mergeExternalFiles(next.externalFiles, r.ownership.files);
|
|
12513
13399
|
if (files.length > 0) out.externalFiles = files;
|
|
12514
13400
|
const block = r.agentsMd.shared;
|
|
12515
|
-
|
|
13401
|
+
const blockPortions = block !== null && block.portions !== null ? block.portions : r.agentsMd.blockRecordDropped === true ? [] : null;
|
|
13402
|
+
if (blockPortions !== null) {
|
|
12516
13403
|
const portions = [
|
|
12517
13404
|
...(next.portions ?? []).filter((p2) => p2.path !== AGENTS_MD2),
|
|
12518
|
-
...
|
|
13405
|
+
...blockPortions
|
|
12519
13406
|
];
|
|
12520
13407
|
if (portions.length > 0) out.portions = portions;
|
|
12521
13408
|
else delete out.portions;
|
|
@@ -12555,11 +13442,8 @@ function settleCliLog(ctx, target, remaining, done, anchorRemoved) {
|
|
|
12555
13442
|
const survivors = (installLog.externalFiles ?? []).filter((f) => !done.forgotten.has(f.path));
|
|
12556
13443
|
if (survivors.length > 0) next.externalFiles = survivors;
|
|
12557
13444
|
else delete next.externalFiles;
|
|
12558
|
-
const settled = new Set(done.displaced.filter((d2) => d2.forget).map((d2) => d2.path));
|
|
12559
13445
|
if (installLog.rootFiles !== void 0) {
|
|
12560
|
-
next.rootFiles = installLog.rootFiles.
|
|
12561
|
-
(f) => !(f.change === "displaced" && settled.has(f.path))
|
|
12562
|
-
);
|
|
13446
|
+
next.rootFiles = withoutRestored(installLog.rootFiles, done.displaced);
|
|
12563
13447
|
}
|
|
12564
13448
|
const touched = new Set(done.shared.map((r) => r.path));
|
|
12565
13449
|
const portions = [
|
|
@@ -12621,20 +13505,21 @@ var SKILLS_LOCK = "skills-lock.json";
|
|
|
12621
13505
|
function withSkillsLock(rootFiles, assets, projectDir) {
|
|
12622
13506
|
const out = [...rootFiles];
|
|
12623
13507
|
const skills = assets.some((a) => a.method === "skill" && a.scope === "project");
|
|
12624
|
-
if (skills && !out.some((f) => f.path === SKILLS_LOCK) && existsSync26(
|
|
13508
|
+
if (skills && !out.some((f) => f.path === SKILLS_LOCK) && existsSync26(join35(projectDir, SKILLS_LOCK))) {
|
|
12625
13509
|
out.push({ path: SKILLS_LOCK, change: "advisory", notes: [] });
|
|
12626
13510
|
}
|
|
12627
13511
|
return out;
|
|
12628
13512
|
}
|
|
12629
|
-
function remnantFor(path, log, harnessRoot, projectDir) {
|
|
13513
|
+
function remnantFor(path, log, harnessRoot, projectDir, wiringGone = []) {
|
|
12630
13514
|
const clis = installedClis(log);
|
|
12631
13515
|
if (path === SETTINGS_TARGET) {
|
|
13516
|
+
const gone = (k2) => wiringGone.includes(`hooks/${k2.split("#")[1] ?? ""}`);
|
|
12632
13517
|
return (disk) => {
|
|
12633
13518
|
try {
|
|
12634
|
-
const template = readFileSync26(
|
|
13519
|
+
const template = readFileSync26(join35(harnessRoot, "templates", "settings.json"), "utf8");
|
|
12635
13520
|
const render = renderSettingsPortion(template, () => true);
|
|
12636
|
-
return [...legacySettingsSeed(disk, render, projectDir).keys()].filter(
|
|
12637
|
-
(k2) => !k2.endsWith("{}")
|
|
13521
|
+
return [...legacySettingsSeed(disk, render, projectDir, { edited: true }).keys()].filter(
|
|
13522
|
+
(k2) => !k2.endsWith("{}") && !gone(k2)
|
|
12638
13523
|
);
|
|
12639
13524
|
} catch {
|
|
12640
13525
|
return [];
|
|
@@ -12761,7 +13646,7 @@ function noReverseHints(asset, ctx) {
|
|
|
12761
13646
|
}
|
|
12762
13647
|
if (asset.method !== "skill") return [];
|
|
12763
13648
|
const name = asset.detail.skill;
|
|
12764
|
-
const left = name === void 0 ? [] : [".claude/skills", ".agents/skills"].map((root) => `${root}/${name}/`).filter((p2) => existsSync26(
|
|
13649
|
+
const left = name === void 0 ? [] : [".claude/skills", ".agents/skills"].map((root) => `${root}/${name}/`).filter((p2) => existsSync26(join35(ctx.projectDir, p2)));
|
|
12765
13650
|
return [
|
|
12766
13651
|
left.length > 0 ? `files it put down are not on record (installed by an older version) \u2014 left: ${left.join(" \xB7 ")} (delete by hand if the harness installed it)` : "files it put down are not on record (installed by an older version) \u2014 nothing removed"
|
|
12767
13652
|
];
|
|
@@ -12861,21 +13746,31 @@ function removeHarnessFiles(log, projectDir, scope, io) {
|
|
|
12861
13746
|
forgotten: /* @__PURE__ */ new Set(),
|
|
12862
13747
|
stripped: [],
|
|
12863
13748
|
kept: [],
|
|
13749
|
+
legacyAgentsMd: [],
|
|
12864
13750
|
unjudged: [],
|
|
12865
13751
|
outside: [],
|
|
12866
13752
|
displaced: [],
|
|
12867
13753
|
shared: [],
|
|
12868
13754
|
retiredWiring: [],
|
|
13755
|
+
legacyWiring: [],
|
|
12869
13756
|
importStripped: false,
|
|
12870
13757
|
anchor: { removed: false, lines: [] }
|
|
12871
13758
|
};
|
|
12872
13759
|
const pruneFrom = [];
|
|
12873
|
-
stripSharedFiles(log, projectDir, scope.shared, io, out, pruneFrom);
|
|
12874
13760
|
const isTarget = harnessTargets(log);
|
|
12875
|
-
|
|
13761
|
+
const candidates = harnessCandidates(log);
|
|
13762
|
+
for (const path of candidates) {
|
|
12876
13763
|
if (scope.has(path))
|
|
12877
13764
|
removeRecordedFile(path, { log, projectDir, io, out, isTarget, pruneFrom });
|
|
12878
13765
|
}
|
|
13766
|
+
const judged = new Set(candidates);
|
|
13767
|
+
for (const path of legacyFileCandidates()) {
|
|
13768
|
+
if (judged.has(path) || !scope.has(path) || !safeExists(join35(projectDir, path))) continue;
|
|
13769
|
+
if (recorded(log, path, { isTarget }).state !== "none") continue;
|
|
13770
|
+
removeRecordedFile(path, { log, projectDir, io, out, isTarget, pruneFrom });
|
|
13771
|
+
}
|
|
13772
|
+
out.legacyWiring = removeLegacyHookWiring(log, projectDir, scope, io, out.removed);
|
|
13773
|
+
stripSharedFiles(log, projectDir, scope.shared, io, out, pruneFrom);
|
|
12879
13774
|
if (scope.importBlock) {
|
|
12880
13775
|
out.importStripped = io.write ? stripRootImport(projectDir) : hasRootImport(projectDir);
|
|
12881
13776
|
}
|
|
@@ -12884,11 +13779,19 @@ function removeHarnessFiles(log, projectDir, scope, io) {
|
|
|
12884
13779
|
const anchorPath = log.templates?.rootClaudeMd?.path;
|
|
12885
13780
|
if (out.anchor.removed && anchorPath !== void 0) out.removedAnchor = anchorPath;
|
|
12886
13781
|
}
|
|
12887
|
-
restoreDisplaced(log, projectDir,
|
|
13782
|
+
out.displaced = restoreDisplaced(log, projectDir, {
|
|
13783
|
+
has: scope.has,
|
|
13784
|
+
willBeGone: /* @__PURE__ */ new Set([
|
|
13785
|
+
...out.removed,
|
|
13786
|
+
...out.removedAnchor === void 0 ? [] : [out.removedAnchor],
|
|
13787
|
+
...io.assetFilesGone ?? []
|
|
13788
|
+
]),
|
|
13789
|
+
write: io.write
|
|
13790
|
+
});
|
|
12888
13791
|
if (io.write) {
|
|
12889
|
-
for (const p2 of pruneFrom) pruneEmptyDirsUpward(projectDir,
|
|
13792
|
+
for (const p2 of pruneFrom) pruneEmptyDirsUpward(projectDir, dirname8(join35(projectDir, p2)));
|
|
12890
13793
|
for (const d2 of scope.skeleton) {
|
|
12891
|
-
const abs =
|
|
13794
|
+
const abs = join35(projectDir, d2);
|
|
12892
13795
|
if (outsideProjectTarget(projectDir, abs) !== null) continue;
|
|
12893
13796
|
pruneEmptyDirsUpward(projectDir, abs);
|
|
12894
13797
|
}
|
|
@@ -12917,14 +13820,14 @@ function templateNext(harnessRoot, log, path) {
|
|
|
12917
13820
|
if (path === INSTALLED_TRACKS) return installedTracksText(log.spec.tracks.filter(isTrack));
|
|
12918
13821
|
if (!path.startsWith(CLAUDE_DIR3)) return null;
|
|
12919
13822
|
try {
|
|
12920
|
-
return readFileSync26(
|
|
13823
|
+
return readFileSync26(join35(harnessRoot, "templates", path.slice(CLAUDE_DIR3.length)), "utf8");
|
|
12921
13824
|
} catch {
|
|
12922
13825
|
return null;
|
|
12923
13826
|
}
|
|
12924
13827
|
}
|
|
12925
13828
|
function removeRecordedFile(path, ctx) {
|
|
12926
13829
|
const { log, projectDir, io, out } = ctx;
|
|
12927
|
-
const abs =
|
|
13830
|
+
const abs = join35(projectDir, path);
|
|
12928
13831
|
let foreign;
|
|
12929
13832
|
try {
|
|
12930
13833
|
foreign = foreignOwnedTarget(projectDir, path);
|
|
@@ -12943,7 +13846,7 @@ function removeRecordedFile(path, ctx) {
|
|
|
12943
13846
|
}
|
|
12944
13847
|
let st2;
|
|
12945
13848
|
try {
|
|
12946
|
-
st2 =
|
|
13849
|
+
st2 = lstatSync6(abs, { throwIfNoEntry: false });
|
|
12947
13850
|
} catch {
|
|
12948
13851
|
out.unjudged.push(path);
|
|
12949
13852
|
return;
|
|
@@ -12966,17 +13869,20 @@ function removeRecordedFile(path, ctx) {
|
|
|
12966
13869
|
out.unjudged.push(path);
|
|
12967
13870
|
return;
|
|
12968
13871
|
}
|
|
13872
|
+
const rec = recorded(log, path, { isTarget: ctx.isTarget });
|
|
13873
|
+
const legacy = rec.state !== "sha" && isLegacyHarnessFile(path, hashContent(disk)) && (rec.state === "no-sha" || mayReclaimLegacy(log, path));
|
|
13874
|
+
const inBundle = legacy && ctx.isTarget(bundlePath(path));
|
|
12969
13875
|
const verdict = judge({
|
|
12970
13876
|
op: "remove",
|
|
12971
13877
|
kind: "harness",
|
|
12972
|
-
rec:
|
|
13878
|
+
rec: legacy ? { state: "no-sha" } : rec,
|
|
12973
13879
|
disk,
|
|
12974
|
-
next: templateNext(io.harnessRoot, log, path)
|
|
13880
|
+
next: legacy ? inBundle ? disk : null : templateNext(io.harnessRoot, log, path)
|
|
12975
13881
|
});
|
|
12976
13882
|
if (verdict.verdict !== "remove" && verdict.verdict !== "backup+remove") return;
|
|
12977
13883
|
let backup = null;
|
|
12978
13884
|
if (verdict.verdict === "backup+remove") {
|
|
12979
|
-
backup = io.write ?
|
|
13885
|
+
backup = io.write ? relative6(projectDir, backupFile(effective)).split(sep6).join("/") : `${relative6(projectDir, effective).split(sep6).join("/")}.backup-<time>`;
|
|
12980
13886
|
}
|
|
12981
13887
|
if (io.write) {
|
|
12982
13888
|
if (effective !== abs) io.rm(abs);
|
|
@@ -12985,7 +13891,34 @@ function removeRecordedFile(path, ctx) {
|
|
|
12985
13891
|
out.removed.push(path);
|
|
12986
13892
|
out.forgotten.add(path);
|
|
12987
13893
|
ctx.pruneFrom.push(path);
|
|
12988
|
-
if (backup !== null)
|
|
13894
|
+
if (backup !== null)
|
|
13895
|
+
out.backedUp.push({ path, backup, line: legacy && !inBundle ? LEGACY_SAVED : verdict.line });
|
|
13896
|
+
}
|
|
13897
|
+
var LEGACY_SAVED = "older harness version (byte-identical, not in the current bundle) \u2014 saved a copy, removed from live";
|
|
13898
|
+
function legacyFileCandidates() {
|
|
13899
|
+
return [...LEGACY_HARNESS_FILES.keys()].flatMap(
|
|
13900
|
+
(p2) => p2.startsWith(SKILLS_DIR3) ? [p2, `.agents/skills/${p2.slice(SKILLS_DIR3.length)}`] : [p2]
|
|
13901
|
+
);
|
|
13902
|
+
}
|
|
13903
|
+
function bundlePath(path) {
|
|
13904
|
+
return path.startsWith(".agents/skills/") ? `${SKILLS_DIR3}${path.slice(".agents/skills/".length)}` : path;
|
|
13905
|
+
}
|
|
13906
|
+
function mayReclaimLegacy(log, path) {
|
|
13907
|
+
const clis = installedClis(log);
|
|
13908
|
+
if (!ownersOf(path).some((c3) => clis.includes(c3))) return false;
|
|
13909
|
+
if (isExcludedPath(bundlePath(path), excludedIds(log))) return false;
|
|
13910
|
+
return !(log.rootFiles ?? []).some((f) => f.path === path && f.change === "displaced");
|
|
13911
|
+
}
|
|
13912
|
+
function removeLegacyHookWiring(log, projectDir, scope, io, removed) {
|
|
13913
|
+
if (!scope.has(SETTINGS_TARGET) || !installedClis(log).includes("claude")) return [];
|
|
13914
|
+
if ((log.portions ?? []).some((p2) => p2.path === SETTINGS_TARGET)) return [];
|
|
13915
|
+
const abs = join35(projectDir, SETTINGS_TARGET);
|
|
13916
|
+
if (!safeExists(abs) || outsideProjectTarget(projectDir, abs) !== null) return [];
|
|
13917
|
+
const claudeDir = join35(projectDir, ".claude");
|
|
13918
|
+
const gone = LEGACY_HOOK_REFS.filter(
|
|
13919
|
+
(r) => !RETIRED_HOOK_WIRING_REFS.includes(r) && (removed.includes(`${CLAUDE_DIR3}${r}`) || !safeExists(join35(claudeDir, r)))
|
|
13920
|
+
);
|
|
13921
|
+
return removeRetiredHookRefs(abs, claudeDir, gone, { evenIfScriptExists: true, write: io.write });
|
|
12989
13922
|
}
|
|
12990
13923
|
function stripSharedFiles(log, projectDir, paths, io, out, pruneFrom) {
|
|
12991
13924
|
const made = new Map((log.externalFiles ?? []).map((f) => [f.path, f.sha256]));
|
|
@@ -13004,7 +13937,7 @@ function stripSharedFiles(log, projectDir, paths, io, out, pruneFrom) {
|
|
|
13004
13937
|
};
|
|
13005
13938
|
for (const path of paths) {
|
|
13006
13939
|
if (!relevant(path)) continue;
|
|
13007
|
-
const abs =
|
|
13940
|
+
const abs = join35(projectDir, path);
|
|
13008
13941
|
if (safeExists(abs)) {
|
|
13009
13942
|
const o = outsideProjectTarget(projectDir, abs);
|
|
13010
13943
|
if (o !== null) {
|
|
@@ -13015,7 +13948,7 @@ function stripSharedFiles(log, projectDir, paths, io, out, pruneFrom) {
|
|
|
13015
13948
|
if (path === SETTINGS_TARGET && safeExists(abs)) {
|
|
13016
13949
|
out.retiredWiring = removeRetiredHookRefs(
|
|
13017
13950
|
abs,
|
|
13018
|
-
|
|
13951
|
+
join35(projectDir, ".claude"),
|
|
13019
13952
|
RETIRED_HOOK_WIRING_REFS,
|
|
13020
13953
|
{ evenIfScriptExists: true, write: io.write }
|
|
13021
13954
|
);
|
|
@@ -13024,12 +13957,15 @@ function stripSharedFiles(log, projectDir, paths, io, out, pruneFrom) {
|
|
|
13024
13957
|
if (sha !== void 0 && removeHarnessMadeShared(path, sha, projectDir, io, out, pruneFrom)) {
|
|
13025
13958
|
continue;
|
|
13026
13959
|
}
|
|
13960
|
+
if (path === AGENTS_MD2 && sha === void 0) {
|
|
13961
|
+
if (removeUnrecordedLegacyAgentsMd(path, projectDir, io, out, pruneFrom)) continue;
|
|
13962
|
+
}
|
|
13027
13963
|
const r = stripShared({
|
|
13028
13964
|
projectDir,
|
|
13029
13965
|
path,
|
|
13030
13966
|
portions: log.portions ?? [],
|
|
13031
13967
|
excluded: [...excludedIds(log)],
|
|
13032
|
-
remnant: remnantFor(path, log, io.harnessRoot, projectDir),
|
|
13968
|
+
remnant: remnantFor(path, log, io.harnessRoot, projectDir, out.legacyWiring),
|
|
13033
13969
|
remnantLine: remnantLine(path),
|
|
13034
13970
|
write: io.write,
|
|
13035
13971
|
// 하네스가 만든 파일(#569 `created` · #13 `externalFiles`)은 몫을 걷고 남는 것이 없으면 파일째 지운다
|
|
@@ -13040,7 +13976,7 @@ function stripSharedFiles(log, projectDir, paths, io, out, pruneFrom) {
|
|
|
13040
13976
|
}
|
|
13041
13977
|
}
|
|
13042
13978
|
function removeHarnessMadeShared(path, sha, projectDir, io, out, pruneFrom) {
|
|
13043
|
-
const abs =
|
|
13979
|
+
const abs = join35(projectDir, path);
|
|
13044
13980
|
if (!existsSync26(abs)) {
|
|
13045
13981
|
out.forgotten.add(path);
|
|
13046
13982
|
return true;
|
|
@@ -13053,7 +13989,7 @@ function removeHarnessMadeShared(path, sha, projectDir, io, out, pruneFrom) {
|
|
|
13053
13989
|
out.unjudged.push(path);
|
|
13054
13990
|
return true;
|
|
13055
13991
|
}
|
|
13056
|
-
if (
|
|
13992
|
+
if (lstatSync6(abs).isSymbolicLink()) effective = real;
|
|
13057
13993
|
current = readFileSync26(effective, "utf8");
|
|
13058
13994
|
} catch {
|
|
13059
13995
|
out.unjudged.push(path);
|
|
@@ -13061,7 +13997,15 @@ function removeHarnessMadeShared(path, sha, projectDir, io, out, pruneFrom) {
|
|
|
13061
13997
|
}
|
|
13062
13998
|
if (hashContent(current) !== sha) {
|
|
13063
13999
|
if (path === AGENTS_MD2) {
|
|
13064
|
-
|
|
14000
|
+
const verdict = isLegacyHarnessAgentsMd(current) ? agentsMdRemainder(current, io.harnessRoot) : null;
|
|
14001
|
+
if (verdict?.ok === true && verdict.strip.legacyRemoved) {
|
|
14002
|
+
removeLegacyAgentsMd(path, abs, effective, verdict.strip, {
|
|
14003
|
+
projectDir,
|
|
14004
|
+
io,
|
|
14005
|
+
out,
|
|
14006
|
+
pruneFrom
|
|
14007
|
+
});
|
|
14008
|
+
} else out.kept.push(path);
|
|
13065
14009
|
return true;
|
|
13066
14010
|
}
|
|
13067
14011
|
out.forgotten.add(path);
|
|
@@ -13073,9 +14017,13 @@ function removeHarnessMadeShared(path, sha, projectDir, io, out, pruneFrom) {
|
|
|
13073
14017
|
out.unjudged.push(path);
|
|
13074
14018
|
return true;
|
|
13075
14019
|
}
|
|
14020
|
+
if (verdict.strip.legacyRemoved) {
|
|
14021
|
+
removeLegacyAgentsMd(path, abs, effective, verdict.strip, { projectDir, io, out, pruneFrom });
|
|
14022
|
+
return true;
|
|
14023
|
+
}
|
|
13076
14024
|
if (verdict.remainder !== null) {
|
|
13077
14025
|
try {
|
|
13078
|
-
if (io.write)
|
|
14026
|
+
if (io.write) writeFileSync9(effective, neutralizeScaffoldBanner(verdict.remainder), "utf8");
|
|
13079
14027
|
out.stripped.push(path);
|
|
13080
14028
|
out.forgotten.add(path);
|
|
13081
14029
|
} catch {
|
|
@@ -13101,38 +14049,44 @@ function removeHarnessMadeShared(path, sha, projectDir, io, out, pruneFrom) {
|
|
|
13101
14049
|
pruneFrom.push(path);
|
|
13102
14050
|
return true;
|
|
13103
14051
|
}
|
|
13104
|
-
function restoreDisplaced(log, projectDir, scope, io, out) {
|
|
13105
|
-
const willBeGone = /* @__PURE__ */ new Set([
|
|
13106
|
-
...out.removed,
|
|
13107
|
-
...out.removedAnchor === void 0 ? [] : [out.removedAnchor]
|
|
13108
|
-
]);
|
|
13109
|
-
for (const f of log.rootFiles ?? []) {
|
|
13110
|
-
if (f.change !== "displaced" || !scope.has(f.path)) continue;
|
|
13111
|
-
const slot = join34(projectDir, f.path);
|
|
13112
|
-
if (outsideProjectTarget(projectDir, slot) !== null) continue;
|
|
13113
|
-
const backup = f.notes[0] ?? null;
|
|
13114
|
-
const d2 = judgeDisplaced({
|
|
13115
|
-
backup,
|
|
13116
|
-
backupExists: backup !== null && safeExists(join34(projectDir, backup)),
|
|
13117
|
-
slotEmpty: !safeExists(slot) || !io.write && willBeGone.has(f.path)
|
|
13118
|
-
});
|
|
13119
|
-
if (io.write && d2.verdict === "restore" && backup !== null) {
|
|
13120
|
-
mkdirSync7(dirname7(slot), { recursive: true });
|
|
13121
|
-
renameSync(join34(projectDir, backup), slot);
|
|
13122
|
-
}
|
|
13123
|
-
out.displaced.push({
|
|
13124
|
-
path: f.path,
|
|
13125
|
-
backup,
|
|
13126
|
-
verdict: d2.verdict,
|
|
13127
|
-
line: d2.line,
|
|
13128
|
-
forget: d2.record === "forget"
|
|
13129
|
-
});
|
|
13130
|
-
}
|
|
13131
|
-
}
|
|
13132
14052
|
function topOf(path) {
|
|
13133
14053
|
const i = path.indexOf("/");
|
|
13134
14054
|
return i < 0 ? path : `${path.slice(0, i)}/`;
|
|
13135
14055
|
}
|
|
14056
|
+
function displacedLines(displaced, preview) {
|
|
14057
|
+
const lines2 = [];
|
|
14058
|
+
const restore = displaced.filter((d2) => d2.verdict === "restore");
|
|
14059
|
+
if (preview && restore.length > 0) {
|
|
14060
|
+
lines2.push(
|
|
14061
|
+
` \u25CB put back ${restore.length} file(s) of yours (displaced): ${restore.map((d2) => d2.path).join(" \xB7 ")}`
|
|
14062
|
+
);
|
|
14063
|
+
}
|
|
14064
|
+
for (const d2 of displaced) {
|
|
14065
|
+
if (d2.verdict === "restore" && !preview) {
|
|
14066
|
+
lines2.push(` ${status.success(`put back ${d2.path} (from ${d2.backup})`)}`);
|
|
14067
|
+
} else if (d2.verdict === "advise") {
|
|
14068
|
+
lines2.push(` ${c.yellow("\u2298")} ${d2.path} \u2014 ${d2.line}`);
|
|
14069
|
+
}
|
|
14070
|
+
}
|
|
14071
|
+
return lines2;
|
|
14072
|
+
}
|
|
14073
|
+
function plannedAssets(plan, log) {
|
|
14074
|
+
const ids = new Set(plan.reverseSteps.map((s) => s.assetId));
|
|
14075
|
+
return log.assets.filter((a) => ids.has(a.id));
|
|
14076
|
+
}
|
|
14077
|
+
function plannedAssetFiles(plan, log) {
|
|
14078
|
+
return plannedAssets(plan, log).flatMap(
|
|
14079
|
+
(a) => a.method === "skill" && a.scope === "project" ? (a.files ?? []).map((f) => f.path) : []
|
|
14080
|
+
);
|
|
14081
|
+
}
|
|
14082
|
+
function inAssetSlots(assets) {
|
|
14083
|
+
const slots = new Set(
|
|
14084
|
+
assets.flatMap(
|
|
14085
|
+
(a) => a.method === "skill" && a.scope === "project" ? (a.files ?? []).map((f) => `${f.path.split("/").slice(0, 3).join("/")}/`) : []
|
|
14086
|
+
)
|
|
14087
|
+
);
|
|
14088
|
+
return (path) => [...slots].some((s) => path.startsWith(s));
|
|
14089
|
+
}
|
|
13136
14090
|
function harnessRemovalLines(r, log, projectDir, scope, preview) {
|
|
13137
14091
|
const lines2 = [];
|
|
13138
14092
|
const groups = /* @__PURE__ */ new Map();
|
|
@@ -13147,7 +14101,7 @@ function harnessRemovalLines(r, log, projectDir, scope, preview) {
|
|
|
13147
14101
|
}
|
|
13148
14102
|
if (preview) {
|
|
13149
14103
|
for (const [top, g] of groups) {
|
|
13150
|
-
const edited = g.backedUp > 0 ? ` (${g.backedUp}
|
|
14104
|
+
const edited = g.backedUp > 0 ? ` (${g.backedUp} with a copy saved beside as *.backup-<time>)` : "";
|
|
13151
14105
|
lines2.push(` \u25CB remove ${g.removed} harness file(s) under ${top}${edited}`);
|
|
13152
14106
|
}
|
|
13153
14107
|
} else if (groups.size > 0) {
|
|
@@ -13166,24 +14120,24 @@ function harnessRemovalLines(r, log, projectDir, scope, preview) {
|
|
|
13166
14120
|
);
|
|
13167
14121
|
}
|
|
13168
14122
|
lines2.push(...r.anchor.lines);
|
|
13169
|
-
|
|
13170
|
-
if (preview && restore.length > 0) {
|
|
13171
|
-
lines2.push(
|
|
13172
|
-
` \u25CB put back ${restore.length} file(s) of yours (displaced): ${restore.map((d2) => d2.path).join(" \xB7 ")}`
|
|
13173
|
-
);
|
|
13174
|
-
}
|
|
13175
|
-
for (const d2 of r.displaced) {
|
|
13176
|
-
if (d2.verdict === "restore" && !preview) {
|
|
13177
|
-
lines2.push(` ${status.success(`put back ${d2.path} (from ${d2.backup})`)}`);
|
|
13178
|
-
} else if (d2.verdict === "advise") {
|
|
13179
|
-
lines2.push(` ${c.yellow("\u2298")} ${d2.path} \u2014 ${d2.line}`);
|
|
13180
|
-
}
|
|
13181
|
-
}
|
|
14123
|
+
lines2.push(...displacedLines(r.displaced, preview));
|
|
13182
14124
|
for (const path of r.stripped) {
|
|
13183
14125
|
lines2.push(
|
|
13184
14126
|
preview ? ` \u25CB strip harness sections from ${path} (\uBCF8\uBB38 \uBCF4\uC874)` : ` ${status.success(`${path} \u2014 harness sections removed (\uBCF8\uBB38 \uBCF4\uC874)`)}`
|
|
13185
14127
|
);
|
|
13186
14128
|
}
|
|
14129
|
+
for (const l of r.legacyAgentsMd) {
|
|
14130
|
+
const kept = l.keptEdited.length > 0 ? ` \xB7 kept ${l.keptEdited.length} section(s) you edited (${l.keptEdited.join(" \xB7 ")})` : "";
|
|
14131
|
+
if (preview) {
|
|
14132
|
+
lines2.push(
|
|
14133
|
+
l.fileRemoved ? ` \u25CB remove ${l.path} (written by an older harness version \u2014 a copy is saved first)` : ` \u25CB remove the harness sections written by an older version from ${l.path} \u2014 yours stays${kept} (a copy is saved first)`
|
|
14134
|
+
);
|
|
14135
|
+
} else {
|
|
14136
|
+
lines2.push(
|
|
14137
|
+
l.fileRemoved ? ` ${status.success(`removed ${l.path} (written by an older harness version \u2014 saved a copy: ${l.backup})`)}` : ` ${status.success(`${l.path} \u2014 removed the harness sections written by an older version \u2014 yours stays${kept} (saved a copy: ${l.backup})`)}`
|
|
14138
|
+
);
|
|
14139
|
+
}
|
|
14140
|
+
}
|
|
13187
14141
|
for (const path of r.unjudged) {
|
|
13188
14142
|
lines2.push(
|
|
13189
14143
|
path === AGENTS_MD2 ? ` ${c.yellow("\u2298")} ${path} kept \u2014 harness sections could not be separated (a file or template could not be read, or the write failed). Remove manually if intended.` : ` ${c.yellow("\u2298")} ${path} left \u2014 could not read it to judge. Remove manually if intended.`
|
|
@@ -13195,6 +14149,12 @@ function harnessRemovalLines(r, log, projectDir, scope, preview) {
|
|
|
13195
14149
|
` ${c.yellow("\u2298")} ${path} kept \u2014 modified since install. Remove manually if intended.`
|
|
13196
14150
|
);
|
|
13197
14151
|
}
|
|
14152
|
+
if (r.legacyWiring.length > 0) {
|
|
14153
|
+
const refs = r.legacyWiring.join(" \xB7 ");
|
|
14154
|
+
lines2.push(
|
|
14155
|
+
preview ? ` \u25CB remove harness hook wiring from an older version (script gone) from ${SETTINGS_TARGET}: ${refs}` : ` ${status.success(`${SETTINGS_TARGET} \u2014 removed harness hook wiring from an older version (script gone): ${refs}`)}`
|
|
14156
|
+
);
|
|
14157
|
+
}
|
|
13198
14158
|
if (r.retiredWiring.length > 0) {
|
|
13199
14159
|
const refs = r.retiredWiring.join(" \xB7 ");
|
|
13200
14160
|
lines2.push(
|
|
@@ -13245,25 +14205,25 @@ function yoursUnder(projectDir, dir) {
|
|
|
13245
14205
|
const walk2 = (abs2, prefix) => {
|
|
13246
14206
|
let entries;
|
|
13247
14207
|
try {
|
|
13248
|
-
entries =
|
|
14208
|
+
entries = readdirSync7(abs2, { withFileTypes: true });
|
|
13249
14209
|
} catch {
|
|
13250
14210
|
return;
|
|
13251
14211
|
}
|
|
13252
14212
|
for (const e2 of entries) {
|
|
13253
14213
|
const name = `${prefix}${e2.name}`;
|
|
13254
|
-
if (e2.isDirectory()) walk2(
|
|
14214
|
+
if (e2.isDirectory()) walk2(join35(abs2, e2.name), `${name}/`);
|
|
13255
14215
|
else if (BACKUP_SUFFIX.test(e2.name)) continue;
|
|
13256
14216
|
else if (e2.isSymbolicLink()) {
|
|
13257
14217
|
let target = "?";
|
|
13258
14218
|
try {
|
|
13259
|
-
target = readlinkSync(
|
|
14219
|
+
target = readlinkSync(join35(abs2, e2.name));
|
|
13260
14220
|
} catch {
|
|
13261
14221
|
}
|
|
13262
14222
|
out.push({ name, shown: `${name} (your link \u2192 ${target})` });
|
|
13263
14223
|
} else out.push({ name, shown: name });
|
|
13264
14224
|
}
|
|
13265
14225
|
};
|
|
13266
|
-
const abs =
|
|
14226
|
+
const abs = join35(projectDir, dir);
|
|
13267
14227
|
try {
|
|
13268
14228
|
if (!statSync5(abs).isDirectory()) return [];
|
|
13269
14229
|
} catch {
|
|
@@ -13275,7 +14235,7 @@ function yoursUnder(projectDir, dir) {
|
|
|
13275
14235
|
function assetsLeftLines(log, projectDir, scope) {
|
|
13276
14236
|
const lines2 = [];
|
|
13277
14237
|
for (const a of log.assets) {
|
|
13278
|
-
const here = (a.files ?? []).map((f) => f.path).filter((p2) => scope.has(p2) && safeExists(
|
|
14238
|
+
const here = (a.files ?? []).map((f) => f.path).filter((p2) => scope.has(p2) && safeExists(join35(projectDir, p2)));
|
|
13279
14239
|
if (here.length === 0) continue;
|
|
13280
14240
|
const slots = [...new Set(here.map((p2) => p2.split("/").slice(0, 3).join("/")))].sort();
|
|
13281
14241
|
lines2.push(
|
|
@@ -13287,7 +14247,7 @@ function assetsLeftLines(log, projectDir, scope) {
|
|
|
13287
14247
|
function removeAnchor(log, projectDir, io) {
|
|
13288
14248
|
const rootMd = log.templates?.rootClaudeMd;
|
|
13289
14249
|
if (!rootMd) return { removed: false, lines: [] };
|
|
13290
|
-
const abs =
|
|
14250
|
+
const abs = join35(projectDir, rootMd.path);
|
|
13291
14251
|
if (!existsSync26(abs)) return { removed: false, lines: [] };
|
|
13292
14252
|
const outside = outsideProjectTarget(projectDir, abs);
|
|
13293
14253
|
if (outside !== null) return { removed: false, lines: outsideLines([outside], log) };
|
|
@@ -13326,7 +14286,7 @@ function removeAnchor(log, projectDir, io) {
|
|
|
13326
14286
|
]
|
|
13327
14287
|
};
|
|
13328
14288
|
}
|
|
13329
|
-
const backup = edited ?
|
|
14289
|
+
const backup = edited ? relative6(projectDir, backupFile(abs)).split(sep6).join("/") : null;
|
|
13330
14290
|
io.rm(abs);
|
|
13331
14291
|
return {
|
|
13332
14292
|
removed: true,
|
|
@@ -13338,7 +14298,7 @@ function removeAnchor(log, projectDir, io) {
|
|
|
13338
14298
|
var AGENTS_MD2 = "AGENTS.md";
|
|
13339
14299
|
function readAgentsMdTemplate(harnessRoot) {
|
|
13340
14300
|
try {
|
|
13341
|
-
return readFileSync26(
|
|
14301
|
+
return readFileSync26(join35(harnessRoot, AGENTS_MD_TEMPLATE), "utf8");
|
|
13342
14302
|
} catch {
|
|
13343
14303
|
return null;
|
|
13344
14304
|
}
|
|
@@ -13356,24 +14316,70 @@ function neutralizeScaffoldBanner(text) {
|
|
|
13356
14316
|
function agentsMdRemainder(current, harnessRoot) {
|
|
13357
14317
|
const template = readAgentsMdTemplate(harnessRoot);
|
|
13358
14318
|
if (template === null) return { ok: false };
|
|
13359
|
-
|
|
13360
|
-
|
|
13361
|
-
|
|
13362
|
-
|
|
13363
|
-
|
|
13364
|
-
|
|
13365
|
-
|
|
13366
|
-
|
|
14319
|
+
const strip = stripAgentsMd({
|
|
14320
|
+
existing: current,
|
|
14321
|
+
template,
|
|
14322
|
+
harnessRuleHeadings: ruleHeadings(harnessRoot)
|
|
14323
|
+
});
|
|
14324
|
+
return { ok: true, remainder: strip.remainder, strip };
|
|
14325
|
+
}
|
|
14326
|
+
function removeUnrecordedLegacyAgentsMd(path, projectDir, io, out, pruneFrom) {
|
|
14327
|
+
const abs = join35(projectDir, path);
|
|
14328
|
+
let effective = abs;
|
|
14329
|
+
let current;
|
|
14330
|
+
try {
|
|
14331
|
+
const real = realpathSync3(abs);
|
|
14332
|
+
if (!statSync5(real).isFile()) return false;
|
|
14333
|
+
if (lstatSync6(abs).isSymbolicLink()) effective = real;
|
|
14334
|
+
current = readFileSync26(effective, "utf8");
|
|
14335
|
+
} catch {
|
|
14336
|
+
return false;
|
|
14337
|
+
}
|
|
14338
|
+
if (!isLegacyHarnessAgentsMd(current)) return false;
|
|
14339
|
+
const verdict = agentsMdRemainder(current, io.harnessRoot);
|
|
14340
|
+
if (!verdict.ok) {
|
|
14341
|
+
out.unjudged.push(path);
|
|
14342
|
+
return true;
|
|
14343
|
+
}
|
|
14344
|
+
removeLegacyAgentsMd(path, abs, effective, verdict.strip, { projectDir, io, out, pruneFrom });
|
|
14345
|
+
return true;
|
|
14346
|
+
}
|
|
14347
|
+
function removeLegacyAgentsMd(path, abs, effective, strip, ctx) {
|
|
14348
|
+
const { projectDir, io, out } = ctx;
|
|
14349
|
+
let backup = `${path}.backup-<time>`;
|
|
14350
|
+
try {
|
|
14351
|
+
if (io.write) {
|
|
14352
|
+
backup = relative6(projectDir, backupFile(effective)).split(sep6).join("/");
|
|
14353
|
+
if (strip.remainder !== null) {
|
|
14354
|
+
writeFileSync9(effective, neutralizeScaffoldBanner(strip.remainder), "utf8");
|
|
14355
|
+
} else {
|
|
14356
|
+
if (effective !== abs) io.rm(abs);
|
|
14357
|
+
io.rm(effective);
|
|
14358
|
+
}
|
|
14359
|
+
}
|
|
14360
|
+
} catch {
|
|
14361
|
+
out.unjudged.push(path);
|
|
14362
|
+
return;
|
|
14363
|
+
}
|
|
14364
|
+
if (strip.remainder === null) ctx.pruneFrom.push(path);
|
|
14365
|
+
out.legacyAgentsMd.push({
|
|
14366
|
+
path,
|
|
14367
|
+
backup,
|
|
14368
|
+
fileRemoved: strip.remainder === null,
|
|
14369
|
+
keptEdited: strip.keptEdited
|
|
14370
|
+
});
|
|
14371
|
+
out.forgotten.add(path);
|
|
14372
|
+
out.shared.push({ path, action: "none", line: "", removed: [], kept: [], portions: [] });
|
|
13367
14373
|
}
|
|
13368
14374
|
function removeToolFiles(files, projectDir, rm) {
|
|
13369
14375
|
const notes = [];
|
|
13370
14376
|
const removed = [];
|
|
13371
14377
|
let failed = 0;
|
|
13372
14378
|
for (const { path, sha256 } of files) {
|
|
13373
|
-
const abs =
|
|
14379
|
+
const abs = join35(projectDir, path);
|
|
13374
14380
|
let isLink;
|
|
13375
14381
|
try {
|
|
13376
|
-
isLink =
|
|
14382
|
+
isLink = lstatSync6(abs).isSymbolicLink();
|
|
13377
14383
|
} catch {
|
|
13378
14384
|
continue;
|
|
13379
14385
|
}
|
|
@@ -13389,7 +14395,7 @@ function removeToolFiles(files, projectDir, rm) {
|
|
|
13389
14395
|
try {
|
|
13390
14396
|
if (hashContent(readFileSync26(abs, "utf8")) !== sha256) {
|
|
13391
14397
|
const backup = backupFile(abs);
|
|
13392
|
-
notes.push(`backed up ${path} \u2192 ${
|
|
14398
|
+
notes.push(`backed up ${path} \u2192 ${relative6(projectDir, backup)} (changed since install)`);
|
|
13393
14399
|
}
|
|
13394
14400
|
rm(abs);
|
|
13395
14401
|
removed.push(path);
|
|
@@ -13398,21 +14404,21 @@ function removeToolFiles(files, projectDir, rm) {
|
|
|
13398
14404
|
notes.push(`left ${path} \u2014 ${e2 instanceof Error ? e2.message : String(e2)}`);
|
|
13399
14405
|
}
|
|
13400
14406
|
}
|
|
13401
|
-
for (const path of removed) pruneEmptyDirsUpward(projectDir,
|
|
14407
|
+
for (const path of removed) pruneEmptyDirsUpward(projectDir, dirname8(join35(projectDir, path)));
|
|
13402
14408
|
return failed > 0 ? { ok: false, message: `${failed} file(s) could not be removed`, notes } : { ok: true, notes };
|
|
13403
14409
|
}
|
|
13404
14410
|
function pruneEmptyDirsUpward(projectDir, startDir) {
|
|
13405
14411
|
let cursor = startDir;
|
|
13406
14412
|
while (true) {
|
|
13407
|
-
const rel =
|
|
13408
|
-
if (rel === "" || rel.startsWith(`..${
|
|
14413
|
+
const rel = relative6(projectDir, cursor);
|
|
14414
|
+
if (rel === "" || rel.startsWith(`..${sep6}`) || rel === "..") return;
|
|
13409
14415
|
try {
|
|
13410
|
-
if (
|
|
13411
|
-
|
|
14416
|
+
if (readdirSync7(cursor).length > 0) return;
|
|
14417
|
+
rmdirSync3(cursor);
|
|
13412
14418
|
} catch {
|
|
13413
14419
|
return;
|
|
13414
14420
|
}
|
|
13415
|
-
cursor =
|
|
14421
|
+
cursor = dirname8(cursor);
|
|
13416
14422
|
}
|
|
13417
14423
|
}
|
|
13418
14424
|
function stripRootImport(projectDir) {
|
|
@@ -13420,8 +14426,8 @@ function stripRootImport(projectDir) {
|
|
|
13420
14426
|
const stripped = current === null ? null : stripHarnessImport(current);
|
|
13421
14427
|
if (stripped === null) return false;
|
|
13422
14428
|
try {
|
|
13423
|
-
backupIfLossyUtf8(
|
|
13424
|
-
|
|
14429
|
+
backupIfLossyUtf8(join35(projectDir, "CLAUDE.md"));
|
|
14430
|
+
writeFileSync9(join35(projectDir, "CLAUDE.md"), stripped, "utf8");
|
|
13425
14431
|
return true;
|
|
13426
14432
|
} catch {
|
|
13427
14433
|
return false;
|
|
@@ -13432,7 +14438,7 @@ function hasRootImport(projectDir) {
|
|
|
13432
14438
|
return current !== null && stripHarnessImport(current) !== null;
|
|
13433
14439
|
}
|
|
13434
14440
|
function readRootClaudeMd(projectDir) {
|
|
13435
|
-
const path =
|
|
14441
|
+
const path = join35(projectDir, "CLAUDE.md");
|
|
13436
14442
|
if (!existsSync26(path)) return null;
|
|
13437
14443
|
try {
|
|
13438
14444
|
return readFileSync26(path, "utf8");
|
|
@@ -13445,7 +14451,7 @@ function defaultSpawn2(cmd, args) {
|
|
|
13445
14451
|
}
|
|
13446
14452
|
function defaultRm(path) {
|
|
13447
14453
|
if (existsSync26(path)) {
|
|
13448
|
-
|
|
14454
|
+
rmSync5(path, { recursive: true, force: true });
|
|
13449
14455
|
}
|
|
13450
14456
|
}
|
|
13451
14457
|
function registerUninstallCommand(cli) {
|