@dev.sail.money/sailor 0.0.2 → 0.1.0-local
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/AGENTS.md +140 -111
- package/LICENSE +21 -21
- package/README.md +430 -337
- package/docs/PERMISSION_MODEL.md +93 -93
- package/examples/permissions/BoundedApproveAndCallBatch.sol +179 -0
- package/examples/permissions/BoundedBet_Limitless_Base.sol +97 -96
- package/examples/permissions/BoundedBorrow_AaveV3_Arbitrum.sol +94 -94
- package/examples/permissions/BoundedPerp_GMXv2_Arbitrum.sol +154 -143
- package/examples/permissions/BoundedStake_Venice_Base.sol +85 -0
- package/examples/permissions/BoundedSupply_AaveV3_Arbitrum.sol +82 -0
- package/examples/permissions/BoundedSwap_UniswapV3_Base.sol +116 -113
- package/examples/permissions/BoundedSwap_UniswapV4_Unichain.sol +150 -144
- package/examples/permissions/BoundedTransfer_ERC20_Ethereum.sol +73 -73
- package/examples/permissions/BoundedVault_ERC4626_Base.sol +97 -0
- package/examples/permissions/README.md +79 -52
- package/examples/permissions/SailCalldata.sol +118 -0
- package/examples/permissions/foundry.toml +10 -10
- package/examples/permissions/interfaces/IBatchPermission.sol +38 -0
- package/examples/permissions/interfaces/IPermission.sol +18 -18
- package/package.json +45 -39
- package/packages/cli/README.md +34 -34
- package/packages/cli/dist/index.cjs +4571 -2944
- package/packages/cli/dist/server.cjs +1252 -2010
- package/packages/sdk/README.md +65 -65
- package/packages/sdk/dist/chains.d.ts +12 -0
- package/packages/sdk/dist/chains.d.ts.map +1 -0
- package/packages/sdk/dist/chains.js +94 -0
- package/packages/sdk/dist/chains.js.map +1 -0
- package/packages/sdk/dist/deployments.d.ts +14 -7
- package/packages/sdk/dist/deployments.d.ts.map +1 -1
- package/packages/sdk/dist/deployments.js +132 -141
- package/packages/sdk/dist/deployments.js.map +1 -1
- package/packages/sdk/dist/index.d.ts +3 -2
- package/packages/sdk/dist/index.d.ts.map +1 -1
- package/packages/sdk/dist/index.js +3 -2
- package/packages/sdk/dist/index.js.map +1 -1
- package/packages/sdk/dist/intelligence.d.ts +1 -1
- package/packages/sdk/dist/intelligence.js +1 -1
- package/packages/sdk/dist/lifi.d.ts +17 -0
- package/packages/sdk/dist/lifi.d.ts.map +1 -1
- package/packages/sdk/dist/lifi.js +24 -0
- package/packages/sdk/dist/lifi.js.map +1 -1
- package/packages/sdk/dist/safe.d.ts +83 -0
- package/packages/sdk/dist/safe.d.ts.map +1 -1
- package/packages/sdk/dist/safe.js +92 -1
- package/packages/sdk/dist/safe.js.map +1 -1
- package/packages/sdk/dist/templates/ammLiquidity.d.ts +24 -11
- package/packages/sdk/dist/templates/ammLiquidity.d.ts.map +1 -1
- package/packages/sdk/dist/templates/ammLiquidity.js +39 -31
- package/packages/sdk/dist/templates/ammLiquidity.js.map +1 -1
- package/packages/sdk/dist/templates/approveAndCallBatch.d.ts +24 -10
- package/packages/sdk/dist/templates/approveAndCallBatch.d.ts.map +1 -1
- package/packages/sdk/dist/templates/approveAndCallBatch.js +36 -23
- package/packages/sdk/dist/templates/approveAndCallBatch.js.map +1 -1
- package/packages/sdk/dist/templates/boundedBorrow.d.ts +19 -9
- package/packages/sdk/dist/templates/boundedBorrow.d.ts.map +1 -1
- package/packages/sdk/dist/templates/boundedBorrow.js +28 -19
- package/packages/sdk/dist/templates/boundedBorrow.js.map +1 -1
- package/packages/sdk/dist/templates/boundedSwap.d.ts +19 -9
- package/packages/sdk/dist/templates/boundedSwap.d.ts.map +1 -1
- package/packages/sdk/dist/templates/boundedSwap.js +30 -20
- package/packages/sdk/dist/templates/boundedSwap.js.map +1 -1
- package/packages/sdk/dist/templates/defiBundle.d.ts +35 -9
- package/packages/sdk/dist/templates/defiBundle.d.ts.map +1 -1
- package/packages/sdk/dist/templates/defiBundle.js +84 -22
- package/packages/sdk/dist/templates/defiBundle.js.map +1 -1
- package/packages/sdk/dist/templates/pendle.d.ts +23 -8
- package/packages/sdk/dist/templates/pendle.d.ts.map +1 -1
- package/packages/sdk/dist/templates/pendle.js +34 -14
- package/packages/sdk/dist/templates/pendle.js.map +1 -1
- package/packages/sdk/dist/templates/transferTarget.d.ts +11 -3
- package/packages/sdk/dist/templates/transferTarget.d.ts.map +1 -1
- package/packages/sdk/dist/templates/transferTarget.js +14 -7
- package/packages/sdk/dist/templates/transferTarget.js.map +1 -1
- package/packages/sdk/dist/types.d.ts +19 -1
- package/packages/sdk/dist/types.d.ts.map +1 -1
- package/packages/sdk/package.json +80 -52
- package/packages/ui/dist/assets/{add-DaJhwIBV.js → add-BxpXfVWe.js} +1 -1
- package/packages/ui/dist/assets/{all-wallets-BUxsqWXi.js → all-wallets-BKTn_sWK.js} +1 -1
- package/packages/ui/dist/assets/{app-store-DkltwTqE.js → app-store-CfuKbwxR.js} +1 -1
- package/packages/ui/dist/assets/{apple-owVOeaIT.js → apple-BKSBbNYg.js} +1 -1
- package/packages/ui/dist/assets/{arrow-bottom-D2mmNJve.js → arrow-bottom-D4bG6gZi.js} +1 -1
- package/packages/ui/dist/assets/{arrow-bottom-circle-CbNYijx-.js → arrow-bottom-circle-BNTs1p0T.js} +1 -1
- package/packages/ui/dist/assets/{arrow-left-DJB61s4C.js → arrow-left-2uee3vYv.js} +1 -1
- package/packages/ui/dist/assets/{arrow-right-BBrsQ9R4.js → arrow-right-BktjMV6h.js} +1 -1
- package/packages/ui/dist/assets/{arrow-top-Cil6bOc8.js → arrow-top-Izu28fX4.js} +1 -1
- package/packages/ui/dist/assets/{bank-CbwEmRo3.js → bank-USBaAyFM.js} +1 -1
- package/packages/ui/dist/assets/{basic-CLNfjw3m.js → basic-C_9KjTEH.js} +1 -1
- package/packages/ui/dist/assets/{browser-B5TtF4Pb.js → browser-DAEMAKV7.js} +1 -1
- package/packages/ui/dist/assets/{card-CO7BVB-C.js → card-DT8yDkKN.js} +1 -1
- package/packages/ui/dist/assets/{ccip-2W7K3_J3.js → ccip-CkqfGSxX.js} +1 -1
- package/packages/ui/dist/assets/{checkmark-BEtSHq9m.js → checkmark-CsgdEXFj.js} +1 -1
- package/packages/ui/dist/assets/{checkmark-bold-D9xGHzPE.js → checkmark-bold-D2gjOQo2.js} +1 -1
- package/packages/ui/dist/assets/{chevron-bottom-BDztht6i.js → chevron-bottom-tprFynYV.js} +1 -1
- package/packages/ui/dist/assets/{chevron-left-EV4GFNbc.js → chevron-left-D2Zj1gNB.js} +1 -1
- package/packages/ui/dist/assets/{chevron-right-B4_bB9oR.js → chevron-right-D1rRuAVe.js} +1 -1
- package/packages/ui/dist/assets/{chevron-top-D54xPNzF.js → chevron-top-24dL1mbL.js} +1 -1
- package/packages/ui/dist/assets/{chrome-store-DYUpAJJq.js → chrome-store-Vy-5niYX.js} +1 -1
- package/packages/ui/dist/assets/{clock-Ca1T1Soz.js → clock-qBjLnVdJ.js} +1 -1
- package/packages/ui/dist/assets/{close-BZqWjurK.js → close-DARDwgcu.js} +1 -1
- package/packages/ui/dist/assets/{coinPlaceholder-e6fl2XDo.js → coinPlaceholder-BvpIbPlD.js} +1 -1
- package/packages/ui/dist/assets/{compass-DCLC7zIh.js → compass-BMTO0ayt.js} +1 -1
- package/packages/ui/dist/assets/{copy-Th2AaD-O.js → copy-PaXeRHza.js} +1 -1
- package/packages/ui/dist/assets/{core-Ckx_cyuH.js → core-BFnStQd-.js} +3 -3
- package/packages/ui/dist/assets/cursor-BDvw-B17.js +3 -0
- package/packages/ui/dist/assets/{cursor-transparent-BKHeABKB.js → cursor-transparent-BEMdi-8q.js} +1 -1
- package/packages/ui/dist/assets/{desktop-CBjY8t6F.js → desktop-CfuLLThw.js} +1 -1
- package/packages/ui/dist/assets/{disconnect-DbSs2cli.js → disconnect-DhwgJMiR.js} +1 -1
- package/packages/ui/dist/assets/{discord-ZlLOAUkM.js → discord-po8qoN1s.js} +1 -1
- package/packages/ui/dist/assets/{etherscan-CKUrqWYN.js → etherscan-BEsz0_yx.js} +1 -1
- package/packages/ui/dist/assets/{events-CiKP71cK.js → events-Bz33Unzu.js} +1 -1
- package/packages/ui/dist/assets/{exclamation-triangle-DA1QzFiO.js → exclamation-triangle-7CjTAGOQ.js} +1 -1
- package/packages/ui/dist/assets/{extension-BVJkmvpJ.js → extension-CmxjEWEt.js} +1 -1
- package/packages/ui/dist/assets/{external-link-D_bsR7B2.js → external-link-CmQ--bNS.js} +1 -1
- package/packages/ui/dist/assets/{facebook-CmFmhojx.js → facebook-CIBn9b65.js} +1 -1
- package/packages/ui/dist/assets/{fallback-Ofl6uSnB.js → fallback-DATyrQlb.js} +1 -1
- package/packages/ui/dist/assets/{farcaster-Co-M3Ss8.js → farcaster-OJ3Jasxg.js} +1 -1
- package/packages/ui/dist/assets/{filters-B1WwNaFU.js → filters-D4x09zeL.js} +1 -1
- package/packages/ui/dist/assets/{github-CP4fP6gn.js → github-ZlIuMArp.js} +1 -1
- package/packages/ui/dist/assets/{google-CsOIXJ6V.js → google-Gwg85sfv.js} +1 -1
- package/packages/ui/dist/assets/{help-circle-DiMkomdF.js → help-circle-D1uOWYcX.js} +1 -1
- package/packages/ui/dist/assets/{id-lmscL5LX.js → id-C0-5UdYk.js} +1 -1
- package/packages/ui/dist/assets/{image-B-ubJrY5.js → image-D_DUsv8-.js} +1 -1
- package/packages/ui/dist/assets/{index-CZR1Qjhs.js → index-BCzex_R6.js} +1 -1
- package/packages/ui/dist/assets/index-BUhrHLpY.js +1775 -0
- package/packages/ui/dist/assets/index-Cq02kQmy.css +1 -0
- package/packages/ui/dist/assets/{index-BaukYv-x.js → index-CrYzBWfD.js} +1 -1
- package/packages/ui/dist/assets/{index-CF0KMmke.js → index-DdbJhIdl.js} +3 -3
- package/packages/ui/dist/assets/{index-DVgfCzCo.js → index-DiojfeVM.js} +1 -1
- package/packages/ui/dist/assets/{index-Dbh5V1Z0.js → index-izd7vu_r.js} +1 -1
- package/packages/ui/dist/assets/{index.es-C78cE5SI.js → index.es-DdkHhQAj.js} +4 -4
- package/packages/ui/dist/assets/{info-Cqg57EVo.js → info-CiRd_kEG.js} +1 -1
- package/packages/ui/dist/assets/{info-circle-DkeSWNKV.js → info-circle-ypxjqarK.js} +1 -1
- package/packages/ui/dist/assets/{lightbulb-DNlO4qKh.js → lightbulb-B-pxLxd8.js} +1 -1
- package/packages/ui/dist/assets/{mail-kVQ8Jb9Y.js → mail-BYmicuVZ.js} +1 -1
- package/packages/ui/dist/assets/{metamask-sdk-CBalSvz7.js → metamask-sdk-Ccl6DG7Q.js} +1 -1
- package/packages/ui/dist/assets/{mobile-BEteuhF7.js → mobile-CtP5PqVT.js} +1 -1
- package/packages/ui/dist/assets/{more-DBWmXQli.js → more-6C2733we.js} +1 -1
- package/packages/ui/dist/assets/{network-placeholder-Dg1uUHiL.js → network-placeholder-CdhxMzqd.js} +1 -1
- package/packages/ui/dist/assets/{nftPlaceholder-i3AHSiD9.js → nftPlaceholder-DVmTWEAY.js} +1 -1
- package/packages/ui/dist/assets/{off-BtMm0fi2.js → off-DNYLughs.js} +1 -1
- package/packages/ui/dist/assets/{parseSignature-Cb5FlWWg.js → parseSignature-Dq2B5Bu3.js} +1 -1
- package/packages/ui/dist/assets/{play-store-iKKkXa6a.js → play-store-D7Qut5ta.js} +1 -1
- package/packages/ui/dist/assets/{plus-CA5NaRtb.js → plus-kqMyjt3q.js} +1 -1
- package/packages/ui/dist/assets/{qr-code-D2kiqR7h.js → qr-code-DiUCWRbz.js} +1 -1
- package/packages/ui/dist/assets/{recycle-horizontal-Dcme7R03.js → recycle-horizontal-Boe3XiS-.js} +1 -1
- package/packages/ui/dist/assets/{refresh-Dega3sDp.js → refresh-CrBgBQYO.js} +1 -1
- package/packages/ui/dist/assets/{reown-logo-xNkksyWJ.js → reown-logo-CFZCCHSx.js} +1 -1
- package/packages/ui/dist/assets/{search-HYl7NO8x.js → search-ChTDrghU.js} +1 -1
- package/packages/ui/dist/assets/{secp256k1-Cxd6_SiH.js → secp256k1-DAV5Q_FR.js} +1 -1
- package/packages/ui/dist/assets/{send-CJU8CUAo.js → send-DLFbBFe1.js} +1 -1
- package/packages/ui/dist/assets/{swapHorizontal-IMUKiUre.js → swapHorizontal-BEs3emfG.js} +1 -1
- package/packages/ui/dist/assets/{swapHorizontalBold-CNYnNJ9-.js → swapHorizontalBold-CC-Hfa7W.js} +1 -1
- package/packages/ui/dist/assets/{swapHorizontalMedium-B9VxEYsT.js → swapHorizontalMedium-BmR0H8DC.js} +1 -1
- package/packages/ui/dist/assets/{swapHorizontalRoundedBold-Dz33l_Jh.js → swapHorizontalRoundedBold-BdP5NGIH.js} +1 -1
- package/packages/ui/dist/assets/{swapVertical-CHUmjVJ0.js → swapVertical-CPrGEJPY.js} +1 -1
- package/packages/ui/dist/assets/{telegram-kl9S2mbU.js → telegram-CxNoZ80Q.js} +1 -1
- package/packages/ui/dist/assets/{three-dots-U5lhA1Am.js → three-dots-BRa6SBpL.js} +1 -1
- package/packages/ui/dist/assets/{twitch-KTEUWXEp.js → twitch-BC338bG5.js} +1 -1
- package/packages/ui/dist/assets/{twitterIcon-BHiq8mRg.js → twitterIcon-BGZmt2i9.js} +1 -1
- package/packages/ui/dist/assets/{verify-CfN-BXNd.js → verify-CEstW0zw.js} +1 -1
- package/packages/ui/dist/assets/{verify-filled-DwZccetj.js → verify-filled-OkZb0weU.js} +1 -1
- package/packages/ui/dist/assets/{w3m-modal-CS-PFqPE.js → w3m-modal-pS09ECwE.js} +1 -1
- package/packages/ui/dist/assets/{wallet-DVlGkhOY.js → wallet-BXVKCgC9.js} +1 -1
- package/packages/ui/dist/assets/{wallet-placeholder-CvR_iEWX.js → wallet-placeholder-C_kNhB1c.js} +1 -1
- package/packages/ui/dist/assets/{walletconnect-8pZBDvVI.js → walletconnect-CRKIuUHH.js} +1 -1
- package/packages/ui/dist/assets/{warning-circle-ylLEE0Yp.js → warning-circle-DB2NnwlJ.js} +1 -1
- package/packages/ui/dist/assets/{x-C_TBsTMj.js → x-DT4RmwL5.js} +1 -1
- package/packages/ui/dist/index.html +14 -14
- package/scripts/check-docs.mjs +262 -262
- package/scripts/check-init.mjs +108 -109
- package/scripts/postinstall.js +81 -366
- package/templates/custom-mandate/.sail/contracts/interfaces/IPermission.sol +18 -18
- package/templates/custom-mandate/README.md +116 -85
- package/templates/custom-mandate/foundry.toml +8 -8
- package/templates/custom-mandate/mandates/BoundedCallPermission.sol +41 -35
- package/templates/custom-mandate/mandates/README.md +16 -16
- package/templates/custom-mandate/mandates/SailCalldata.sol +118 -0
- package/templates/{dca-rebalancer → default}/.cursor/rules +25 -25
- package/templates/default/.env.example +20 -0
- package/templates/{dca-rebalancer → default}/.github/workflows/agent-tick.yml +33 -32
- package/templates/{dca-rebalancer → default}/.sail/README.md +13 -13
- package/templates/{dca-rebalancer → default}/.sail/config.json +10 -10
- package/templates/default/AGENTS.md +171 -0
- package/templates/{dca-rebalancer → default}/CLAUDE.md +2 -2
- package/templates/default/README.md +16 -0
- package/templates/{dca-rebalancer → default}/_gitignore +13 -13
- package/templates/{dca-rebalancer → default}/docs/PERMISSION_MODEL.md +93 -93
- package/templates/default/examples/dca/README.md +16 -0
- package/templates/default/examples/dca/agent.ts +174 -0
- package/templates/{dca-rebalancer/src → default/examples/dca}/mandate.ts +45 -67
- package/templates/{dca-rebalancer → default}/package.json +17 -17
- package/templates/default/src/agent.ts +37 -0
- package/templates/default/src/config.ts +24 -0
- package/templates/default/src/mandate.ts +22 -0
- package/templates/default/tsconfig.json +17 -0
- package/templates/{dca-rebalancer → default}/ui/README.md +3 -3
- package/templates/lifi-permissions/LifiBoundedApprovePermissionCloneable.sol +84 -84
- package/templates/lifi-permissions/LifiDiamondSwapPermissionCloneable.sol +97 -97
- package/templates/lifi-permissions/README.md +53 -53
- package/packages/ui/dist/assets/cursor-DV7rOqbJ.js +0 -3
- package/packages/ui/dist/assets/index-CKxgNxS9.css +0 -1
- package/packages/ui/dist/assets/index-Q2Yai4Fe.js +0 -2103
- package/templates/dca-rebalancer/.env.example +0 -6
- package/templates/dca-rebalancer/AGENTS.md +0 -246
- package/templates/dca-rebalancer/AGENT_PLAYBOOK.md +0 -110
- package/templates/dca-rebalancer/README.md +0 -16
- package/templates/dca-rebalancer/src/agent.ts +0 -253
- package/templates/dca-rebalancer/src/config.ts +0 -27
- package/templates/dca-rebalancer/tsconfig.json +0 -8
- /package/templates/{dca-rebalancer → default}/.sail/.gitkeep +0 -0
package/scripts/check-init.mjs
CHANGED
|
@@ -1,109 +1,108 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* `sailor init` smoke test.
|
|
4
|
-
*
|
|
5
|
-
* Scaffolds a fresh project from the in-tree CLI bundle into a temp dir and
|
|
6
|
-
* asserts the scaffold succeeded. This exists to catch the class of regression
|
|
7
|
-
* the doc-drift gate structurally cannot — e.g. `packageRoot()` resolving to a
|
|
8
|
-
* `bin.sailor` package that ships no `templates/`, which made `init` fail from a
|
|
9
|
-
* monorepo checkout with "Template ... not found. Available: none".
|
|
10
|
-
*
|
|
11
|
-
* It runs the REAL built bundle from a monorepo layout, which is exactly the
|
|
12
|
-
* in-tree path that broke before. Pure Node + child_process; the only build
|
|
13
|
-
* dependency is the CLI bundle (`pnpm --filter sailor build`).
|
|
14
|
-
*
|
|
15
|
-
* Run: node scripts/check-init.mjs (CI builds the CLI first)
|
|
16
|
-
* Exit: 0 = scaffold OK, 1 = failure (prints what was missing).
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
import { execFileSync } from "node:child_process";
|
|
20
|
-
import fs from "node:fs";
|
|
21
|
-
import os from "node:os";
|
|
22
|
-
import path from "node:path";
|
|
23
|
-
import { fileURLToPath } from "node:url";
|
|
24
|
-
|
|
25
|
-
const ROOT = path.join(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
26
|
-
const BUNDLE = path.join(ROOT, "packages/cli/dist/index.cjs");
|
|
27
|
-
const PROJECT = "smoke-agent";
|
|
28
|
-
|
|
29
|
-
function fail(msg) {
|
|
30
|
-
console.error(`✗ init smoke test FAILED: ${msg}`);
|
|
31
|
-
process.exit(1);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (!fs.existsSync(BUNDLE)) {
|
|
35
|
-
fail(`CLI bundle not found at ${BUNDLE}.\n Build it first: pnpm --filter sailor build`);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// Scaffold into a temp dir. `init` requires the destination to live inside the
|
|
39
|
-
// process cwd, so we run the bundle with cwd set to a fresh temp root.
|
|
40
|
-
const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), "sailor-init-smoke-"));
|
|
41
|
-
const dest = path.join(tmpRoot, PROJECT);
|
|
42
|
-
|
|
43
|
-
try {
|
|
44
|
-
let stdout = "";
|
|
45
|
-
try {
|
|
46
|
-
stdout = execFileSync(process.execPath, [BUNDLE, "init", PROJECT], {
|
|
47
|
-
cwd: tmpRoot,
|
|
48
|
-
encoding: "utf-8",
|
|
49
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
50
|
-
});
|
|
51
|
-
} catch (err) {
|
|
52
|
-
const out = `${err.stdout ?? ""}${err.stderr ?? ""}`.trim();
|
|
53
|
-
fail(`\`sailor init ${PROJECT}\` exited non-zero.\n ${out || err.message}`);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// A successful fresh init prints the
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
".
|
|
65
|
-
"
|
|
66
|
-
"
|
|
67
|
-
"
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
//
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
if (pkg.
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
//
|
|
87
|
-
//
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
99
|
-
if (
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
console.log(
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
fs.rmSync(
|
|
108
|
-
|
|
109
|
-
}
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* `sailor init` smoke test.
|
|
4
|
+
*
|
|
5
|
+
* Scaffolds a fresh project from the in-tree CLI bundle into a temp dir and
|
|
6
|
+
* asserts the scaffold succeeded. This exists to catch the class of regression
|
|
7
|
+
* the doc-drift gate structurally cannot — e.g. `packageRoot()` resolving to a
|
|
8
|
+
* `bin.sailor` package that ships no `templates/`, which made `init` fail from a
|
|
9
|
+
* monorepo checkout with "Template ... not found. Available: none".
|
|
10
|
+
*
|
|
11
|
+
* It runs the REAL built bundle from a monorepo layout, which is exactly the
|
|
12
|
+
* in-tree path that broke before. Pure Node + child_process; the only build
|
|
13
|
+
* dependency is the CLI bundle (`pnpm --filter sailor build`).
|
|
14
|
+
*
|
|
15
|
+
* Run: node scripts/check-init.mjs (CI builds the CLI first)
|
|
16
|
+
* Exit: 0 = scaffold OK, 1 = failure (prints what was missing).
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { execFileSync } from "node:child_process";
|
|
20
|
+
import fs from "node:fs";
|
|
21
|
+
import os from "node:os";
|
|
22
|
+
import path from "node:path";
|
|
23
|
+
import { fileURLToPath } from "node:url";
|
|
24
|
+
|
|
25
|
+
const ROOT = path.join(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
26
|
+
const BUNDLE = path.join(ROOT, "packages/cli/dist/index.cjs");
|
|
27
|
+
const PROJECT = "smoke-agent";
|
|
28
|
+
|
|
29
|
+
function fail(msg) {
|
|
30
|
+
console.error(`✗ init smoke test FAILED: ${msg}`);
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (!fs.existsSync(BUNDLE)) {
|
|
35
|
+
fail(`CLI bundle not found at ${BUNDLE}.\n Build it first: pnpm --filter sailor build`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Scaffold into a temp dir. `init` requires the destination to live inside the
|
|
39
|
+
// process cwd, so we run the bundle with cwd set to a fresh temp root.
|
|
40
|
+
const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), "sailor-init-smoke-"));
|
|
41
|
+
const dest = path.join(tmpRoot, PROJECT);
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
let stdout = "";
|
|
45
|
+
try {
|
|
46
|
+
stdout = execFileSync(process.execPath, [BUNDLE, "init", PROJECT], {
|
|
47
|
+
cwd: tmpRoot,
|
|
48
|
+
encoding: "utf-8",
|
|
49
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
50
|
+
});
|
|
51
|
+
} catch (err) {
|
|
52
|
+
const out = `${err.stdout ?? ""}${err.stderr ?? ""}`.trim();
|
|
53
|
+
fail(`\`sailor init ${PROJECT}\` exited non-zero.\n ${out || err.message}`);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// A successful fresh init prints the single-line handoff to the AI assistant.
|
|
57
|
+
if (!/say start/i.test(stdout)) {
|
|
58
|
+
fail(`init did not report success.\n stdout: ${stdout.trim()}`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Assert the scaffold landed.
|
|
62
|
+
const mustExist = [
|
|
63
|
+
".sail/config.json",
|
|
64
|
+
"package.json",
|
|
65
|
+
"foundry.toml",
|
|
66
|
+
"mandates",
|
|
67
|
+
"AGENTS.md",
|
|
68
|
+
];
|
|
69
|
+
for (const rel of mustExist) {
|
|
70
|
+
if (!fs.existsSync(path.join(dest, rel))) fail(`expected scaffolded "${rel}" — not found`);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// config.json is valid JSON named after the project.
|
|
74
|
+
const config = JSON.parse(fs.readFileSync(path.join(dest, ".sail/config.json"), "utf-8"));
|
|
75
|
+
if (config.name !== PROJECT) fail(`config.json name is "${config.name}", expected "${PROJECT}"`);
|
|
76
|
+
|
|
77
|
+
// package.json is valid, renamed, and the workspace protocol was resolved away
|
|
78
|
+
// (a leftover "workspace:*" would make the scaffold un-installable for users).
|
|
79
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(dest, "package.json"), "utf-8"));
|
|
80
|
+
if (pkg.name !== PROJECT) fail(`package.json name is "${pkg.name}", expected "${PROJECT}"`);
|
|
81
|
+
if (pkg.dependencies?.["@sail/sdk"] === "workspace:*") {
|
|
82
|
+
fail(`package.json still has "@sail/sdk": "workspace:*" — init did not resolve it`);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Regression guard: an absolute path outside the cwd must be REJECTED, not
|
|
86
|
+
// silently nested into `<cwd>/<abs path>`. (Pre-fix, `path.join` swallowed the
|
|
87
|
+
// leading slash and scaffolded a bogus nested tree while printing success.)
|
|
88
|
+
const outside = path.join(os.tmpdir(), "sailor-init-outside", "agent");
|
|
89
|
+
let rejected = false;
|
|
90
|
+
try {
|
|
91
|
+
execFileSync(process.execPath, [BUNDLE, "init", outside], {
|
|
92
|
+
cwd: tmpRoot,
|
|
93
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
94
|
+
});
|
|
95
|
+
} catch {
|
|
96
|
+
rejected = true; // non-zero exit = correctly refused
|
|
97
|
+
}
|
|
98
|
+
if (!rejected) fail(`an absolute path outside cwd ("${outside}") was accepted — should be rejected`);
|
|
99
|
+
if (fs.existsSync(path.join(outside, ".sail/config.json"))) {
|
|
100
|
+
fail(`init scaffolded into an out-of-cwd absolute path "${outside}"`);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
console.log(`✓ init smoke test passed — scaffolded ${PROJECT}/ from the in-tree bundle`);
|
|
104
|
+
console.log("✓ init guard passed — absolute path outside cwd rejected, not silently nested");
|
|
105
|
+
} finally {
|
|
106
|
+
fs.rmSync(path.join(os.tmpdir(), "sailor-init-outside"), { recursive: true, force: true });
|
|
107
|
+
fs.rmSync(tmpRoot, { recursive: true, force: true });
|
|
108
|
+
}
|