@transcend-io/cli 10.29.0 → 10.29.2
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/{app-C5baDSA2.mjs → app-DxjIt23c.mjs} +16 -16
- package/dist/{app-C5baDSA2.mjs.map → app-DxjIt23c.mjs.map} +1 -1
- package/dist/{approvePrivacyRequests-B8x7oxTn.mjs → approvePrivacyRequests-CFKObXCt.mjs} +2 -2
- package/dist/{approvePrivacyRequests-B8x7oxTn.mjs.map → approvePrivacyRequests-CFKObXCt.mjs.map} +1 -1
- package/dist/bin/bash-complete.mjs +1 -1
- package/dist/bin/cli.mjs +1 -1
- package/dist/bin/deprecated-command.mjs +1 -1
- package/dist/{buildExamples-7KXBjl-b.mjs → buildExamples-DTMKJ2pF.mjs} +2 -2
- package/dist/{buildExamples-7KXBjl-b.mjs.map → buildExamples-DTMKJ2pF.mjs.map} +1 -1
- package/dist/{buildXdiSyncEndpoint-DcrkZ2Gu.mjs → buildXdiSyncEndpoint-D8YJpLZd.mjs} +2 -2
- package/dist/{buildXdiSyncEndpoint-DcrkZ2Gu.mjs.map → buildXdiSyncEndpoint-D8YJpLZd.mjs.map} +1 -1
- package/dist/{bulkRestartRequests-CysUfl98.mjs → bulkRestartRequests-CMdTpO-W.mjs} +2 -2
- package/dist/{bulkRestartRequests-CysUfl98.mjs.map → bulkRestartRequests-CMdTpO-W.mjs.map} +1 -1
- package/dist/{bulkRetryEnrichers-DaLE67Ht.mjs → bulkRetryEnrichers-DeLVA0zH.mjs} +2 -2
- package/dist/{bulkRetryEnrichers-DaLE67Ht.mjs.map → bulkRetryEnrichers-DeLVA0zH.mjs.map} +1 -1
- package/dist/{cancelPrivacyRequests-D0zNUNdS.mjs → cancelPrivacyRequests-DvRHEAjF.mjs} +2 -2
- package/dist/{cancelPrivacyRequests-D0zNUNdS.mjs.map → cancelPrivacyRequests-DvRHEAjF.mjs.map} +1 -1
- package/dist/{command-CIv9yk86.mjs → command-jo1QPpAq.mjs} +2 -2
- package/dist/{command-CIv9yk86.mjs.map → command-jo1QPpAq.mjs.map} +1 -1
- package/dist/{constants-jjHIzHGm.mjs → constants-BnIMwfNb.mjs} +2 -2
- package/dist/{constants-jjHIzHGm.mjs.map → constants-BnIMwfNb.mjs.map} +1 -1
- package/dist/{createPoolingCommandUi-uiDjLlqf.mjs → createPoolingCommandUi-CE6fvB2v.mjs} +2 -2
- package/dist/{createPoolingCommandUi-uiDjLlqf.mjs.map → createPoolingCommandUi-CE6fvB2v.mjs.map} +1 -1
- package/dist/{downloadPrivacyRequestFiles-B_BVxW5Z.mjs → downloadPrivacyRequestFiles-DUFTfiZL.mjs} +2 -2
- package/dist/{downloadPrivacyRequestFiles-B_BVxW5Z.mjs.map → downloadPrivacyRequestFiles-DUFTfiZL.mjs.map} +1 -1
- package/dist/{generateCrossAccountApiKeys-Bnqgmj-H.mjs → generateCrossAccountApiKeys-BNze2Fyn.mjs} +2 -2
- package/dist/{generateCrossAccountApiKeys-Bnqgmj-H.mjs.map → generateCrossAccountApiKeys-BNze2Fyn.mjs.map} +1 -1
- package/dist/{impl-xq89cSSz2.mjs → impl-B-nmILxQ2.mjs} +2 -2
- package/dist/{impl-xq89cSSz2.mjs.map → impl-B-nmILxQ2.mjs.map} +1 -1
- package/dist/{impl-DNe-gRXe2.mjs → impl-BA0u3f6F2.mjs} +2 -2
- package/dist/{impl-DNe-gRXe2.mjs.map → impl-BA0u3f6F2.mjs.map} +1 -1
- package/dist/{impl-BH_A5rgL.mjs → impl-BQjsGfVz.mjs} +2 -2
- package/dist/{impl-BH_A5rgL.mjs.map → impl-BQjsGfVz.mjs.map} +1 -1
- package/dist/{impl-BqWQh9Ss.mjs → impl-BUVf0UQ0.mjs} +2 -2
- package/dist/{impl-BqWQh9Ss.mjs.map → impl-BUVf0UQ0.mjs.map} +1 -1
- package/dist/{impl-CXTBcYo6.mjs → impl-BUbupZLV.mjs} +2 -2
- package/dist/{impl-CXTBcYo6.mjs.map → impl-BUbupZLV.mjs.map} +1 -1
- package/dist/{impl-XrTL-TDl.mjs → impl-Bq0lE7N5.mjs} +2 -2
- package/dist/{impl-XrTL-TDl.mjs.map → impl-Bq0lE7N5.mjs.map} +1 -1
- package/dist/{impl-BOawPhYE.mjs → impl-C3EjC8hF.mjs} +2 -2
- package/dist/{impl-BOawPhYE.mjs.map → impl-C3EjC8hF.mjs.map} +1 -1
- package/dist/{impl-Bc6p8A1l2.mjs → impl-CMDIQiHg2.mjs} +2 -2
- package/dist/{impl-Bc6p8A1l2.mjs.map → impl-CMDIQiHg2.mjs.map} +1 -1
- package/dist/{impl-DuZjI6p0.mjs → impl-CMFrsj8b.mjs} +2 -2
- package/dist/{impl-DuZjI6p0.mjs.map → impl-CMFrsj8b.mjs.map} +1 -1
- package/dist/{impl-CQVy2k3o.mjs → impl-Cav9IgWW.mjs} +2 -2
- package/dist/{impl-CQVy2k3o.mjs.map → impl-Cav9IgWW.mjs.map} +1 -1
- package/dist/{impl-INhq_CiK.mjs → impl-CdSGCsQD.mjs} +2 -2
- package/dist/{impl-INhq_CiK.mjs.map → impl-CdSGCsQD.mjs.map} +1 -1
- package/dist/{impl-2iVTxNn4.mjs → impl-Cgy6VLCF.mjs} +2 -2
- package/dist/{impl-2iVTxNn4.mjs.map → impl-Cgy6VLCF.mjs.map} +1 -1
- package/dist/{impl-BXUYpR27.mjs → impl-CnoGZZoX.mjs} +2 -2
- package/dist/{impl-BXUYpR27.mjs.map → impl-CnoGZZoX.mjs.map} +1 -1
- package/dist/{impl-RPG-BTmX.mjs → impl-CoNyUtMT.mjs} +2 -2
- package/dist/{impl-RPG-BTmX.mjs.map → impl-CoNyUtMT.mjs.map} +1 -1
- package/dist/{impl-CwXp3Tbr.mjs → impl-CrdDX-vS.mjs} +2 -2
- package/dist/{impl-CwXp3Tbr.mjs.map → impl-CrdDX-vS.mjs.map} +1 -1
- package/dist/{impl-DMe_OqJx.mjs → impl-D9ae4SOp.mjs} +2 -2
- package/dist/{impl-DMe_OqJx.mjs.map → impl-D9ae4SOp.mjs.map} +1 -1
- package/dist/{impl-KmCNH-yw.mjs → impl-DM0nXs11.mjs} +2 -2
- package/dist/{impl-KmCNH-yw.mjs.map → impl-DM0nXs11.mjs.map} +1 -1
- package/dist/{impl-CwKYKBYb.mjs → impl-DMaHiR8F.mjs} +2 -2
- package/dist/{impl-CwKYKBYb.mjs.map → impl-DMaHiR8F.mjs.map} +1 -1
- package/dist/{impl-CvLI_Jig.mjs → impl-DRGgLGNU.mjs} +2 -2
- package/dist/{impl-CvLI_Jig.mjs.map → impl-DRGgLGNU.mjs.map} +1 -1
- package/dist/{impl-DVQmuZQY.mjs → impl-DRvnUtsd.mjs} +2 -2
- package/dist/{impl-DVQmuZQY.mjs.map → impl-DRvnUtsd.mjs.map} +1 -1
- package/dist/{impl-Dw8NYkzw.mjs → impl-DayplqEn.mjs} +2 -2
- package/dist/{impl-Dw8NYkzw.mjs.map → impl-DayplqEn.mjs.map} +1 -1
- package/dist/{impl-BDrvzlpf2.mjs → impl-DdHPAFYq2.mjs} +2 -2
- package/dist/{impl-BDrvzlpf2.mjs.map → impl-DdHPAFYq2.mjs.map} +1 -1
- package/dist/{impl-DK7nSMle2.mjs → impl-Dn_PyB5_2.mjs} +2 -2
- package/dist/{impl-DK7nSMle2.mjs.map → impl-Dn_PyB5_2.mjs.map} +1 -1
- package/dist/{impl-DLG0Egy6.mjs → impl-Dzqr61LA.mjs} +2 -2
- package/dist/{impl-DLG0Egy6.mjs.map → impl-Dzqr61LA.mjs.map} +1 -1
- package/dist/{impl-DNzkRayg.mjs → impl-RgoaYjMi.mjs} +2 -2
- package/dist/{impl-DNzkRayg.mjs.map → impl-RgoaYjMi.mjs.map} +1 -1
- package/dist/{impl-DypttZd6.mjs → impl-RuQc4nQ6.mjs} +2 -2
- package/dist/{impl-DypttZd6.mjs.map → impl-RuQc4nQ6.mjs.map} +1 -1
- package/dist/{impl-DEhw1iNn.mjs → impl-Yb5jtD4V.mjs} +2 -2
- package/dist/{impl-DEhw1iNn.mjs.map → impl-Yb5jtD4V.mjs.map} +1 -1
- package/dist/{impl-CL29fOWM.mjs → impl-_bJkh9UY.mjs} +2 -2
- package/dist/{impl-CL29fOWM.mjs.map → impl-_bJkh9UY.mjs.map} +1 -1
- package/dist/{impl-Dx_TfvW1.mjs → impl-cA3shutB.mjs} +2 -2
- package/dist/{impl-Dx_TfvW1.mjs.map → impl-cA3shutB.mjs.map} +1 -1
- package/dist/{impl-DEJpYLPB.mjs → impl-cjVcQvnQ.mjs} +2 -2
- package/dist/{impl-DEJpYLPB.mjs.map → impl-cjVcQvnQ.mjs.map} +1 -1
- package/dist/{impl-CyQRmuM72.mjs → impl-ehFICcp72.mjs} +2 -2
- package/dist/{impl-CyQRmuM72.mjs.map → impl-ehFICcp72.mjs.map} +1 -1
- package/dist/{impl-CuDs6SsI.mjs → impl-oGSoHT2a.mjs} +2 -2
- package/dist/{impl-CuDs6SsI.mjs.map → impl-oGSoHT2a.mjs.map} +1 -1
- package/dist/{impl-hwpT9u5o2.mjs → impl-x9HLXhsK2.mjs} +2 -2
- package/dist/{impl-hwpT9u5o2.mjs.map → impl-x9HLXhsK2.mjs.map} +1 -1
- package/dist/{impl-B-j5ACi02.mjs → impl-zVgfQ0im2.mjs} +2 -2
- package/dist/{impl-B-j5ACi02.mjs.map → impl-zVgfQ0im2.mjs.map} +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{markRequestDataSiloIdsCompleted-B5N-cQWr.mjs → markRequestDataSiloIdsCompleted-DX7d2Itu.mjs} +2 -2
- package/dist/{markRequestDataSiloIdsCompleted-B5N-cQWr.mjs.map → markRequestDataSiloIdsCompleted-DX7d2Itu.mjs.map} +1 -1
- package/dist/{markSilentPrivacyRequests-BiaButWF.mjs → markSilentPrivacyRequests-3t9IZPpS.mjs} +2 -2
- package/dist/{markSilentPrivacyRequests-BiaButWF.mjs.map → markSilentPrivacyRequests-3t9IZPpS.mjs.map} +1 -1
- package/dist/{notifyPrivacyRequestsAdditionalTime-D3Vtvg5G.mjs → notifyPrivacyRequestsAdditionalTime-Ce_GPf6U.mjs} +2 -2
- package/dist/{notifyPrivacyRequestsAdditionalTime-D3Vtvg5G.mjs.map → notifyPrivacyRequestsAdditionalTime-Ce_GPf6U.mjs.map} +1 -1
- package/dist/{pullChunkedCustomSiloOutstandingIdentifiers-D85P1W_8.mjs → pullChunkedCustomSiloOutstandingIdentifiers-3OvSjU15.mjs} +2 -2
- package/dist/{pullChunkedCustomSiloOutstandingIdentifiers-D85P1W_8.mjs.map → pullChunkedCustomSiloOutstandingIdentifiers-3OvSjU15.mjs.map} +1 -1
- package/dist/{pullManualEnrichmentIdentifiersToCsv-DbNSrKEk.mjs → pullManualEnrichmentIdentifiersToCsv-B9AfaSwT.mjs} +2 -2
- package/dist/{pullManualEnrichmentIdentifiersToCsv-DbNSrKEk.mjs.map → pullManualEnrichmentIdentifiersToCsv-B9AfaSwT.mjs.map} +1 -1
- package/dist/{pushCronIdentifiersFromCsv-5ruUKHtL.mjs → pushCronIdentifiersFromCsv-ByCv8bd4.mjs} +2 -2
- package/dist/{pushCronIdentifiersFromCsv-5ruUKHtL.mjs.map → pushCronIdentifiersFromCsv-ByCv8bd4.mjs.map} +1 -1
- package/dist/{pushManualEnrichmentIdentifiersFromCsv-B0i2239u.mjs → pushManualEnrichmentIdentifiersFromCsv-BQYjiA9G.mjs} +2 -2
- package/dist/{pushManualEnrichmentIdentifiersFromCsv-B0i2239u.mjs.map → pushManualEnrichmentIdentifiersFromCsv-BQYjiA9G.mjs.map} +1 -1
- package/dist/{removeUnverifiedRequestIdentifiers-QmeqrmxM.mjs → removeUnverifiedRequestIdentifiers-DOYx5k0N.mjs} +2 -2
- package/dist/{removeUnverifiedRequestIdentifiers-QmeqrmxM.mjs.map → removeUnverifiedRequestIdentifiers-DOYx5k0N.mjs.map} +1 -1
- package/dist/{retryRequestDataSilos-BfckLjOJ.mjs → retryRequestDataSilos-CUAhRnGs.mjs} +2 -2
- package/dist/{retryRequestDataSilos-BfckLjOJ.mjs.map → retryRequestDataSilos-CUAhRnGs.mjs.map} +1 -1
- package/dist/{skipPreflightJobs-Do_kwu3m.mjs → skipPreflightJobs-CpJMKv7V.mjs} +2 -2
- package/dist/{skipPreflightJobs-Do_kwu3m.mjs.map → skipPreflightJobs-CpJMKv7V.mjs.map} +1 -1
- package/dist/{skipRequestDataSilos-BNDhdllD.mjs → skipRequestDataSilos-BkVAyIwG.mjs} +2 -2
- package/dist/{skipRequestDataSilos-BNDhdllD.mjs.map → skipRequestDataSilos-BkVAyIwG.mjs.map} +1 -1
- package/dist/{streamPrivacyRequestsToCsv-CbJfhV6A.mjs → streamPrivacyRequestsToCsv-CkIiJexX.mjs} +2 -2
- package/dist/{streamPrivacyRequestsToCsv-CbJfhV6A.mjs.map → streamPrivacyRequestsToCsv-CkIiJexX.mjs.map} +1 -1
- package/dist/{updateConsentManagerVersionToLatest-DEFwH4Se.mjs → updateConsentManagerVersionToLatest-BR_UWjal.mjs} +2 -2
- package/dist/{updateConsentManagerVersionToLatest-DEFwH4Se.mjs.map → updateConsentManagerVersionToLatest-BR_UWjal.mjs.map} +1 -1
- package/dist/{uploadConsents-ChmFIw_j.mjs → uploadConsents-DeNdLfPd.mjs} +2 -2
- package/dist/{uploadConsents-ChmFIw_j.mjs.map → uploadConsents-DeNdLfPd.mjs.map} +1 -1
- package/dist/{uploadPrivacyRequestsFromCsv-D3KSb1qH.mjs → uploadPrivacyRequestsFromCsv-CxtOU5CQ.mjs} +2 -2
- package/dist/{uploadPrivacyRequestsFromCsv-D3KSb1qH.mjs.map → uploadPrivacyRequestsFromCsv-CxtOU5CQ.mjs.map} +1 -1
- package/package.json +4 -4
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{g as e}from"./constants-
|
|
1
|
+
import{g as e}from"./constants-BnIMwfNb.mjs";import{a as t,c as n,i as r,l as i,o as a,r as o,s,t as c}from"./policy-runtime-BMKa-Upy.mjs";import{t as l}from"./done-input-validation-BUz-aVC5.mjs";import{a as u,c as d,d as f,f as p,g as m,h,i as g,l as ee,m as _,n as v,p as y,r as te,t as ne,u as re}from"./prompts-ClBXdELk.mjs";import{t as ie}from"./run-captured-process-BXwWXuTh.mjs";import{t as ae}from"./project-plan-apply-Dvndx455.mjs";import{n as b,r as x,t as S}from"./jsonc-D9dDWb1J.mjs";import{isAbsolute as C,join as w,posix as T,relative as E,resolve as oe,sep as D}from"node:path";import O from"colors";const k=`transcend/policy`;function se(e,t=k){let n=e.process.cwd(),r=oe(n,t);if(e.fs.existsSync(r)&&!e.fs.statSync(r).isDirectory())throw Error(`Policy target is not a directory: ${r}`);return{invocationDirectory:n,targetDirectory:r,...u(e,{invocationDirectory:n,targetDirectory:r,standaloneProjectRoot:n}),relativePaths:g(e,r),relativeFilePaths:g(e,r,{includeDirectories:!1})}}function ce(e){return w(e.targetDirectory,`manifest.json`)}const A={Editor:`editor`,Skill:`skill`,Ci:`ci`};var le=`# Idiomatic Rego and document-tree authoring
|
|
2
2
|
|
|
3
3
|
## Start from the document tree
|
|
4
4
|
|
|
@@ -300,4 +300,4 @@ jobs:
|
|
|
300
300
|
`,warnings:r};try{return{contents:S(e,t,n),warnings:r}}catch(t){return{contents:e??`{}
|
|
301
301
|
`,warnings:[...r,`${t instanceof Error?t.message:String(t)} Existing content was left unchanged.`]}}}function K(e,t,n,r){t.forEach(({path:t,value:i,label:a})=>{let o=t.reduce((e,t)=>e&&typeof e==`object`&&!Array.isArray(e)?e[t]:void 0,e);o===void 0?n.push({path:t,value:i}):U(o,i)||r.push(`VS Code setting "${a}" has a repository-specific value and was left unchanged.`)})}function me(e,t){let n=E(e,t).split(D).join(`/`)||`.`;return n===`.`?"${workspaceFolder}":`\${workspaceFolder}/${n}`}function he(e,t,n){let r=W(e,`VS Code policy settings`);if(`warning`in r)return{contents:r.contents,warnings:[r.warning]};let{current:i}=r,a=[],o=[],s=i[`opa.roots`],c=me(t,n);if(s===void 0)a.push({path:[`opa.roots`],value:[c]});else if(Array.isArray(s)&&s.every(e=>typeof e==`string`)){let e=b(s,[c]);U(e,s)||a.push({path:[`opa.roots`],value:e})}else o.push(`VS Code setting "opa.roots" is customized and was left unchanged.`);K(i,[{path:[`opa.checkOnSave`],value:!0,label:`opa.checkOnSave`},{path:[`opa.strictMode`],value:!0,label:`opa.strictMode`},{path:[`opa.bundleMode`],value:!0,label:`opa.bundleMode`},{path:[`opa.formatter`],value:`opa-fmt-rego-v1`,label:`opa.formatter`}],a,o);let l=i[`[rego]`];return l===void 0?a.push({path:[`[rego]`],value:{"editor.defaultFormatter":V,"editor.formatOnSave":!0,"editor.insertSpaces":!1,"editor.tabSize":4}}):typeof l==`object`&&l&&!Array.isArray(l)?K(i,[{path:[`[rego]`,`editor.defaultFormatter`],value:V,label:`[rego].editor.defaultFormatter`},{path:[`[rego]`,`editor.formatOnSave`],value:!0,label:`[rego].editor.formatOnSave`},{path:[`[rego]`,`editor.insertSpaces`],value:!1,label:`[rego].editor.insertSpaces`},{path:[`[rego]`,`editor.tabSize`],value:4,label:`[rego].editor.tabSize`}],a,o):o.push(`VS Code language setting "[rego]" is customized and was left unchanged.`),G(e,a,`VS Code policy settings`,o)}function ge(e){let t=W(e,`VS Code policy extension recommendations`);if(`warning`in t)return{contents:t.contents,warnings:[t.warning]};let{current:n}=t,r=[],i=[],a=n.recommendations;if(a===void 0||Array.isArray(a)&&a.every(e=>typeof e==`string`)){let e=a??[],t=b(e,[V]).filter(e=>e!==H);U(e,t)||r.push({path:[`recommendations`],value:t})}else i.push(`VS Code extension recommendations use an unknown shape and were left unchanged.`);let o=n.unwantedRecommendations;if(o===void 0||Array.isArray(o)&&o.every(e=>typeof e==`string`)){let e=o??[],t=b(e,[H]);U(e,t)||r.push({path:[`unwantedRecommendations`],value:t})}else i.push(`VS Code unwanted extension recommendations use an unknown shape and were left unchanged.`);return G(e,r,`VS Code policy extension recommendations`,i)}function _e(e,t){return{label:`policy: lint`,type:`process`,command:`transcend`,args:[`policy`,`lint`,`--dir`,E(e,t).split(D).join(`/`)||`.`,`--noInteractive`],group:{kind:`test`,isDefault:!0},problemMatcher:[]}}function ve(e,t,n){let r=W(e,`VS Code policy tasks`);if(`warning`in r)return{contents:r.contents,warnings:[r.warning]};let{current:i}=r,a=[],o=[],s=i.version;s===void 0?a.push({path:[`version`],value:`2.0.0`}):s!==`2.0.0`&&o.push(`VS Code task schema version is customized and was left unchanged.`);let c=_e(t,n),l=i.tasks;if(l===void 0)a.push({path:[`tasks`],value:[c]});else if(Array.isArray(l)){let e=l.find(e=>typeof e==`object`&&!!e&&!Array.isArray(e)&&e.label===`policy: lint`);e===void 0?a.push({path:[`tasks`],value:[...l,c]}):U(e,c)||o.push(`VS Code task "policy: lint" has repository-specific customization and was left unchanged.`)}else o.push(`VS Code tasks use an unknown shape and were left unchanged.`);return G(e,a,`VS Code policy tasks`,o)}const q={name:j,displayName:`Policy Engine`,owner:`@transcend-io/cli`,files:M};function ye(e){return`transcend policy lint --dir ${_(y(e.invocationDirectory,e.targetDirectory))} --noInteractive`}function J(e,t){let n=new Set(L().map(({path:t})=>w(e.targetDirectory,t))),r=new Set(t.features);return r.has(A.Editor)&&(n.add(w(e.projectRoot,`.vscode`,`settings.json`)),n.add(w(e.projectRoot,`.vscode`,`extensions.json`)),n.add(w(e.projectRoot,`.vscode`,`tasks.json`))),r.has(A.Skill)&&d(e.projectRoot,e.existingSkillDirectories,q).forEach(e=>n.add(e)),r.has(A.Ci)&&e.repositoryRoot&&e.usesGithub&&n.add(w(e.repositoryRoot,R)),[...n].sort((e,t)=>e.localeCompare(t))}function Y(e,t){let n=E(e,t);if(n===`..`||n.startsWith(`..${D}`)||C(n))throw Error(`Refusing to modify path outside project root: ${t}`)}function be(e){let t=new Set([`input.json`]);return e.forEach(({path:e})=>{t.add(e);let n=T.dirname(e);for(;n!==`.`;)t.add(n),n=T.dirname(n)}),t}function X(e,t,n){let r=p({snapshot:re(t.snapshots,n.path),after:n.contents,description:n.description,...n.createOnly===void 0?{}:{createOnly:n.createOnly}});r?e.changes.push(r):e.unchanged.push(n.path)}function xe(e,t,n,r,i,a){X(e,t,{path:n,contents:r.contents,description:i}),e.warnings.push(...r.warnings.map(e=>`${e} (${y(a,n)})`))}function Se(e,t){let{state:n}=e,r=L(),i=ce(n),a=ye(n),o=w(n.targetDirectory,`policy_engine`,`example`,`result.rego`),s={version:1,command:`init`,rootDirectory:n.projectRoot,targetDirectory:n.targetDirectory,manifestPath:i,changes:[],unchanged:[],warnings:[],nextSteps:[a],features:[...t.features]},c=J(n,t);Y(n.projectRoot,n.targetDirectory),c.forEach(e=>Y(n.projectRoot,e));let l=!1;if(n.relativeFilePaths.length===0)l=!0,s.directoryPreconditions=[{path:n.targetDirectory,relativePaths:[...n.relativePaths]}],r.forEach(t=>{let r=w(n.targetDirectory,t.path);if(f(e.snapshots,r).kind!==`absent`)throw Error(`Expected an empty policy target, but found an entry at: ${r}`);X(s,e,{path:r,contents:t.contents,description:t.description,createOnly:!0})});else{let t=!0;r.forEach(r=>{let i=w(n.targetDirectory,r.path),a=f(e.snapshots,i);if(a.kind===`file`&&a.contents===r.contents){s.unchanged.push(i);return}t=!1,a.kind!==`absent`&&(s.unchanged.push(i),s.warnings.push(`Existing policy scaffold path was left unchanged: ${y(n.invocationDirectory,i)}`))}),l=t;let i=be(r),o=n.relativeFilePaths.some(e=>!i.has(e));(!t||o)&&s.warnings.push(`Existing policy target contains custom or partial content, so no starter files were added or overwritten. Review ${y(n.invocationDirectory,n.targetDirectory)} manually, then run \`${a}\`.`)}l&&(s.disposableExamplePath=o,s.nextSteps.push(`Edit ${_(y(n.invocationDirectory,o))}`));let u=new Set(t.features),d=n.projectRoot;if(u.has(A.Editor)){let t=w(d,`.vscode`,`settings.json`),r=w(d,`.vscode`,`extensions.json`),i=w(d,`.vscode`,`tasks.json`);[{path:t,description:`Merge strict target-scoped OPA and Rego editor settings`,merge:he},{path:r,description:`Recommend the OPA extension and discourage its syntax-only conflict`,merge:(e,t,n)=>ge(e)},{path:i,description:`Add the default target-scoped policy lint task`,merge:ve}].forEach(({path:t,description:r,merge:i})=>{let a=f(e.snapshots,t);if(a.kind!==`absent`&&a.kind!==`file`){s.unchanged.push(t),s.warnings.push(`Existing VS Code artifact is not a regular file and was left unchanged: ${y(n.invocationDirectory,t)}`);return}xe(s,e,t,i(a.kind===`file`?a.contents:null,d,n.targetDirectory),r,n.invocationDirectory)})}if(u.has(A.Skill)){let t=ee({rootDirectory:d,existingDirectories:n.existingSkillDirectories,snapshots:e.snapshots,skill:q,preserveModified:!0});s.changes.push(...t.changes),s.unchanged.push(...t.unchanged),s.warnings.push(...t.warnings.map(e=>t.unchanged.reduce((e,t)=>e.replace(t,y(n.invocationDirectory,t)),e)))}if(u.has(A.Ci))if(!n.repositoryRoot||!n.usesGithub)s.warnings.push(`GitHub Actions setup was selected, but this target is not inside a detected GitHub repository.`);else{let r=w(n.repositoryRoot,R),i=E(n.repositoryRoot,n.targetDirectory).split(D).join(`/`)||`.`,o=B({cliVersion:t.cliVersion,targetDirectory:i}),c=f(e.snapshots,r);c.kind===`absent`?X(s,e,{path:r,contents:o,description:`Add credential-free Policy Engine validation`,createOnly:!0}):c.kind===`file`&&c.contents===o?s.unchanged.push(r):(s.unchanged.push(r),s.warnings.push(`Existing GitHub Actions workflow was left unchanged: ${y(n.invocationDirectory,r)}. Adapt it manually to run \`${a}\`.`))}return s.changes.forEach(({path:e})=>Y(n.projectRoot,e)),s}const Z={[A.Editor]:`VS Code settings and lint task`,[A.Skill]:`Policy Engine Agent Skill`,[A.Ci]:`Validation-only GitHub Actions`},Q=Object.values(A);function Ce(e,t,n){return!e.json&&!e.noInteractive&&!!(t&&n)}async function we(e,t,n){let r={[A.Editor]:t.editor,[A.Skill]:t.skill,[A.Ci]:t.ci};if(!n.interactive)return Q.filter(e=>r[e]===!0);let i=Q.map(e=>({name:Z[e],value:e,checked:r[e]!==!1}));return e.checkbox(`Choose repository setup:`,i)}function $(e,n){let r=[n.stdout.trim(),n.stderr.trim()].filter(Boolean).join(`
|
|
302
302
|
`),i=e===`OPA`?o:t;return`${e===`OPA`?`OPA 1.x`:`Regal ${c} or newer`} is required, but \`${e.toLowerCase()} version\` exited with code ${n.code}${r?`: ${r}`:`.`} Install or upgrade it using the official instructions: ${i}`}async function Te(e,t,o){let l={opa:null,regal:null},u=[],d=await o(`opa`,[`version`],{cwd:t},e);if(d.error?.code===`ENOENT`)u.push(r);else{let e=`${d.stdout}\n${d.stderr}`,t=n(e);d.code===0?t?u.push(t):l.opa=s(e).version:u.push(t??$(`OPA`,d))}let f=await o(`regal`,[`version`],{cwd:t},e);if(f.error?.code===`ENOENT`)u.push(a);else{let e=`${f.stdout}\n${f.stderr}`,t=i(e,c,`the generated OPA 1.13.1 capabilities configuration`);f.code===0?t?u.push(t):l.regal=s(e).version:u.push(t??$(`Regal`,f))}return{tools:l,warnings:u}}async function Ee(t,n=k,r=ie){l(this.process);try{let i=await Te(this,this.process.cwd(),r),a=se(this,n),o=new v(this),s=Ce(t,this.process.stdin.isTTY,this.process.stderr.isTTY),c=await we(o,t,{interactive:s}),l=J(a,{features:c}),u=Se({state:a,snapshots:te(this,a.projectRoot,l)},{features:c,cliVersion:e});u.warnings.push(...i.warnings),t.json||this.logger.info(h(u,{cwd:this.process.cwd(),title:`Policy initialization plan`,details:[{label:`Target`,path:u.targetDirectory},{label:`Manifest`,path:u.manifestPath}]}));let d=u.changes.length===0||t.dryRun;if(u.changes.length>0&&!t.dryRun)if(t.yes)d=!0;else if(s)d=await o.confirm(`Apply this complete plan?`,!0);else throw Error(`The plan requires approval in a non-interactive invocation. Review with --dryRun, then pass --yes.`);d&&!t.dryRun&&u.changes.length>0&&await ae(this,u);let f=d&&!t.dryRun&&u.changes.length>0,p=d&&!t.dryRun,m=N({projectPath:_(y(this.process.cwd(),a.targetDirectory)),...u.disposableExamplePath?{examplePath:_(y(this.process.cwd(),u.disposableExamplePath))}:{},hasSkill:p&&c.includes(A.Skill),lintCommand:u.nextSteps[0]}),g=P(u,{applied:f,dryRun:t.dryRun,cwd:this.process.cwd(),aiHandoff:m,tools:i.tools});if(t.json){this.process.stdout.write(`${JSON.stringify(g)}\n`);return}if(t.dryRun){this.logger.info(O.yellow(`Dry run complete. No changes were written.`));return}if(!d){this.logger.info(O.yellow(`No changes applied.`));return}if(u.changes.length===0){let e=u.warnings.length===i.warnings.length?`Policy project is already initialized.`:`Existing policy project was left unchanged.`;this.logger.info(O.green(e))}else this.logger.info(O.green(`Policy project initialized.`));u.nextSteps.length>0&&(this.logger.info(`\n${O.bold(`Next steps`)}`),u.nextSteps.forEach(e=>this.logger.info(e))),this.logger.info(`\n${O.bold(`AI handoff — paste into your coding agent`)}`),this.logger.info(m)}catch(e){if(e instanceof ne)return this.process.exit(130);throw e}}export{Ee as init};
|
|
303
|
-
//# sourceMappingURL=impl-
|
|
303
|
+
//# sourceMappingURL=impl-Dn_PyB5_2.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impl-DK7nSMle2.mjs","names":["POLICY_SKILL_MD","POLICY_SETUP_TOOLING_REFERENCE_MD","POLICY_AUTHORING_REFERENCE_MD","POLICY_TESTING_DEBUGGING_REFERENCE_MD","POLICY_PUBLISHING_REFERENCE_MD","CLI_VERSION"],"sources":["../src/lib/policy/policy-project-discovery.ts","../src/lib/policy/policy-scaffold-model.ts","../../../skills/transcend-policy-engine/references/authoring.md","../../../skills/transcend-policy-engine/references/publishing.md","../../../skills/transcend-policy-engine/references/setup-tooling.md","../../../skills/transcend-policy-engine/references/testing-debugging.md","../../../skills/transcend-policy-engine/SKILL.md","../src/lib/policy/policy-skill.ts","../src/lib/policy/policy-scaffold-output.ts","../src/lib/policy/policy-scaffold-templates.ts","../src/lib/policy/policy-scaffold-artifacts.ts","../src/lib/policy/policy-scaffold-config.ts","../src/lib/policy/policy-scaffold-planning.ts","../src/commands/policy/init/impl.ts"],"sourcesContent":["import { join, resolve } from 'node:path';\n\nimport type { LocalContext } from '../../context.js';\nimport {\n collectProjectRelativePaths,\n discoverProjectRepository,\n} from '../scaffolding/project-discovery.js';\nimport type { PolicyProjectState } from './policy-scaffold-model.js';\n\n/** Default local policy project directory. */\nexport const DEFAULT_POLICY_PROJECT_DIRECTORY = 'transcend/policy';\n\n/**\n * Collect repository state required by the pure policy planner.\n *\n * @param context - CLI context\n * @param directory - User-selected target directory\n * @returns Policy project discovery state\n */\nexport function discoverPolicyProject(\n context: LocalContext,\n directory: string = DEFAULT_POLICY_PROJECT_DIRECTORY,\n): PolicyProjectState {\n const invocationDirectory = context.process.cwd();\n const targetDirectory = resolve(invocationDirectory, directory);\n if (\n context.fs.existsSync(targetDirectory) &&\n !context.fs.statSync(targetDirectory).isDirectory()\n ) {\n throw new Error(`Policy target is not a directory: ${targetDirectory}`);\n }\n const repository = discoverProjectRepository(context, {\n invocationDirectory,\n targetDirectory,\n standaloneProjectRoot: invocationDirectory,\n });\n return {\n invocationDirectory,\n targetDirectory,\n ...repository,\n relativePaths: collectProjectRelativePaths(context, targetDirectory),\n relativeFilePaths: collectProjectRelativePaths(context, targetDirectory, {\n includeDirectories: false,\n }),\n };\n}\n\n/**\n * Resolve the bundle manifest path for a discovered project.\n *\n * @param state - Policy project state\n * @returns Absolute manifest path\n */\nexport function getPolicyManifestPath(state: PolicyProjectState): string {\n return join(state.targetDirectory, 'manifest.json');\n}\n","import type { ExistingProjectSkillDirectory } from '../scaffolding/agent-skill.js';\nimport type { ProjectPlan } from '../scaffolding/project-plan.js';\n\n/** Version of the stable policy initialization JSON result. */\nexport const POLICY_INIT_RESULT_VERSION = 1 as const;\n\n/** Optional repository integrations for policy authoring. */\nexport const PolicySetupFeature = {\n /** Repository-level editor configuration. */\n Editor: 'editor',\n /** Managed policy authoring skill. */\n Skill: 'skill',\n /** Credential-free continuous integration. */\n Ci: 'ci',\n} as const;\n\n/** Optional repository integration for policy authoring. */\nexport type PolicySetupFeature = (typeof PolicySetupFeature)[keyof typeof PolicySetupFeature];\n\n/** Repository and target state collected before policy planning. */\nexport interface PolicyProjectState {\n /** Directory from which the CLI was invoked. */\n invocationDirectory: string;\n /** Absolute user-selected policy directory. */\n targetDirectory: string;\n /** Repository or invocation root that owns setup artifacts. */\n projectRoot: string;\n /** Nearest repository root, when present. */\n repositoryRoot?: string;\n /** Existing project-level skill directories. */\n existingSkillDirectories: ExistingProjectSkillDirectory[];\n /** Whether the repository appears to use GitHub. */\n usesGithub: boolean;\n /** Case-preserving relative paths below the policy directory. */\n relativePaths: string[];\n /** Relative file and link paths below the policy directory. */\n relativeFilePaths: string[];\n}\n\n/** A complete, validated policy initialization plan. */\nexport interface PolicyInitProjectPlan extends ProjectPlan {\n /** JSON contract version. */\n version: typeof POLICY_INIT_RESULT_VERSION;\n /** Command that produced the plan. */\n command: 'init';\n /** Absolute policy project directory. */\n targetDirectory: string;\n /** Absolute policy manifest path. */\n manifestPath: string;\n /** Files inspected and deliberately left unchanged. */\n unchanged: string[];\n /** Non-fatal plan warnings. */\n warnings: string[];\n /** Raw commands shown after a successful apply. */\n nextSteps: string[];\n /** Exact generated example that remains safe to replace. */\n disposableExamplePath?: string;\n /** Selected repository integrations. */\n features: PolicySetupFeature[];\n}\n",null,null,null,null,null,"import POLICY_AUTHORING_REFERENCE_MD from '../../../../../skills/transcend-policy-engine/references/authoring.md';\nimport POLICY_PUBLISHING_REFERENCE_MD from '../../../../../skills/transcend-policy-engine/references/publishing.md';\nimport POLICY_SETUP_TOOLING_REFERENCE_MD from '../../../../../skills/transcend-policy-engine/references/setup-tooling.md';\nimport POLICY_TESTING_DEBUGGING_REFERENCE_MD from '../../../../../skills/transcend-policy-engine/references/testing-debugging.md';\nimport POLICY_SKILL_MD from '../../../../../skills/transcend-policy-engine/SKILL.md';\nimport type { AgentSkillFile } from '../scaffolding/agent-skill.js';\n\n/** Namespaced directory and frontmatter name for the installed Agent Skill. */\nexport const POLICY_SKILL_NAME = 'transcend-policy-engine';\n\nexport {\n POLICY_AUTHORING_REFERENCE_MD,\n POLICY_PUBLISHING_REFERENCE_MD,\n POLICY_SETUP_TOOLING_REFERENCE_MD,\n POLICY_SKILL_MD,\n POLICY_TESTING_DEBUGGING_REFERENCE_MD,\n};\n\n/** Complete portable Policy Engine Agent Skill file set. */\nexport const POLICY_SKILL_FILES: readonly AgentSkillFile[] = [\n { path: 'SKILL.md', contents: POLICY_SKILL_MD },\n { path: 'references/setup-tooling.md', contents: POLICY_SETUP_TOOLING_REFERENCE_MD },\n { path: 'references/authoring.md', contents: POLICY_AUTHORING_REFERENCE_MD },\n { path: 'references/testing-debugging.md', contents: POLICY_TESTING_DEBUGGING_REFERENCE_MD },\n { path: 'references/publishing.md', contents: POLICY_PUBLISHING_REFERENCE_MD },\n];\n","import {\n toPublicPlannedChange,\n type PublicPlannedChange,\n} from '../scaffolding/project-plan-output.js';\nimport type { PolicyInitProjectPlan, PolicySetupFeature } from './policy-scaffold-model.js';\nimport { POLICY_SKILL_NAME } from './policy-skill.js';\n\n/** Detected local policy tool versions. */\nexport interface PolicyInitToolVersions {\n /** OPA version, or null when missing or incompatible. */\n opa: string | null;\n /** Regal version, or null when missing or incompatible. */\n regal: string | null;\n}\n\n/** Stable machine-readable policy initialization result. */\nexport interface PolicyInitPlanResult {\n /** JSON contract version. */\n version: number;\n /** Command that produced the result. */\n command: 'init';\n /** Whether the plan was applied. */\n applied: boolean;\n /** Whether this was a dry run. */\n dryRun: boolean;\n /** Absolute policy target directory. */\n targetDirectory: string;\n /** Absolute policy manifest path. */\n manifestPath: string;\n /** Planned mutations without file contents. */\n changes: PublicPlannedChange[];\n /** Non-fatal preservation and runtime warnings. */\n warnings: string[];\n /** Suggested raw one-line follow-up commands. */\n nextSteps: string[];\n /** Explicitly selected repository integrations. */\n features: PolicySetupFeature[];\n /** Compact prompt for continuing with a coding agent. */\n aiHandoff: string;\n /** Compatible local policy tool versions. */\n tools: PolicyInitToolVersions;\n}\n\n/**\n * Build the compact policy implementation and CI handoff.\n *\n * @param options - Portable example path and lint command\n * @returns Raw one-line prompt\n */\nexport function buildPolicyInitAiHandoff(options: {\n /** Display path to the policy project. */\n projectPath: string;\n /** Display path to an exact disposable example. */\n examplePath?: string;\n /** Whether the policy authoring skill was installed. */\n hasSkill: boolean;\n /** Copyable lint command. */\n lintCommand: string;\n}): string {\n if (!options.examplePath) {\n const instruction = options.hasSkill\n ? `Use the \\`${POLICY_SKILL_NAME}\\` skill to review`\n : 'Review';\n return (\n `${instruction} the existing policy project in ${options.projectPath}, ` +\n `align its document tree and input/output contract with the intended application, adapt ` +\n `repository validation as needed, and rerun ${options.lintCommand}.`\n );\n }\n const instruction = options.hasSkill\n ? `Use the \\`${POLICY_SKILL_NAME}\\` skill to replace`\n : 'Replace';\n return (\n `${instruction} the disposable example in ${options.examplePath} with ` +\n `the intended policy document tree and input/output contract, adapt repository validation ` +\n `to local conventions, and rerun ${options.lintCommand}.`\n );\n}\n\n/**\n * Build the stable machine-readable initialization result.\n *\n * @param plan - Policy project plan\n * @param options - Apply and runtime state\n * @returns Public JSON result\n */\nexport function buildPolicyInitPlanResult(\n plan: PolicyInitProjectPlan,\n options: {\n /** Whether the plan was applied. */\n applied: boolean;\n /** Whether this was a dry run. */\n dryRun: boolean;\n /** Working directory for portable paths. */\n cwd: string;\n /** Compact coding-agent prompt. */\n aiHandoff: string;\n /** Compatible local policy tool versions. */\n tools: PolicyInitToolVersions;\n },\n): PolicyInitPlanResult {\n return {\n version: plan.version,\n command: plan.command,\n applied: options.applied,\n dryRun: options.dryRun,\n targetDirectory: plan.targetDirectory,\n manifestPath: plan.manifestPath,\n changes: plan.changes.map((change) => toPublicPlannedChange(options.cwd, change)),\n warnings: plan.warnings,\n nextSteps: plan.nextSteps,\n features: [...plan.features],\n aiHandoff: options.aiHandoff,\n tools: options.tools,\n };\n}\n","/** OPA version targeted by generated policy authoring configuration. */\nexport const POLICY_STARTER_OPA_VERSION = '1.13.1';\n\n/** One deterministic file in the safe policy starter. */\nexport interface PolicyStarterFile {\n /** POSIX-style path relative to the policy directory. */\n path: string;\n /** Complete UTF-8 file contents. */\n contents: string;\n /** Human-readable reason shown in the plan. */\n description: string;\n}\n\n/** Publishable Policy Engine bundle manifest. */\nexport const POLICY_MANIFEST_TEMPLATE = `{\n \"roots\": [\"policy_engine\"]\n}\n`;\n\n/** Strict Regal project configuration pinned to the deployed OPA capabilities. */\nexport const POLICY_REGAL_CONFIG_TEMPLATE = `capabilities:\n from:\n engine: opa\n version: v${POLICY_STARTER_OPA_VERSION}\nproject:\n roots:\n - .\n rego-version: 1\n`;\n\n/** Disposable, fail-closed example policy. */\nexport const POLICY_RESULT_REGO_TEMPLATE = `package policy_engine.example\n\nimport rego.v1\n\n# METADATA\n# title: Disposable example result\n# description: |\n# A fail-closed teaching entrypoint. Replace this example with the document\n# tree and result contract required by your application.\n# entrypoint: true\ndefault result := {\n\t\"decision\": \"deny\",\n\t\"reason_code\": \"untrusted_or_invalid_input\",\n}\n\nresult := {\n\t\"decision\": \"allow\",\n\t\"reason_code\": \"trusted_subject\",\n} if {\n\tinput.subject.trusted == true\n}\n`;\n\n/** Executable tests adjacent to the disposable example policy. */\nexport const POLICY_RESULT_TEST_REGO_TEMPLATE = `package policy_engine.example_test\n\nimport data.policy_engine.example\nimport rego.v1\n\ntest_denies_untrusted_subject if {\n\tresult := example.result with input as {\"subject\": {\"trusted\": false}}\n\tresult == {\n\t\t\"decision\": \"deny\",\n\t\t\"reason_code\": \"untrusted_or_invalid_input\",\n\t}\n}\n\ntest_fails_closed_for_missing_subject if {\n\tresult := example.result with input as {}\n\tresult == {\n\t\t\"decision\": \"deny\",\n\t\t\"reason_code\": \"untrusted_or_invalid_input\",\n\t}\n}\n\ntest_allows_trusted_subject if {\n\tresult := example.result with input as {\"subject\": {\"trusted\": true}}\n\tresult == {\n\t\t\"decision\": \"allow\",\n\t\t\"reason_code\": \"trusted_subject\",\n\t}\n}\n`;\n\n/** Sanitized local input example containing no credentials or personal data. */\nexport const POLICY_INPUT_EXAMPLE_TEMPLATE = `{\n \"subject\": {\n \"trusted\": false\n }\n}\n`;\n\n/** Target-local ignore rules for private evaluation input only. */\nexport const POLICY_GITIGNORE_TEMPLATE = `# Local policy evaluation input.\n/input.json\n`;\n\n/** Concise project-local authoring guide. */\nexport const POLICY_README_TEMPLATE = `# Transcend Policy Project\n\nThis directory is an OPA document tree that can be published to Transcend Policy Engine.\n\nThe policy under \\`policy_engine/example\\` is disposable teaching material. Replace it with your intended package tree, input shape, and extensible result documents. Keep decisions fail-closed and cover every non-test package with \\`manifest.json\\`.\n\nValidate formatting, strict Rego v1 compatibility, Regal lint, tests, and the publish contract:\n\n\\`\\`\\`sh\ntranscend policy lint --dir .\n\\`\\`\\`\n`;\n\n/** Complete safe starter in deterministic plan order. */\nconst POLICY_STARTER_FILES: readonly PolicyStarterFile[] = [\n {\n path: 'manifest.json',\n contents: POLICY_MANIFEST_TEMPLATE,\n description: 'Create the publishable Policy Engine manifest',\n },\n {\n path: '.regal/config.yaml',\n contents: POLICY_REGAL_CONFIG_TEMPLATE,\n description: 'Pin strict Rego v1 linting to OPA 1.13.1 capabilities',\n },\n {\n path: 'policy_engine/example/result.rego',\n contents: POLICY_RESULT_REGO_TEMPLATE,\n description: 'Create a documented fail-closed result entrypoint',\n },\n {\n path: 'policy_engine/example/result_test.rego',\n contents: POLICY_RESULT_TEST_REGO_TEMPLATE,\n description: 'Create executable tests for allow and fail-closed decisions',\n },\n {\n path: 'input.example.json',\n contents: POLICY_INPUT_EXAMPLE_TEMPLATE,\n description: 'Create a sanitized local evaluation input',\n },\n {\n path: '.gitignore',\n contents: POLICY_GITIGNORE_TEMPLATE,\n description: 'Ignore only the private local input file',\n },\n {\n path: 'README.md',\n contents: POLICY_README_TEMPLATE,\n description: 'Create the concise policy project guide',\n },\n];\n\n/**\n * Generate an independent copy of the safe policy starter.\n *\n * @returns Deterministic relative files\n */\nexport function generatePolicyStarterFiles(): PolicyStarterFile[] {\n return POLICY_STARTER_FILES.map((file) => ({ ...file }));\n}\n","import { posix } from 'node:path';\n\nimport { POLICY_STARTER_OPA_VERSION } from './policy-scaffold-templates.js';\n\n/** Regal version pinned by generated policy validation. */\nexport const POLICY_STARTER_REGAL_VERSION = '0.42.0';\n\n/** Repository-relative generated workflow path. */\nexport const POLICY_CI_WORKFLOW_PATH = '.github/workflows/transcend-policy.yml';\n\n/** Immutable actions/checkout v6 release commit. */\nexport const ACTIONS_CHECKOUT_SHA = 'd23441a48e516b6c34aea4fa41551a30e30af803';\n\n/** Immutable open-policy-agent/setup-opa v2.4.0 release commit. */\nexport const SETUP_OPA_SHA = 'b2b258e089860efaadaaf71bf6e3aecb4a3eeff1';\n\n/** Immutable open-policy-agent/setup-regal v2.0.0 release commit. */\nexport const SETUP_REGAL_SHA = '761188c3b435761fa254beca508a44875619648f';\n\n/**\n * Prefix a path below the repository-relative policy target.\n *\n * @param targetDirectory - POSIX repository-relative target\n * @param child - POSIX target-relative path or pattern\n * @returns Repository-relative path or pattern\n */\nfunction targetPath(targetDirectory: string, child: string): string {\n return targetDirectory === '.' ? child : posix.join(targetDirectory, child);\n}\n\n/**\n * Generate credential-free, validation-only Policy Engine CI.\n *\n * @param options - Repository paths and exact CLI release\n * @returns Complete GitHub Actions workflow YAML\n */\nexport function generatePolicyGithubActionsWorkflow(options: {\n /** Exact released Transcend CLI version. */\n cliVersion: string;\n /** Policy directory relative to the repository root. */\n targetDirectory: string;\n}): string {\n const watchedPaths = [\n targetPath(options.targetDirectory, '**/*.rego'),\n targetPath(options.targetDirectory, '**/*.json'),\n targetPath(options.targetDirectory, '**/*.yaml'),\n targetPath(options.targetDirectory, '**/*.yml'),\n targetPath(options.targetDirectory, '.regal/config.yaml'),\n targetPath(options.targetDirectory, '.regal.yaml'),\n POLICY_CI_WORKFLOW_PATH,\n ];\n const pathFilters = watchedPaths.map((path) => ` - ${JSON.stringify(path)}`).join('\\n');\n\n return `# Generated by transcend policy init.\nname: Transcend Policy\n\non:\n pull_request:\n paths:\n${pathFilters}\n push:\n paths:\n${pathFilters}\n\npermissions:\n contents: read\n\njobs:\n lint:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@${ACTIONS_CHECKOUT_SHA} # v6\n - name: Set up OPA\n uses: open-policy-agent/setup-opa@${SETUP_OPA_SHA} # v2.4.0\n with:\n version: ${JSON.stringify(POLICY_STARTER_OPA_VERSION)}\n - name: Set up Regal\n uses: open-policy-agent/setup-regal@${SETUP_REGAL_SHA} # v2.0.0\n with:\n version: ${JSON.stringify(POLICY_STARTER_REGAL_VERSION)}\n - name: Install the Transcend CLI\n run: npm install --global @transcend-io/cli@${options.cliVersion}\n - name: Validate Policy Engine project\n env:\n POLICY_DIRECTORY: ${JSON.stringify(options.targetDirectory)}\n run: >-\n transcend policy lint\n --dir \"$POLICY_DIRECTORY\"\n --noInteractive\n --json\n`;\n}\n","import { relative, sep } from 'node:path';\n\nimport {\n mergeJsonc,\n mergeStringArray,\n parseJsoncObject,\n type JsoncUpdate,\n} from '../scaffolding/jsonc.js';\n\n/** Recommended VS Code extension for OPA and Regal authoring. */\nexport const POLICY_VSCODE_EXTENSION = 'tsandall.opa';\n\n/** Conflicting syntax-only VS Code extension. */\nexport const CONFLICTING_POLICY_VSCODE_EXTENSION = 'glebbash.opa-highlight-only';\n\n/** Result of safely merging one repository editor artifact. */\nexport interface PolicyEditorMergeResult {\n /** Complete merged contents, or the unchanged original when unsafe. */\n contents: string;\n /** Actionable preservation warnings. */\n warnings: string[];\n}\n\n/** One desired scalar setting that must not replace a customization. */\ninterface DesiredSetting {\n /** JSONC object path. */\n path: string[];\n /** Desired generated value. */\n value: unknown;\n /** Human-readable setting key. */\n label: string;\n}\n\n/**\n * Compare JSON-compatible configuration values.\n *\n * @param left - Existing value\n * @param right - Desired value\n * @returns Whether the values are structurally equal\n */\nfunction configurationValuesEqual(left: unknown, right: unknown): boolean {\n return JSON.stringify(left) === JSON.stringify(right);\n}\n\n/**\n * Parse an editor object while preserving malformed existing content.\n *\n * @param contents - Existing JSONC, or null\n * @param label - Configuration label\n * @returns Parsed object or a preservation result\n */\nfunction parseEditorObject(\n contents: string | null,\n label: string,\n):\n | {\n /** Parsed JSONC object. */\n current: Record<string, unknown>;\n }\n | {\n /** Complete unchanged contents. */\n contents: string;\n /** Actionable warning. */\n warning: string;\n } {\n try {\n return { current: parseJsoncObject(contents ?? '{}\\n', label) };\n } catch (error) {\n return {\n contents: contents ?? '{}\\n',\n warning: `${error instanceof Error ? error.message : String(error)} Existing content was left unchanged.`,\n };\n }\n}\n\n/**\n * Apply safe JSONC updates or preserve the existing file when comments prevent it.\n *\n * @param contents - Existing JSONC\n * @param updates - Proven-safe updates\n * @param label - Configuration label\n * @param warnings - Existing merge warnings\n * @returns Complete contents and warnings\n */\nfunction applyEditorUpdates(\n contents: string | null,\n updates: readonly JsoncUpdate[],\n label: string,\n warnings: string[],\n): PolicyEditorMergeResult {\n if (updates.length === 0) {\n return { contents: contents ?? '{}\\n', warnings };\n }\n try {\n return {\n contents: mergeJsonc(contents, updates, label),\n warnings,\n };\n } catch (error) {\n return {\n contents: contents ?? '{}\\n',\n warnings: [\n ...warnings,\n `${error instanceof Error ? error.message : String(error)} Existing content was left unchanged.`,\n ],\n };\n }\n}\n\n/**\n * Add absent scalar settings without replacing repository customizations.\n *\n * @param current - Parsed editor object\n * @param desired - Desired settings\n * @param updates - Safe updates to append to\n * @param warnings - Conflict warnings to append to\n */\nfunction collectSafeScalarUpdates(\n current: Record<string, unknown>,\n desired: readonly DesiredSetting[],\n updates: JsoncUpdate[],\n warnings: string[],\n): void {\n desired.forEach(({ path, value, label }) => {\n const existing = path.reduce<unknown>((parent, key) => {\n return parent && typeof parent === 'object' && !Array.isArray(parent)\n ? (parent as Record<string, unknown>)[key]\n : undefined;\n }, current);\n if (existing === undefined) {\n updates.push({ path, value });\n } else if (!configurationValuesEqual(existing, value)) {\n warnings.push(\n `VS Code setting \"${label}\" has a repository-specific value and was left unchanged.`,\n );\n }\n });\n}\n\n/**\n * Build the workspace-relative OPA bundle root.\n *\n * @param repositoryRoot - Root that owns `.vscode`\n * @param targetDirectory - Selected policy project directory\n * @returns VS Code workspace path\n */\nfunction buildOpaWorkspaceRoot(repositoryRoot: string, targetDirectory: string): string {\n const target = relative(repositoryRoot, targetDirectory).split(sep).join('/') || '.';\n return target === '.' ? '${workspaceFolder}' : `\\${workspaceFolder}/${target}`;\n}\n\n/**\n * Merge strict target-scoped OPA and Rego editor settings.\n *\n * Setting names match the authoritative `open-policy-agent/vscode-opa`\n * extension metadata. Existing conflicting values are preserved and reported.\n *\n * @param contents - Existing `.vscode/settings.json` JSONC\n * @param repositoryRoot - Root that owns `.vscode`\n * @param targetDirectory - Selected policy project directory\n * @returns Merged settings and conflict warnings\n */\nexport function mergePolicyEditorSettings(\n contents: string | null,\n repositoryRoot: string,\n targetDirectory: string,\n): PolicyEditorMergeResult {\n const parsed = parseEditorObject(contents, 'VS Code policy settings');\n if ('warning' in parsed) {\n return { contents: parsed.contents, warnings: [parsed.warning] };\n }\n const { current } = parsed;\n const updates: JsoncUpdate[] = [];\n const warnings: string[] = [];\n\n const roots = current['opa.roots'];\n const desiredRoot = buildOpaWorkspaceRoot(repositoryRoot, targetDirectory);\n if (roots === undefined) {\n updates.push({ path: ['opa.roots'], value: [desiredRoot] });\n } else if (Array.isArray(roots) && roots.every((value) => typeof value === 'string')) {\n const merged = mergeStringArray(roots, [desiredRoot]);\n if (!configurationValuesEqual(merged, roots)) {\n updates.push({ path: ['opa.roots'], value: merged });\n }\n } else {\n warnings.push('VS Code setting \"opa.roots\" is customized and was left unchanged.');\n }\n\n collectSafeScalarUpdates(\n current,\n [\n { path: ['opa.checkOnSave'], value: true, label: 'opa.checkOnSave' },\n { path: ['opa.strictMode'], value: true, label: 'opa.strictMode' },\n { path: ['opa.bundleMode'], value: true, label: 'opa.bundleMode' },\n { path: ['opa.formatter'], value: 'opa-fmt-rego-v1', label: 'opa.formatter' },\n ],\n updates,\n warnings,\n );\n\n const regoSettings = current['[rego]'];\n if (regoSettings === undefined) {\n updates.push({\n path: ['[rego]'],\n value: {\n 'editor.defaultFormatter': POLICY_VSCODE_EXTENSION,\n 'editor.formatOnSave': true,\n 'editor.insertSpaces': false,\n 'editor.tabSize': 4,\n },\n });\n } else if (\n regoSettings !== null &&\n typeof regoSettings === 'object' &&\n !Array.isArray(regoSettings)\n ) {\n collectSafeScalarUpdates(\n current,\n [\n {\n path: ['[rego]', 'editor.defaultFormatter'],\n value: POLICY_VSCODE_EXTENSION,\n label: '[rego].editor.defaultFormatter',\n },\n {\n path: ['[rego]', 'editor.formatOnSave'],\n value: true,\n label: '[rego].editor.formatOnSave',\n },\n {\n path: ['[rego]', 'editor.insertSpaces'],\n value: false,\n label: '[rego].editor.insertSpaces',\n },\n {\n path: ['[rego]', 'editor.tabSize'],\n value: 4,\n label: '[rego].editor.tabSize',\n },\n ],\n updates,\n warnings,\n );\n } else {\n warnings.push('VS Code language setting \"[rego]\" is customized and was left unchanged.');\n }\n\n return applyEditorUpdates(contents, updates, 'VS Code policy settings', warnings);\n}\n\n/**\n * Merge OPA extension recommendations without disturbing unknown entries.\n *\n * VS Code's `extensions.json` schema supports `unwantedRecommendations`, so\n * the syntax-only extension can be removed from recommendations and discouraged.\n *\n * @param contents - Existing `.vscode/extensions.json` JSONC\n * @returns Merged extension recommendations and warnings\n */\nexport function mergePolicyEditorExtensions(contents: string | null): PolicyEditorMergeResult {\n const parsed = parseEditorObject(contents, 'VS Code policy extension recommendations');\n if ('warning' in parsed) {\n return { contents: parsed.contents, warnings: [parsed.warning] };\n }\n const { current } = parsed;\n const updates: JsoncUpdate[] = [];\n const warnings: string[] = [];\n\n const recommendations = current.recommendations;\n if (\n recommendations === undefined ||\n (Array.isArray(recommendations) && recommendations.every((value) => typeof value === 'string'))\n ) {\n const existing = recommendations ?? [];\n const desired = mergeStringArray(existing, [POLICY_VSCODE_EXTENSION]).filter(\n (value) => value !== CONFLICTING_POLICY_VSCODE_EXTENSION,\n );\n if (!configurationValuesEqual(existing, desired)) {\n updates.push({ path: ['recommendations'], value: desired });\n }\n } else {\n warnings.push(\n 'VS Code extension recommendations use an unknown shape and were left unchanged.',\n );\n }\n\n const unwanted = current.unwantedRecommendations;\n if (\n unwanted === undefined ||\n (Array.isArray(unwanted) && unwanted.every((value) => typeof value === 'string'))\n ) {\n const existing = unwanted ?? [];\n const desired = mergeStringArray(existing, [CONFLICTING_POLICY_VSCODE_EXTENSION]);\n if (!configurationValuesEqual(existing, desired)) {\n updates.push({ path: ['unwantedRecommendations'], value: desired });\n }\n } else {\n warnings.push(\n 'VS Code unwanted extension recommendations use an unknown shape and were left unchanged.',\n );\n }\n\n return applyEditorUpdates(\n contents,\n updates,\n 'VS Code policy extension recommendations',\n warnings,\n );\n}\n\n/**\n * Build the generated target-scoped VS Code lint task.\n *\n * @param repositoryRoot - Root that owns `.vscode`\n * @param targetDirectory - Selected policy project directory\n * @returns VS Code task object\n */\nexport function buildPolicyLintTask(\n repositoryRoot: string,\n targetDirectory: string,\n): Record<string, unknown> {\n const target = relative(repositoryRoot, targetDirectory).split(sep).join('/') || '.';\n return {\n label: 'policy: lint',\n type: 'process',\n command: 'transcend',\n args: ['policy', 'lint', '--dir', target, '--noInteractive'],\n group: {\n kind: 'test',\n isDefault: true,\n },\n problemMatcher: [],\n };\n}\n\n/**\n * Merge the default policy lint task while preserving custom tasks.\n *\n * @param contents - Existing `.vscode/tasks.json` JSONC\n * @param repositoryRoot - Root that owns `.vscode`\n * @param targetDirectory - Selected policy project directory\n * @returns Merged task configuration and warnings\n */\nexport function mergePolicyEditorTasks(\n contents: string | null,\n repositoryRoot: string,\n targetDirectory: string,\n): PolicyEditorMergeResult {\n const parsed = parseEditorObject(contents, 'VS Code policy tasks');\n if ('warning' in parsed) {\n return { contents: parsed.contents, warnings: [parsed.warning] };\n }\n const { current } = parsed;\n const updates: JsoncUpdate[] = [];\n const warnings: string[] = [];\n const version = current.version;\n if (version === undefined) {\n updates.push({ path: ['version'], value: '2.0.0' });\n } else if (version !== '2.0.0') {\n warnings.push('VS Code task schema version is customized and was left unchanged.');\n }\n\n const desiredTask = buildPolicyLintTask(repositoryRoot, targetDirectory);\n const tasks = current.tasks;\n if (tasks === undefined) {\n updates.push({ path: ['tasks'], value: [desiredTask] });\n } else if (Array.isArray(tasks)) {\n const matchingTask = tasks.find(\n (task) =>\n task !== null &&\n typeof task === 'object' &&\n !Array.isArray(task) &&\n (task as Record<string, unknown>).label === 'policy: lint',\n );\n if (matchingTask === undefined) {\n updates.push({ path: ['tasks'], value: [...tasks, desiredTask] });\n } else if (!configurationValuesEqual(matchingTask, desiredTask)) {\n warnings.push(\n 'VS Code task \"policy: lint\" has repository-specific customization and was left unchanged.',\n );\n }\n } else {\n warnings.push('VS Code tasks use an unknown shape and were left unchanged.');\n }\n\n return applyEditorUpdates(contents, updates, 'VS Code policy tasks', warnings);\n}\n","import { isAbsolute, join, posix, relative, sep } from 'node:path';\n\nimport {\n getManagedAgentSkillCandidatePaths,\n planManagedAgentSkill,\n type ManagedAgentSkillDefinition,\n} from '../scaffolding/agent-skill.js';\nimport { displayProjectPath, quoteShellArgument } from '../scaffolding/project-plan-output.js';\nimport {\n getPlanningPathSnapshot,\n getPlanningFileSnapshot,\n planFileChange,\n type PlanningPathSnapshot,\n} from '../scaffolding/project-plan.js';\nimport { getPolicyManifestPath } from './policy-project-discovery.js';\nimport {\n generatePolicyGithubActionsWorkflow,\n POLICY_CI_WORKFLOW_PATH,\n} from './policy-scaffold-artifacts.js';\nimport {\n mergePolicyEditorExtensions,\n mergePolicyEditorSettings,\n mergePolicyEditorTasks,\n type PolicyEditorMergeResult,\n} from './policy-scaffold-config.js';\nimport {\n POLICY_INIT_RESULT_VERSION,\n PolicySetupFeature,\n type PolicyInitProjectPlan,\n type PolicyProjectState,\n type PolicySetupFeature as PolicySetupFeatureType,\n} from './policy-scaffold-model.js';\nimport { generatePolicyStarterFiles, type PolicyStarterFile } from './policy-scaffold-templates.js';\nimport { POLICY_SKILL_FILES, POLICY_SKILL_NAME } from './policy-skill.js';\n\n/** Managed Policy Engine Agent Skill definition. */\nconst POLICY_MANAGED_SKILL: ManagedAgentSkillDefinition = {\n name: POLICY_SKILL_NAME,\n displayName: 'Policy Engine',\n owner: '@transcend-io/cli',\n files: POLICY_SKILL_FILES,\n};\n\n/** In-memory input consumed by the pure policy initializer. */\nexport interface PolicyInitPlanningInput {\n /** Project discovery state. */\n state: PolicyProjectState;\n /** Potential mutation paths keyed by absolute path. */\n snapshots: Readonly<Record<string, PlanningPathSnapshot>>;\n}\n\n/** Optional repository setup selected for policy initialization. */\nexport interface PolicyInitPlanOptions {\n /** Selected setup features. */\n features: readonly PolicySetupFeatureType[];\n /** Exact released Transcend CLI version for generated CI. */\n cliVersion: string;\n}\n\n/**\n * Build the copyable policy lint command for one target.\n *\n * @param state - Discovered project state\n * @returns Raw one-line command\n */\nexport function buildPolicyLintCommand(state: PolicyProjectState): string {\n const directory = displayProjectPath(state.invocationDirectory, state.targetDirectory);\n return `transcend policy lint --dir ${quoteShellArgument(directory)} --noInteractive`;\n}\n\n/**\n * Enumerate all core starter paths that could be created.\n *\n * @param state - Policy project state\n * @param options - Selected repository setup\n * @returns Absolute candidate paths\n */\nexport function getPolicyInitPlanningCandidatePaths(\n state: PolicyProjectState,\n options: Pick<PolicyInitPlanOptions, 'features'>,\n): string[] {\n const paths = new Set(\n generatePolicyStarterFiles().map(({ path }) => join(state.targetDirectory, path)),\n );\n const selected = new Set(options.features);\n if (selected.has(PolicySetupFeature.Editor)) {\n paths.add(join(state.projectRoot, '.vscode', 'settings.json'));\n paths.add(join(state.projectRoot, '.vscode', 'extensions.json'));\n paths.add(join(state.projectRoot, '.vscode', 'tasks.json'));\n }\n if (selected.has(PolicySetupFeature.Skill)) {\n getManagedAgentSkillCandidatePaths(\n state.projectRoot,\n state.existingSkillDirectories,\n POLICY_MANAGED_SKILL,\n ).forEach((path) => paths.add(path));\n }\n if (selected.has(PolicySetupFeature.Ci) && state.repositoryRoot && state.usesGithub) {\n paths.add(join(state.repositoryRoot, POLICY_CI_WORKFLOW_PATH));\n }\n return [...paths].sort((left, right) => left.localeCompare(right));\n}\n\n/**\n * Ensure a destination stays below an approved project root.\n *\n * @param root - Approved root\n * @param path - Candidate path\n */\nfunction assertContained(root: string, path: string): void {\n const child = relative(root, path);\n if (child === '..' || child.startsWith(`..${sep}`) || isAbsolute(child)) {\n throw new Error(`Refusing to modify path outside project root: ${path}`);\n }\n}\n\n/**\n * Enumerate generated file and directory paths allowed in an exact starter.\n *\n * @param files - Starter files\n * @returns POSIX relative paths\n */\nfunction starterRelativePaths(files: readonly PolicyStarterFile[]): Set<string> {\n const paths = new Set<string>(['input.json']);\n files.forEach(({ path }) => {\n paths.add(path);\n let parent = posix.dirname(path);\n while (parent !== '.') {\n paths.add(parent);\n parent = posix.dirname(parent);\n }\n });\n return paths;\n}\n\n/**\n * Add or classify one regular-file mutation.\n *\n * @param plan - Policy plan being assembled\n * @param input - Collected snapshots\n * @param options - Desired file\n */\nfunction addFileChange(\n plan: PolicyInitProjectPlan,\n input: PolicyInitPlanningInput,\n options: {\n /** Absolute destination path. */\n path: string;\n /** Complete desired contents. */\n contents: string;\n /** Human-readable plan description. */\n description: string;\n /** Refuse existing contents. */\n createOnly?: boolean;\n },\n): void {\n const change = planFileChange({\n snapshot: getPlanningFileSnapshot(input.snapshots, options.path),\n after: options.contents,\n description: options.description,\n ...(options.createOnly === undefined ? {} : { createOnly: options.createOnly }),\n });\n if (change) {\n plan.changes.push(change);\n } else {\n plan.unchanged.push(options.path);\n }\n}\n\n/**\n * Add one safe editor merge and its preservation warnings.\n *\n * @param plan - Policy plan being assembled\n * @param input - Collected snapshots\n * @param path - Absolute editor artifact path\n * @param result - Pure JSONC merge result\n * @param description - Human-readable plan description\n * @param cwd - Invocation directory for portable warning paths\n */\nfunction addEditorMerge(\n plan: PolicyInitProjectPlan,\n input: PolicyInitPlanningInput,\n path: string,\n result: PolicyEditorMergeResult,\n description: string,\n cwd: string,\n): void {\n addFileChange(plan, input, {\n path,\n contents: result.contents,\n description,\n });\n plan.warnings.push(\n ...result.warnings.map((warning) => `${warning} (${displayProjectPath(cwd, path)})`),\n );\n}\n\n/**\n * Build a safe policy project plan without reading the filesystem.\n *\n * Empty targets receive the complete starter. Existing targets are classified\n * only; no domain file is added, merged, or overwritten.\n *\n * @param input - Collected project state and path snapshots\n * @param options - Selected setup and pinned CLI version\n * @returns Validated policy initialization plan\n */\nexport function buildPolicyInitPlan(\n input: PolicyInitPlanningInput,\n options: PolicyInitPlanOptions,\n): PolicyInitProjectPlan {\n const { state } = input;\n const files = generatePolicyStarterFiles();\n const manifestPath = getPolicyManifestPath(state);\n const lintCommand = buildPolicyLintCommand(state);\n const resultPath = join(state.targetDirectory, 'policy_engine', 'example', 'result.rego');\n const plan: PolicyInitProjectPlan = {\n version: POLICY_INIT_RESULT_VERSION,\n command: 'init',\n rootDirectory: state.projectRoot,\n targetDirectory: state.targetDirectory,\n manifestPath,\n changes: [],\n unchanged: [],\n warnings: [],\n nextSteps: [lintCommand],\n features: [...options.features],\n };\n\n const candidatePaths = getPolicyInitPlanningCandidatePaths(state, options);\n assertContained(state.projectRoot, state.targetDirectory);\n candidatePaths.forEach((path) => assertContained(state.projectRoot, path));\n\n let hasDisposableExample = false;\n if (state.relativeFilePaths.length === 0) {\n hasDisposableExample = true;\n plan.directoryPreconditions = [\n {\n path: state.targetDirectory,\n relativePaths: [...state.relativePaths],\n },\n ];\n files.forEach((file) => {\n const path = join(state.targetDirectory, file.path);\n const snapshot = getPlanningPathSnapshot(input.snapshots, path);\n if (snapshot.kind !== 'absent') {\n throw new Error(`Expected an empty policy target, but found an entry at: ${path}`);\n }\n addFileChange(plan, input, {\n path,\n contents: file.contents,\n description: file.description,\n createOnly: true,\n });\n });\n } else {\n let allStarterFilesMatch = true;\n files.forEach((file) => {\n const path = join(state.targetDirectory, file.path);\n const snapshot = getPlanningPathSnapshot(input.snapshots, path);\n if (snapshot.kind === 'file' && snapshot.contents === file.contents) {\n plan.unchanged.push(path);\n return;\n }\n allStarterFilesMatch = false;\n if (snapshot.kind !== 'absent') {\n plan.unchanged.push(path);\n plan.warnings.push(\n `Existing policy scaffold path was left unchanged: ${displayProjectPath(\n state.invocationDirectory,\n path,\n )}`,\n );\n }\n });\n hasDisposableExample = allStarterFilesMatch;\n\n const allowedPaths = starterRelativePaths(files);\n const hasCustomPaths = state.relativeFilePaths.some((path) => !allowedPaths.has(path));\n if (!allStarterFilesMatch || hasCustomPaths) {\n plan.warnings.push(\n `Existing policy target contains custom or partial content, so no starter files were added or overwritten. ` +\n `Review ${displayProjectPath(\n state.invocationDirectory,\n state.targetDirectory,\n )} manually, then run \\`${lintCommand}\\`.`,\n );\n }\n }\n if (hasDisposableExample) {\n plan.disposableExamplePath = resultPath;\n plan.nextSteps.push(\n `Edit ${quoteShellArgument(displayProjectPath(state.invocationDirectory, resultPath))}`,\n );\n }\n\n const selected = new Set(options.features);\n const root = state.projectRoot;\n if (selected.has(PolicySetupFeature.Editor)) {\n const settingsPath = join(root, '.vscode', 'settings.json');\n const extensionsPath = join(root, '.vscode', 'extensions.json');\n const tasksPath = join(root, '.vscode', 'tasks.json');\n const editorArtifacts = [\n {\n path: settingsPath,\n description: 'Merge strict target-scoped OPA and Rego editor settings',\n merge: mergePolicyEditorSettings,\n },\n {\n path: extensionsPath,\n description: 'Recommend the OPA extension and discourage its syntax-only conflict',\n merge: (\n contents: string | null,\n _repositoryRoot: string,\n _targetDirectory: string,\n ): PolicyEditorMergeResult => mergePolicyEditorExtensions(contents),\n },\n {\n path: tasksPath,\n description: 'Add the default target-scoped policy lint task',\n merge: mergePolicyEditorTasks,\n },\n ];\n editorArtifacts.forEach(({ path, description, merge }) => {\n const snapshot = getPlanningPathSnapshot(input.snapshots, path);\n if (snapshot.kind !== 'absent' && snapshot.kind !== 'file') {\n plan.unchanged.push(path);\n plan.warnings.push(\n `Existing VS Code artifact is not a regular file and was left unchanged: ${displayProjectPath(\n state.invocationDirectory,\n path,\n )}`,\n );\n return;\n }\n addEditorMerge(\n plan,\n input,\n path,\n merge(snapshot.kind === 'file' ? snapshot.contents : null, root, state.targetDirectory),\n description,\n state.invocationDirectory,\n );\n });\n }\n\n if (selected.has(PolicySetupFeature.Skill)) {\n const skillPlan = planManagedAgentSkill({\n rootDirectory: root,\n existingDirectories: state.existingSkillDirectories,\n snapshots: input.snapshots,\n skill: POLICY_MANAGED_SKILL,\n preserveModified: true,\n });\n plan.changes.push(...skillPlan.changes);\n plan.unchanged.push(...skillPlan.unchanged);\n plan.warnings.push(\n ...skillPlan.warnings.map((warning) => {\n return skillPlan.unchanged.reduce(\n (rendered, path) =>\n rendered.replace(path, displayProjectPath(state.invocationDirectory, path)),\n warning,\n );\n }),\n );\n }\n\n if (selected.has(PolicySetupFeature.Ci)) {\n if (!state.repositoryRoot || !state.usesGithub) {\n plan.warnings.push(\n 'GitHub Actions setup was selected, but this target is not inside a detected GitHub repository.',\n );\n } else {\n const workflowPath = join(state.repositoryRoot, POLICY_CI_WORKFLOW_PATH);\n const target =\n relative(state.repositoryRoot, state.targetDirectory).split(sep).join('/') || '.';\n const workflowContents = generatePolicyGithubActionsWorkflow({\n cliVersion: options.cliVersion,\n targetDirectory: target,\n });\n const workflowSnapshot = getPlanningPathSnapshot(input.snapshots, workflowPath);\n if (workflowSnapshot.kind === 'absent') {\n addFileChange(plan, input, {\n path: workflowPath,\n contents: workflowContents,\n description: 'Add credential-free Policy Engine validation',\n createOnly: true,\n });\n } else if (\n workflowSnapshot.kind === 'file' &&\n workflowSnapshot.contents === workflowContents\n ) {\n plan.unchanged.push(workflowPath);\n } else {\n plan.unchanged.push(workflowPath);\n plan.warnings.push(\n `Existing GitHub Actions workflow was left unchanged: ${displayProjectPath(\n state.invocationDirectory,\n workflowPath,\n )}. Adapt it manually to run \\`${lintCommand}\\`.`,\n );\n }\n }\n }\n\n plan.changes.forEach(({ path }) => assertContained(state.projectRoot, path));\n return plan;\n}\n","import colors from 'colors';\n\nimport { version as CLI_VERSION } from '../../../constants.js';\nimport type { LocalContext } from '../../../context.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport {\n runCapturedProcess,\n type CapturedProcessResult,\n type CapturedProcessRunner,\n} from '../../../lib/cli/run-captured-process.js';\nimport {\n DEFAULT_POLICY_PROJECT_DIRECTORY,\n discoverPolicyProject,\n} from '../../../lib/policy/policy-project-discovery.js';\nimport {\n OPA_INSTALL_URL,\n OPA_MISSING_MESSAGE,\n parsePolicyToolVersion,\n MINIMUM_POLICY_STARTER_REGAL_VERSION,\n REGAL_INSTALL_URL,\n REGAL_MISSING_MESSAGE,\n unsupportedOpaVersionMessage,\n unsupportedRegalVersionMessage,\n} from '../../../lib/policy/policy-runtime.js';\nimport {\n PolicySetupFeature,\n type PolicySetupFeature as PolicySetupFeatureType,\n} from '../../../lib/policy/policy-scaffold-model.js';\nimport {\n buildPolicyInitAiHandoff,\n buildPolicyInitPlanResult,\n type PolicyInitToolVersions,\n} from '../../../lib/policy/policy-scaffold-output.js';\nimport {\n buildPolicyInitPlan,\n getPolicyInitPlanningCandidatePaths,\n} from '../../../lib/policy/policy-scaffold-planning.js';\nimport { collectPlanningSnapshots } from '../../../lib/scaffolding/project-discovery.js';\nimport { applyProjectPlan } from '../../../lib/scaffolding/project-plan-apply.js';\nimport {\n displayProjectPath,\n quoteShellArgument,\n renderProjectPlan,\n} from '../../../lib/scaffolding/project-plan-output.js';\nimport {\n PromptCancelledError,\n type PromptChoice,\n ScaffoldPrompts,\n} from '../../../lib/scaffolding/prompts.js';\n\n/** Flags for `transcend policy init`. */\nexport interface PolicyInitFlags {\n /** Install repository-level VS Code setup. */\n editor?: boolean;\n /** Install the Policy Engine Agent Skill. */\n skill?: boolean;\n /** Install validation-only GitHub Actions CI. */\n ci?: boolean;\n /** Disable prompts. */\n noInteractive: boolean;\n /** Render but do not apply the plan. */\n dryRun: boolean;\n /** Approve the final displayed plan. */\n yes: boolean;\n /** Emit one stable JSON result on stdout. */\n json: boolean;\n}\n\n/** User-facing optional setup labels. */\nconst SETUP_LABELS: Readonly<Record<PolicySetupFeatureType, string>> = {\n [PolicySetupFeature.Editor]: 'VS Code settings and lint task',\n [PolicySetupFeature.Skill]: 'Policy Engine Agent Skill',\n [PolicySetupFeature.Ci]: 'Validation-only GitHub Actions',\n};\n\n/** All optional setup features in stable prompt order. */\nconst ALL_SETUP_FEATURES = Object.values(PolicySetupFeature);\n\n/** Runtime compatibility detected before policy planning. */\ninterface PolicyRuntimeProbe {\n /** Compatible tool versions. */\n tools: PolicyInitToolVersions;\n /** Missing or incompatible runtime guidance. */\n warnings: string[];\n}\n\n/**\n * Whether this invocation can ask questions.\n *\n * @param flags - Interaction flags\n * @param stdinIsTTY - Whether standard input is interactive\n * @param stderrIsTTY - Whether prompt output is interactive\n * @returns Whether prompts are enabled\n */\nfunction isInteractiveInvocation(\n flags: Pick<PolicyInitFlags, 'json' | 'noInteractive'>,\n stdinIsTTY: boolean | undefined,\n stderrIsTTY: boolean | undefined,\n): boolean {\n return !flags.json && !flags.noInteractive && Boolean(stdinIsTTY && stderrIsTTY);\n}\n\n/**\n * Resolve setup from explicit flags or one default-selected checklist.\n *\n * @param prompts - Prompt adapters\n * @param flags - Setup flags\n * @param options - Interaction state\n * @returns Explicitly selected setup features\n */\nasync function resolveFeatures(\n prompts: ScaffoldPrompts,\n flags: PolicyInitFlags,\n options: {\n /** Whether prompts are available. */\n interactive: boolean;\n },\n): Promise<PolicySetupFeatureType[]> {\n const enabled: Readonly<Record<PolicySetupFeatureType, boolean | undefined>> = {\n [PolicySetupFeature.Editor]: flags.editor,\n [PolicySetupFeature.Skill]: flags.skill,\n [PolicySetupFeature.Ci]: flags.ci,\n };\n if (!options.interactive) {\n return ALL_SETUP_FEATURES.filter((feature) => enabled[feature] === true);\n }\n const choices: PromptChoice<PolicySetupFeatureType>[] = ALL_SETUP_FEATURES.map((feature) => ({\n name: SETUP_LABELS[feature],\n value: feature,\n checked: enabled[feature] !== false,\n }));\n return prompts.checkbox('Choose repository setup:', choices);\n}\n\n/**\n * Explain a failed version subprocess with official installation guidance.\n *\n * @param tool - Policy tool name\n * @param result - Failed captured process\n * @returns Actionable warning\n */\nfunction failedVersionProbeMessage(tool: 'OPA' | 'Regal', result: CapturedProcessResult): string {\n const detail = [result.stdout.trim(), result.stderr.trim()].filter(Boolean).join('\\n');\n const url = tool === 'OPA' ? OPA_INSTALL_URL : REGAL_INSTALL_URL;\n const requirement =\n tool === 'OPA' ? 'OPA 1.x' : `Regal ${MINIMUM_POLICY_STARTER_REGAL_VERSION} or newer`;\n return (\n `${requirement} is required, but \\`${tool.toLowerCase()} version\\` exited with code ` +\n `${result.code}${detail ? `: ${detail}` : '.'} ` +\n `Install or upgrade it using the official instructions: ${url}`\n );\n}\n\n/**\n * Probe both local policy runtimes without installing or modifying them.\n *\n * @param context - CLI context\n * @param cwd - Invocation working directory\n * @param runner - Captured subprocess runner\n * @returns Compatible versions and exact runtime guidance\n */\nasync function probePolicyRuntimes(\n context: LocalContext,\n cwd: string,\n runner: CapturedProcessRunner,\n): Promise<PolicyRuntimeProbe> {\n const tools: PolicyInitToolVersions = { opa: null, regal: null };\n const warnings: string[] = [];\n\n const opaResult = await runner('opa', ['version'], { cwd }, context);\n if (opaResult.error?.code === 'ENOENT') {\n warnings.push(OPA_MISSING_MESSAGE);\n } else {\n const output = `${opaResult.stdout}\\n${opaResult.stderr}`;\n const unsupported = unsupportedOpaVersionMessage(output);\n if (opaResult.code !== 0) {\n warnings.push(unsupported ?? failedVersionProbeMessage('OPA', opaResult));\n } else if (unsupported) {\n warnings.push(unsupported);\n } else {\n tools.opa = parsePolicyToolVersion(output)!.version;\n }\n }\n\n const regalResult = await runner('regal', ['version'], { cwd }, context);\n if (regalResult.error?.code === 'ENOENT') {\n warnings.push(REGAL_MISSING_MESSAGE);\n } else {\n const output = `${regalResult.stdout}\\n${regalResult.stderr}`;\n const unsupported = unsupportedRegalVersionMessage(\n output,\n MINIMUM_POLICY_STARTER_REGAL_VERSION,\n 'the generated OPA 1.13.1 capabilities configuration',\n );\n if (regalResult.code !== 0) {\n warnings.push(unsupported ?? failedVersionProbeMessage('Regal', regalResult));\n } else if (unsupported) {\n warnings.push(unsupported);\n } else {\n tools.regal = parsePolicyToolVersion(output)!.version;\n }\n }\n\n return { tools, warnings };\n}\n\n/**\n * Initialize a credential-free local Policy Engine project.\n *\n * @param this - CLI context\n * @param flags - Scaffold and interaction flags\n * @param directory - Target policy directory\n * @param runner - Captured policy tool runner\n */\nexport async function init(\n this: LocalContext,\n flags: PolicyInitFlags,\n directory: string = DEFAULT_POLICY_PROJECT_DIRECTORY,\n runner: CapturedProcessRunner = runCapturedProcess,\n): Promise<void> {\n doneInputValidation(this.process);\n try {\n const runtime = await probePolicyRuntimes(this, this.process.cwd(), runner);\n const state = discoverPolicyProject(this, directory);\n const prompts = new ScaffoldPrompts(this);\n const interactive = isInteractiveInvocation(\n flags,\n this.process.stdin.isTTY,\n this.process.stderr.isTTY,\n );\n const features = await resolveFeatures(prompts, flags, { interactive });\n const candidatePaths = getPolicyInitPlanningCandidatePaths(state, { features });\n const snapshots = collectPlanningSnapshots(this, state.projectRoot, candidatePaths);\n\n const plan = buildPolicyInitPlan(\n { state, snapshots },\n {\n features,\n cliVersion: CLI_VERSION,\n },\n );\n plan.warnings.push(...runtime.warnings);\n\n if (!flags.json) {\n this.logger.info(\n renderProjectPlan(plan, {\n cwd: this.process.cwd(),\n title: 'Policy initialization plan',\n details: [\n { label: 'Target', path: plan.targetDirectory },\n { label: 'Manifest', path: plan.manifestPath },\n ],\n }),\n );\n }\n\n let approved = plan.changes.length === 0 || flags.dryRun;\n if (plan.changes.length > 0 && !flags.dryRun) {\n if (flags.yes) {\n approved = true;\n } else if (interactive) {\n approved = await prompts.confirm('Apply this complete plan?', true);\n } else {\n throw new Error(\n 'The plan requires approval in a non-interactive invocation. Review with --dryRun, then pass --yes.',\n );\n }\n }\n\n if (approved && !flags.dryRun && plan.changes.length > 0) {\n await applyProjectPlan(this, plan);\n }\n const applied = approved && !flags.dryRun && plan.changes.length > 0;\n const setupAvailable = approved && !flags.dryRun;\n const aiHandoff = buildPolicyInitAiHandoff({\n projectPath: quoteShellArgument(\n displayProjectPath(this.process.cwd(), state.targetDirectory),\n ),\n ...(plan.disposableExamplePath\n ? {\n examplePath: quoteShellArgument(\n displayProjectPath(this.process.cwd(), plan.disposableExamplePath),\n ),\n }\n : {}),\n hasSkill: setupAvailable && features.includes(PolicySetupFeature.Skill),\n lintCommand: plan.nextSteps[0]!,\n });\n const result = buildPolicyInitPlanResult(plan, {\n applied,\n dryRun: flags.dryRun,\n cwd: this.process.cwd(),\n aiHandoff,\n tools: runtime.tools,\n });\n if (flags.json) {\n this.process.stdout.write(`${JSON.stringify(result)}\\n`);\n return;\n }\n if (flags.dryRun) {\n this.logger.info(colors.yellow('Dry run complete. No changes were written.'));\n return;\n }\n if (!approved) {\n this.logger.info(colors.yellow('No changes applied.'));\n return;\n }\n if (plan.changes.length === 0) {\n const message =\n plan.warnings.length === runtime.warnings.length\n ? 'Policy project is already initialized.'\n : 'Existing policy project was left unchanged.';\n this.logger.info(colors.green(message));\n } else {\n this.logger.info(colors.green('Policy project initialized.'));\n }\n if (plan.nextSteps.length > 0) {\n this.logger.info(`\\n${colors.bold('Next steps')}`);\n plan.nextSteps.forEach((step) => this.logger.info(step));\n }\n this.logger.info(`\\n${colors.bold('AI handoff — paste into your coding agent')}`);\n this.logger.info(aiHandoff);\n } catch (error) {\n if (error instanceof PromptCancelledError) {\n return this.process.exit(130);\n }\n throw error;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"impl-Dn_PyB5_2.mjs","names":["POLICY_SKILL_MD","POLICY_SETUP_TOOLING_REFERENCE_MD","POLICY_AUTHORING_REFERENCE_MD","POLICY_TESTING_DEBUGGING_REFERENCE_MD","POLICY_PUBLISHING_REFERENCE_MD","CLI_VERSION"],"sources":["../src/lib/policy/policy-project-discovery.ts","../src/lib/policy/policy-scaffold-model.ts","../../../skills/transcend-policy-engine/references/authoring.md","../../../skills/transcend-policy-engine/references/publishing.md","../../../skills/transcend-policy-engine/references/setup-tooling.md","../../../skills/transcend-policy-engine/references/testing-debugging.md","../../../skills/transcend-policy-engine/SKILL.md","../src/lib/policy/policy-skill.ts","../src/lib/policy/policy-scaffold-output.ts","../src/lib/policy/policy-scaffold-templates.ts","../src/lib/policy/policy-scaffold-artifacts.ts","../src/lib/policy/policy-scaffold-config.ts","../src/lib/policy/policy-scaffold-planning.ts","../src/commands/policy/init/impl.ts"],"sourcesContent":["import { join, resolve } from 'node:path';\n\nimport type { LocalContext } from '../../context.js';\nimport {\n collectProjectRelativePaths,\n discoverProjectRepository,\n} from '../scaffolding/project-discovery.js';\nimport type { PolicyProjectState } from './policy-scaffold-model.js';\n\n/** Default local policy project directory. */\nexport const DEFAULT_POLICY_PROJECT_DIRECTORY = 'transcend/policy';\n\n/**\n * Collect repository state required by the pure policy planner.\n *\n * @param context - CLI context\n * @param directory - User-selected target directory\n * @returns Policy project discovery state\n */\nexport function discoverPolicyProject(\n context: LocalContext,\n directory: string = DEFAULT_POLICY_PROJECT_DIRECTORY,\n): PolicyProjectState {\n const invocationDirectory = context.process.cwd();\n const targetDirectory = resolve(invocationDirectory, directory);\n if (\n context.fs.existsSync(targetDirectory) &&\n !context.fs.statSync(targetDirectory).isDirectory()\n ) {\n throw new Error(`Policy target is not a directory: ${targetDirectory}`);\n }\n const repository = discoverProjectRepository(context, {\n invocationDirectory,\n targetDirectory,\n standaloneProjectRoot: invocationDirectory,\n });\n return {\n invocationDirectory,\n targetDirectory,\n ...repository,\n relativePaths: collectProjectRelativePaths(context, targetDirectory),\n relativeFilePaths: collectProjectRelativePaths(context, targetDirectory, {\n includeDirectories: false,\n }),\n };\n}\n\n/**\n * Resolve the bundle manifest path for a discovered project.\n *\n * @param state - Policy project state\n * @returns Absolute manifest path\n */\nexport function getPolicyManifestPath(state: PolicyProjectState): string {\n return join(state.targetDirectory, 'manifest.json');\n}\n","import type { ExistingProjectSkillDirectory } from '../scaffolding/agent-skill.js';\nimport type { ProjectPlan } from '../scaffolding/project-plan.js';\n\n/** Version of the stable policy initialization JSON result. */\nexport const POLICY_INIT_RESULT_VERSION = 1 as const;\n\n/** Optional repository integrations for policy authoring. */\nexport const PolicySetupFeature = {\n /** Repository-level editor configuration. */\n Editor: 'editor',\n /** Managed policy authoring skill. */\n Skill: 'skill',\n /** Credential-free continuous integration. */\n Ci: 'ci',\n} as const;\n\n/** Optional repository integration for policy authoring. */\nexport type PolicySetupFeature = (typeof PolicySetupFeature)[keyof typeof PolicySetupFeature];\n\n/** Repository and target state collected before policy planning. */\nexport interface PolicyProjectState {\n /** Directory from which the CLI was invoked. */\n invocationDirectory: string;\n /** Absolute user-selected policy directory. */\n targetDirectory: string;\n /** Repository or invocation root that owns setup artifacts. */\n projectRoot: string;\n /** Nearest repository root, when present. */\n repositoryRoot?: string;\n /** Existing project-level skill directories. */\n existingSkillDirectories: ExistingProjectSkillDirectory[];\n /** Whether the repository appears to use GitHub. */\n usesGithub: boolean;\n /** Case-preserving relative paths below the policy directory. */\n relativePaths: string[];\n /** Relative file and link paths below the policy directory. */\n relativeFilePaths: string[];\n}\n\n/** A complete, validated policy initialization plan. */\nexport interface PolicyInitProjectPlan extends ProjectPlan {\n /** JSON contract version. */\n version: typeof POLICY_INIT_RESULT_VERSION;\n /** Command that produced the plan. */\n command: 'init';\n /** Absolute policy project directory. */\n targetDirectory: string;\n /** Absolute policy manifest path. */\n manifestPath: string;\n /** Files inspected and deliberately left unchanged. */\n unchanged: string[];\n /** Non-fatal plan warnings. */\n warnings: string[];\n /** Raw commands shown after a successful apply. */\n nextSteps: string[];\n /** Exact generated example that remains safe to replace. */\n disposableExamplePath?: string;\n /** Selected repository integrations. */\n features: PolicySetupFeature[];\n}\n",null,null,null,null,null,"import POLICY_AUTHORING_REFERENCE_MD from '../../../../../skills/transcend-policy-engine/references/authoring.md';\nimport POLICY_PUBLISHING_REFERENCE_MD from '../../../../../skills/transcend-policy-engine/references/publishing.md';\nimport POLICY_SETUP_TOOLING_REFERENCE_MD from '../../../../../skills/transcend-policy-engine/references/setup-tooling.md';\nimport POLICY_TESTING_DEBUGGING_REFERENCE_MD from '../../../../../skills/transcend-policy-engine/references/testing-debugging.md';\nimport POLICY_SKILL_MD from '../../../../../skills/transcend-policy-engine/SKILL.md';\nimport type { AgentSkillFile } from '../scaffolding/agent-skill.js';\n\n/** Namespaced directory and frontmatter name for the installed Agent Skill. */\nexport const POLICY_SKILL_NAME = 'transcend-policy-engine';\n\nexport {\n POLICY_AUTHORING_REFERENCE_MD,\n POLICY_PUBLISHING_REFERENCE_MD,\n POLICY_SETUP_TOOLING_REFERENCE_MD,\n POLICY_SKILL_MD,\n POLICY_TESTING_DEBUGGING_REFERENCE_MD,\n};\n\n/** Complete portable Policy Engine Agent Skill file set. */\nexport const POLICY_SKILL_FILES: readonly AgentSkillFile[] = [\n { path: 'SKILL.md', contents: POLICY_SKILL_MD },\n { path: 'references/setup-tooling.md', contents: POLICY_SETUP_TOOLING_REFERENCE_MD },\n { path: 'references/authoring.md', contents: POLICY_AUTHORING_REFERENCE_MD },\n { path: 'references/testing-debugging.md', contents: POLICY_TESTING_DEBUGGING_REFERENCE_MD },\n { path: 'references/publishing.md', contents: POLICY_PUBLISHING_REFERENCE_MD },\n];\n","import {\n toPublicPlannedChange,\n type PublicPlannedChange,\n} from '../scaffolding/project-plan-output.js';\nimport type { PolicyInitProjectPlan, PolicySetupFeature } from './policy-scaffold-model.js';\nimport { POLICY_SKILL_NAME } from './policy-skill.js';\n\n/** Detected local policy tool versions. */\nexport interface PolicyInitToolVersions {\n /** OPA version, or null when missing or incompatible. */\n opa: string | null;\n /** Regal version, or null when missing or incompatible. */\n regal: string | null;\n}\n\n/** Stable machine-readable policy initialization result. */\nexport interface PolicyInitPlanResult {\n /** JSON contract version. */\n version: number;\n /** Command that produced the result. */\n command: 'init';\n /** Whether the plan was applied. */\n applied: boolean;\n /** Whether this was a dry run. */\n dryRun: boolean;\n /** Absolute policy target directory. */\n targetDirectory: string;\n /** Absolute policy manifest path. */\n manifestPath: string;\n /** Planned mutations without file contents. */\n changes: PublicPlannedChange[];\n /** Non-fatal preservation and runtime warnings. */\n warnings: string[];\n /** Suggested raw one-line follow-up commands. */\n nextSteps: string[];\n /** Explicitly selected repository integrations. */\n features: PolicySetupFeature[];\n /** Compact prompt for continuing with a coding agent. */\n aiHandoff: string;\n /** Compatible local policy tool versions. */\n tools: PolicyInitToolVersions;\n}\n\n/**\n * Build the compact policy implementation and CI handoff.\n *\n * @param options - Portable example path and lint command\n * @returns Raw one-line prompt\n */\nexport function buildPolicyInitAiHandoff(options: {\n /** Display path to the policy project. */\n projectPath: string;\n /** Display path to an exact disposable example. */\n examplePath?: string;\n /** Whether the policy authoring skill was installed. */\n hasSkill: boolean;\n /** Copyable lint command. */\n lintCommand: string;\n}): string {\n if (!options.examplePath) {\n const instruction = options.hasSkill\n ? `Use the \\`${POLICY_SKILL_NAME}\\` skill to review`\n : 'Review';\n return (\n `${instruction} the existing policy project in ${options.projectPath}, ` +\n `align its document tree and input/output contract with the intended application, adapt ` +\n `repository validation as needed, and rerun ${options.lintCommand}.`\n );\n }\n const instruction = options.hasSkill\n ? `Use the \\`${POLICY_SKILL_NAME}\\` skill to replace`\n : 'Replace';\n return (\n `${instruction} the disposable example in ${options.examplePath} with ` +\n `the intended policy document tree and input/output contract, adapt repository validation ` +\n `to local conventions, and rerun ${options.lintCommand}.`\n );\n}\n\n/**\n * Build the stable machine-readable initialization result.\n *\n * @param plan - Policy project plan\n * @param options - Apply and runtime state\n * @returns Public JSON result\n */\nexport function buildPolicyInitPlanResult(\n plan: PolicyInitProjectPlan,\n options: {\n /** Whether the plan was applied. */\n applied: boolean;\n /** Whether this was a dry run. */\n dryRun: boolean;\n /** Working directory for portable paths. */\n cwd: string;\n /** Compact coding-agent prompt. */\n aiHandoff: string;\n /** Compatible local policy tool versions. */\n tools: PolicyInitToolVersions;\n },\n): PolicyInitPlanResult {\n return {\n version: plan.version,\n command: plan.command,\n applied: options.applied,\n dryRun: options.dryRun,\n targetDirectory: plan.targetDirectory,\n manifestPath: plan.manifestPath,\n changes: plan.changes.map((change) => toPublicPlannedChange(options.cwd, change)),\n warnings: plan.warnings,\n nextSteps: plan.nextSteps,\n features: [...plan.features],\n aiHandoff: options.aiHandoff,\n tools: options.tools,\n };\n}\n","/** OPA version targeted by generated policy authoring configuration. */\nexport const POLICY_STARTER_OPA_VERSION = '1.13.1';\n\n/** One deterministic file in the safe policy starter. */\nexport interface PolicyStarterFile {\n /** POSIX-style path relative to the policy directory. */\n path: string;\n /** Complete UTF-8 file contents. */\n contents: string;\n /** Human-readable reason shown in the plan. */\n description: string;\n}\n\n/** Publishable Policy Engine bundle manifest. */\nexport const POLICY_MANIFEST_TEMPLATE = `{\n \"roots\": [\"policy_engine\"]\n}\n`;\n\n/** Strict Regal project configuration pinned to the deployed OPA capabilities. */\nexport const POLICY_REGAL_CONFIG_TEMPLATE = `capabilities:\n from:\n engine: opa\n version: v${POLICY_STARTER_OPA_VERSION}\nproject:\n roots:\n - .\n rego-version: 1\n`;\n\n/** Disposable, fail-closed example policy. */\nexport const POLICY_RESULT_REGO_TEMPLATE = `package policy_engine.example\n\nimport rego.v1\n\n# METADATA\n# title: Disposable example result\n# description: |\n# A fail-closed teaching entrypoint. Replace this example with the document\n# tree and result contract required by your application.\n# entrypoint: true\ndefault result := {\n\t\"decision\": \"deny\",\n\t\"reason_code\": \"untrusted_or_invalid_input\",\n}\n\nresult := {\n\t\"decision\": \"allow\",\n\t\"reason_code\": \"trusted_subject\",\n} if {\n\tinput.subject.trusted == true\n}\n`;\n\n/** Executable tests adjacent to the disposable example policy. */\nexport const POLICY_RESULT_TEST_REGO_TEMPLATE = `package policy_engine.example_test\n\nimport data.policy_engine.example\nimport rego.v1\n\ntest_denies_untrusted_subject if {\n\tresult := example.result with input as {\"subject\": {\"trusted\": false}}\n\tresult == {\n\t\t\"decision\": \"deny\",\n\t\t\"reason_code\": \"untrusted_or_invalid_input\",\n\t}\n}\n\ntest_fails_closed_for_missing_subject if {\n\tresult := example.result with input as {}\n\tresult == {\n\t\t\"decision\": \"deny\",\n\t\t\"reason_code\": \"untrusted_or_invalid_input\",\n\t}\n}\n\ntest_allows_trusted_subject if {\n\tresult := example.result with input as {\"subject\": {\"trusted\": true}}\n\tresult == {\n\t\t\"decision\": \"allow\",\n\t\t\"reason_code\": \"trusted_subject\",\n\t}\n}\n`;\n\n/** Sanitized local input example containing no credentials or personal data. */\nexport const POLICY_INPUT_EXAMPLE_TEMPLATE = `{\n \"subject\": {\n \"trusted\": false\n }\n}\n`;\n\n/** Target-local ignore rules for private evaluation input only. */\nexport const POLICY_GITIGNORE_TEMPLATE = `# Local policy evaluation input.\n/input.json\n`;\n\n/** Concise project-local authoring guide. */\nexport const POLICY_README_TEMPLATE = `# Transcend Policy Project\n\nThis directory is an OPA document tree that can be published to Transcend Policy Engine.\n\nThe policy under \\`policy_engine/example\\` is disposable teaching material. Replace it with your intended package tree, input shape, and extensible result documents. Keep decisions fail-closed and cover every non-test package with \\`manifest.json\\`.\n\nValidate formatting, strict Rego v1 compatibility, Regal lint, tests, and the publish contract:\n\n\\`\\`\\`sh\ntranscend policy lint --dir .\n\\`\\`\\`\n`;\n\n/** Complete safe starter in deterministic plan order. */\nconst POLICY_STARTER_FILES: readonly PolicyStarterFile[] = [\n {\n path: 'manifest.json',\n contents: POLICY_MANIFEST_TEMPLATE,\n description: 'Create the publishable Policy Engine manifest',\n },\n {\n path: '.regal/config.yaml',\n contents: POLICY_REGAL_CONFIG_TEMPLATE,\n description: 'Pin strict Rego v1 linting to OPA 1.13.1 capabilities',\n },\n {\n path: 'policy_engine/example/result.rego',\n contents: POLICY_RESULT_REGO_TEMPLATE,\n description: 'Create a documented fail-closed result entrypoint',\n },\n {\n path: 'policy_engine/example/result_test.rego',\n contents: POLICY_RESULT_TEST_REGO_TEMPLATE,\n description: 'Create executable tests for allow and fail-closed decisions',\n },\n {\n path: 'input.example.json',\n contents: POLICY_INPUT_EXAMPLE_TEMPLATE,\n description: 'Create a sanitized local evaluation input',\n },\n {\n path: '.gitignore',\n contents: POLICY_GITIGNORE_TEMPLATE,\n description: 'Ignore only the private local input file',\n },\n {\n path: 'README.md',\n contents: POLICY_README_TEMPLATE,\n description: 'Create the concise policy project guide',\n },\n];\n\n/**\n * Generate an independent copy of the safe policy starter.\n *\n * @returns Deterministic relative files\n */\nexport function generatePolicyStarterFiles(): PolicyStarterFile[] {\n return POLICY_STARTER_FILES.map((file) => ({ ...file }));\n}\n","import { posix } from 'node:path';\n\nimport { POLICY_STARTER_OPA_VERSION } from './policy-scaffold-templates.js';\n\n/** Regal version pinned by generated policy validation. */\nexport const POLICY_STARTER_REGAL_VERSION = '0.42.0';\n\n/** Repository-relative generated workflow path. */\nexport const POLICY_CI_WORKFLOW_PATH = '.github/workflows/transcend-policy.yml';\n\n/** Immutable actions/checkout v6 release commit. */\nexport const ACTIONS_CHECKOUT_SHA = 'd23441a48e516b6c34aea4fa41551a30e30af803';\n\n/** Immutable open-policy-agent/setup-opa v2.4.0 release commit. */\nexport const SETUP_OPA_SHA = 'b2b258e089860efaadaaf71bf6e3aecb4a3eeff1';\n\n/** Immutable open-policy-agent/setup-regal v2.0.0 release commit. */\nexport const SETUP_REGAL_SHA = '761188c3b435761fa254beca508a44875619648f';\n\n/**\n * Prefix a path below the repository-relative policy target.\n *\n * @param targetDirectory - POSIX repository-relative target\n * @param child - POSIX target-relative path or pattern\n * @returns Repository-relative path or pattern\n */\nfunction targetPath(targetDirectory: string, child: string): string {\n return targetDirectory === '.' ? child : posix.join(targetDirectory, child);\n}\n\n/**\n * Generate credential-free, validation-only Policy Engine CI.\n *\n * @param options - Repository paths and exact CLI release\n * @returns Complete GitHub Actions workflow YAML\n */\nexport function generatePolicyGithubActionsWorkflow(options: {\n /** Exact released Transcend CLI version. */\n cliVersion: string;\n /** Policy directory relative to the repository root. */\n targetDirectory: string;\n}): string {\n const watchedPaths = [\n targetPath(options.targetDirectory, '**/*.rego'),\n targetPath(options.targetDirectory, '**/*.json'),\n targetPath(options.targetDirectory, '**/*.yaml'),\n targetPath(options.targetDirectory, '**/*.yml'),\n targetPath(options.targetDirectory, '.regal/config.yaml'),\n targetPath(options.targetDirectory, '.regal.yaml'),\n POLICY_CI_WORKFLOW_PATH,\n ];\n const pathFilters = watchedPaths.map((path) => ` - ${JSON.stringify(path)}`).join('\\n');\n\n return `# Generated by transcend policy init.\nname: Transcend Policy\n\non:\n pull_request:\n paths:\n${pathFilters}\n push:\n paths:\n${pathFilters}\n\npermissions:\n contents: read\n\njobs:\n lint:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@${ACTIONS_CHECKOUT_SHA} # v6\n - name: Set up OPA\n uses: open-policy-agent/setup-opa@${SETUP_OPA_SHA} # v2.4.0\n with:\n version: ${JSON.stringify(POLICY_STARTER_OPA_VERSION)}\n - name: Set up Regal\n uses: open-policy-agent/setup-regal@${SETUP_REGAL_SHA} # v2.0.0\n with:\n version: ${JSON.stringify(POLICY_STARTER_REGAL_VERSION)}\n - name: Install the Transcend CLI\n run: npm install --global @transcend-io/cli@${options.cliVersion}\n - name: Validate Policy Engine project\n env:\n POLICY_DIRECTORY: ${JSON.stringify(options.targetDirectory)}\n run: >-\n transcend policy lint\n --dir \"$POLICY_DIRECTORY\"\n --noInteractive\n --json\n`;\n}\n","import { relative, sep } from 'node:path';\n\nimport {\n mergeJsonc,\n mergeStringArray,\n parseJsoncObject,\n type JsoncUpdate,\n} from '../scaffolding/jsonc.js';\n\n/** Recommended VS Code extension for OPA and Regal authoring. */\nexport const POLICY_VSCODE_EXTENSION = 'tsandall.opa';\n\n/** Conflicting syntax-only VS Code extension. */\nexport const CONFLICTING_POLICY_VSCODE_EXTENSION = 'glebbash.opa-highlight-only';\n\n/** Result of safely merging one repository editor artifact. */\nexport interface PolicyEditorMergeResult {\n /** Complete merged contents, or the unchanged original when unsafe. */\n contents: string;\n /** Actionable preservation warnings. */\n warnings: string[];\n}\n\n/** One desired scalar setting that must not replace a customization. */\ninterface DesiredSetting {\n /** JSONC object path. */\n path: string[];\n /** Desired generated value. */\n value: unknown;\n /** Human-readable setting key. */\n label: string;\n}\n\n/**\n * Compare JSON-compatible configuration values.\n *\n * @param left - Existing value\n * @param right - Desired value\n * @returns Whether the values are structurally equal\n */\nfunction configurationValuesEqual(left: unknown, right: unknown): boolean {\n return JSON.stringify(left) === JSON.stringify(right);\n}\n\n/**\n * Parse an editor object while preserving malformed existing content.\n *\n * @param contents - Existing JSONC, or null\n * @param label - Configuration label\n * @returns Parsed object or a preservation result\n */\nfunction parseEditorObject(\n contents: string | null,\n label: string,\n):\n | {\n /** Parsed JSONC object. */\n current: Record<string, unknown>;\n }\n | {\n /** Complete unchanged contents. */\n contents: string;\n /** Actionable warning. */\n warning: string;\n } {\n try {\n return { current: parseJsoncObject(contents ?? '{}\\n', label) };\n } catch (error) {\n return {\n contents: contents ?? '{}\\n',\n warning: `${error instanceof Error ? error.message : String(error)} Existing content was left unchanged.`,\n };\n }\n}\n\n/**\n * Apply safe JSONC updates or preserve the existing file when comments prevent it.\n *\n * @param contents - Existing JSONC\n * @param updates - Proven-safe updates\n * @param label - Configuration label\n * @param warnings - Existing merge warnings\n * @returns Complete contents and warnings\n */\nfunction applyEditorUpdates(\n contents: string | null,\n updates: readonly JsoncUpdate[],\n label: string,\n warnings: string[],\n): PolicyEditorMergeResult {\n if (updates.length === 0) {\n return { contents: contents ?? '{}\\n', warnings };\n }\n try {\n return {\n contents: mergeJsonc(contents, updates, label),\n warnings,\n };\n } catch (error) {\n return {\n contents: contents ?? '{}\\n',\n warnings: [\n ...warnings,\n `${error instanceof Error ? error.message : String(error)} Existing content was left unchanged.`,\n ],\n };\n }\n}\n\n/**\n * Add absent scalar settings without replacing repository customizations.\n *\n * @param current - Parsed editor object\n * @param desired - Desired settings\n * @param updates - Safe updates to append to\n * @param warnings - Conflict warnings to append to\n */\nfunction collectSafeScalarUpdates(\n current: Record<string, unknown>,\n desired: readonly DesiredSetting[],\n updates: JsoncUpdate[],\n warnings: string[],\n): void {\n desired.forEach(({ path, value, label }) => {\n const existing = path.reduce<unknown>((parent, key) => {\n return parent && typeof parent === 'object' && !Array.isArray(parent)\n ? (parent as Record<string, unknown>)[key]\n : undefined;\n }, current);\n if (existing === undefined) {\n updates.push({ path, value });\n } else if (!configurationValuesEqual(existing, value)) {\n warnings.push(\n `VS Code setting \"${label}\" has a repository-specific value and was left unchanged.`,\n );\n }\n });\n}\n\n/**\n * Build the workspace-relative OPA bundle root.\n *\n * @param repositoryRoot - Root that owns `.vscode`\n * @param targetDirectory - Selected policy project directory\n * @returns VS Code workspace path\n */\nfunction buildOpaWorkspaceRoot(repositoryRoot: string, targetDirectory: string): string {\n const target = relative(repositoryRoot, targetDirectory).split(sep).join('/') || '.';\n return target === '.' ? '${workspaceFolder}' : `\\${workspaceFolder}/${target}`;\n}\n\n/**\n * Merge strict target-scoped OPA and Rego editor settings.\n *\n * Setting names match the authoritative `open-policy-agent/vscode-opa`\n * extension metadata. Existing conflicting values are preserved and reported.\n *\n * @param contents - Existing `.vscode/settings.json` JSONC\n * @param repositoryRoot - Root that owns `.vscode`\n * @param targetDirectory - Selected policy project directory\n * @returns Merged settings and conflict warnings\n */\nexport function mergePolicyEditorSettings(\n contents: string | null,\n repositoryRoot: string,\n targetDirectory: string,\n): PolicyEditorMergeResult {\n const parsed = parseEditorObject(contents, 'VS Code policy settings');\n if ('warning' in parsed) {\n return { contents: parsed.contents, warnings: [parsed.warning] };\n }\n const { current } = parsed;\n const updates: JsoncUpdate[] = [];\n const warnings: string[] = [];\n\n const roots = current['opa.roots'];\n const desiredRoot = buildOpaWorkspaceRoot(repositoryRoot, targetDirectory);\n if (roots === undefined) {\n updates.push({ path: ['opa.roots'], value: [desiredRoot] });\n } else if (Array.isArray(roots) && roots.every((value) => typeof value === 'string')) {\n const merged = mergeStringArray(roots, [desiredRoot]);\n if (!configurationValuesEqual(merged, roots)) {\n updates.push({ path: ['opa.roots'], value: merged });\n }\n } else {\n warnings.push('VS Code setting \"opa.roots\" is customized and was left unchanged.');\n }\n\n collectSafeScalarUpdates(\n current,\n [\n { path: ['opa.checkOnSave'], value: true, label: 'opa.checkOnSave' },\n { path: ['opa.strictMode'], value: true, label: 'opa.strictMode' },\n { path: ['opa.bundleMode'], value: true, label: 'opa.bundleMode' },\n { path: ['opa.formatter'], value: 'opa-fmt-rego-v1', label: 'opa.formatter' },\n ],\n updates,\n warnings,\n );\n\n const regoSettings = current['[rego]'];\n if (regoSettings === undefined) {\n updates.push({\n path: ['[rego]'],\n value: {\n 'editor.defaultFormatter': POLICY_VSCODE_EXTENSION,\n 'editor.formatOnSave': true,\n 'editor.insertSpaces': false,\n 'editor.tabSize': 4,\n },\n });\n } else if (\n regoSettings !== null &&\n typeof regoSettings === 'object' &&\n !Array.isArray(regoSettings)\n ) {\n collectSafeScalarUpdates(\n current,\n [\n {\n path: ['[rego]', 'editor.defaultFormatter'],\n value: POLICY_VSCODE_EXTENSION,\n label: '[rego].editor.defaultFormatter',\n },\n {\n path: ['[rego]', 'editor.formatOnSave'],\n value: true,\n label: '[rego].editor.formatOnSave',\n },\n {\n path: ['[rego]', 'editor.insertSpaces'],\n value: false,\n label: '[rego].editor.insertSpaces',\n },\n {\n path: ['[rego]', 'editor.tabSize'],\n value: 4,\n label: '[rego].editor.tabSize',\n },\n ],\n updates,\n warnings,\n );\n } else {\n warnings.push('VS Code language setting \"[rego]\" is customized and was left unchanged.');\n }\n\n return applyEditorUpdates(contents, updates, 'VS Code policy settings', warnings);\n}\n\n/**\n * Merge OPA extension recommendations without disturbing unknown entries.\n *\n * VS Code's `extensions.json` schema supports `unwantedRecommendations`, so\n * the syntax-only extension can be removed from recommendations and discouraged.\n *\n * @param contents - Existing `.vscode/extensions.json` JSONC\n * @returns Merged extension recommendations and warnings\n */\nexport function mergePolicyEditorExtensions(contents: string | null): PolicyEditorMergeResult {\n const parsed = parseEditorObject(contents, 'VS Code policy extension recommendations');\n if ('warning' in parsed) {\n return { contents: parsed.contents, warnings: [parsed.warning] };\n }\n const { current } = parsed;\n const updates: JsoncUpdate[] = [];\n const warnings: string[] = [];\n\n const recommendations = current.recommendations;\n if (\n recommendations === undefined ||\n (Array.isArray(recommendations) && recommendations.every((value) => typeof value === 'string'))\n ) {\n const existing = recommendations ?? [];\n const desired = mergeStringArray(existing, [POLICY_VSCODE_EXTENSION]).filter(\n (value) => value !== CONFLICTING_POLICY_VSCODE_EXTENSION,\n );\n if (!configurationValuesEqual(existing, desired)) {\n updates.push({ path: ['recommendations'], value: desired });\n }\n } else {\n warnings.push(\n 'VS Code extension recommendations use an unknown shape and were left unchanged.',\n );\n }\n\n const unwanted = current.unwantedRecommendations;\n if (\n unwanted === undefined ||\n (Array.isArray(unwanted) && unwanted.every((value) => typeof value === 'string'))\n ) {\n const existing = unwanted ?? [];\n const desired = mergeStringArray(existing, [CONFLICTING_POLICY_VSCODE_EXTENSION]);\n if (!configurationValuesEqual(existing, desired)) {\n updates.push({ path: ['unwantedRecommendations'], value: desired });\n }\n } else {\n warnings.push(\n 'VS Code unwanted extension recommendations use an unknown shape and were left unchanged.',\n );\n }\n\n return applyEditorUpdates(\n contents,\n updates,\n 'VS Code policy extension recommendations',\n warnings,\n );\n}\n\n/**\n * Build the generated target-scoped VS Code lint task.\n *\n * @param repositoryRoot - Root that owns `.vscode`\n * @param targetDirectory - Selected policy project directory\n * @returns VS Code task object\n */\nexport function buildPolicyLintTask(\n repositoryRoot: string,\n targetDirectory: string,\n): Record<string, unknown> {\n const target = relative(repositoryRoot, targetDirectory).split(sep).join('/') || '.';\n return {\n label: 'policy: lint',\n type: 'process',\n command: 'transcend',\n args: ['policy', 'lint', '--dir', target, '--noInteractive'],\n group: {\n kind: 'test',\n isDefault: true,\n },\n problemMatcher: [],\n };\n}\n\n/**\n * Merge the default policy lint task while preserving custom tasks.\n *\n * @param contents - Existing `.vscode/tasks.json` JSONC\n * @param repositoryRoot - Root that owns `.vscode`\n * @param targetDirectory - Selected policy project directory\n * @returns Merged task configuration and warnings\n */\nexport function mergePolicyEditorTasks(\n contents: string | null,\n repositoryRoot: string,\n targetDirectory: string,\n): PolicyEditorMergeResult {\n const parsed = parseEditorObject(contents, 'VS Code policy tasks');\n if ('warning' in parsed) {\n return { contents: parsed.contents, warnings: [parsed.warning] };\n }\n const { current } = parsed;\n const updates: JsoncUpdate[] = [];\n const warnings: string[] = [];\n const version = current.version;\n if (version === undefined) {\n updates.push({ path: ['version'], value: '2.0.0' });\n } else if (version !== '2.0.0') {\n warnings.push('VS Code task schema version is customized and was left unchanged.');\n }\n\n const desiredTask = buildPolicyLintTask(repositoryRoot, targetDirectory);\n const tasks = current.tasks;\n if (tasks === undefined) {\n updates.push({ path: ['tasks'], value: [desiredTask] });\n } else if (Array.isArray(tasks)) {\n const matchingTask = tasks.find(\n (task) =>\n task !== null &&\n typeof task === 'object' &&\n !Array.isArray(task) &&\n (task as Record<string, unknown>).label === 'policy: lint',\n );\n if (matchingTask === undefined) {\n updates.push({ path: ['tasks'], value: [...tasks, desiredTask] });\n } else if (!configurationValuesEqual(matchingTask, desiredTask)) {\n warnings.push(\n 'VS Code task \"policy: lint\" has repository-specific customization and was left unchanged.',\n );\n }\n } else {\n warnings.push('VS Code tasks use an unknown shape and were left unchanged.');\n }\n\n return applyEditorUpdates(contents, updates, 'VS Code policy tasks', warnings);\n}\n","import { isAbsolute, join, posix, relative, sep } from 'node:path';\n\nimport {\n getManagedAgentSkillCandidatePaths,\n planManagedAgentSkill,\n type ManagedAgentSkillDefinition,\n} from '../scaffolding/agent-skill.js';\nimport { displayProjectPath, quoteShellArgument } from '../scaffolding/project-plan-output.js';\nimport {\n getPlanningPathSnapshot,\n getPlanningFileSnapshot,\n planFileChange,\n type PlanningPathSnapshot,\n} from '../scaffolding/project-plan.js';\nimport { getPolicyManifestPath } from './policy-project-discovery.js';\nimport {\n generatePolicyGithubActionsWorkflow,\n POLICY_CI_WORKFLOW_PATH,\n} from './policy-scaffold-artifacts.js';\nimport {\n mergePolicyEditorExtensions,\n mergePolicyEditorSettings,\n mergePolicyEditorTasks,\n type PolicyEditorMergeResult,\n} from './policy-scaffold-config.js';\nimport {\n POLICY_INIT_RESULT_VERSION,\n PolicySetupFeature,\n type PolicyInitProjectPlan,\n type PolicyProjectState,\n type PolicySetupFeature as PolicySetupFeatureType,\n} from './policy-scaffold-model.js';\nimport { generatePolicyStarterFiles, type PolicyStarterFile } from './policy-scaffold-templates.js';\nimport { POLICY_SKILL_FILES, POLICY_SKILL_NAME } from './policy-skill.js';\n\n/** Managed Policy Engine Agent Skill definition. */\nconst POLICY_MANAGED_SKILL: ManagedAgentSkillDefinition = {\n name: POLICY_SKILL_NAME,\n displayName: 'Policy Engine',\n owner: '@transcend-io/cli',\n files: POLICY_SKILL_FILES,\n};\n\n/** In-memory input consumed by the pure policy initializer. */\nexport interface PolicyInitPlanningInput {\n /** Project discovery state. */\n state: PolicyProjectState;\n /** Potential mutation paths keyed by absolute path. */\n snapshots: Readonly<Record<string, PlanningPathSnapshot>>;\n}\n\n/** Optional repository setup selected for policy initialization. */\nexport interface PolicyInitPlanOptions {\n /** Selected setup features. */\n features: readonly PolicySetupFeatureType[];\n /** Exact released Transcend CLI version for generated CI. */\n cliVersion: string;\n}\n\n/**\n * Build the copyable policy lint command for one target.\n *\n * @param state - Discovered project state\n * @returns Raw one-line command\n */\nexport function buildPolicyLintCommand(state: PolicyProjectState): string {\n const directory = displayProjectPath(state.invocationDirectory, state.targetDirectory);\n return `transcend policy lint --dir ${quoteShellArgument(directory)} --noInteractive`;\n}\n\n/**\n * Enumerate all core starter paths that could be created.\n *\n * @param state - Policy project state\n * @param options - Selected repository setup\n * @returns Absolute candidate paths\n */\nexport function getPolicyInitPlanningCandidatePaths(\n state: PolicyProjectState,\n options: Pick<PolicyInitPlanOptions, 'features'>,\n): string[] {\n const paths = new Set(\n generatePolicyStarterFiles().map(({ path }) => join(state.targetDirectory, path)),\n );\n const selected = new Set(options.features);\n if (selected.has(PolicySetupFeature.Editor)) {\n paths.add(join(state.projectRoot, '.vscode', 'settings.json'));\n paths.add(join(state.projectRoot, '.vscode', 'extensions.json'));\n paths.add(join(state.projectRoot, '.vscode', 'tasks.json'));\n }\n if (selected.has(PolicySetupFeature.Skill)) {\n getManagedAgentSkillCandidatePaths(\n state.projectRoot,\n state.existingSkillDirectories,\n POLICY_MANAGED_SKILL,\n ).forEach((path) => paths.add(path));\n }\n if (selected.has(PolicySetupFeature.Ci) && state.repositoryRoot && state.usesGithub) {\n paths.add(join(state.repositoryRoot, POLICY_CI_WORKFLOW_PATH));\n }\n return [...paths].sort((left, right) => left.localeCompare(right));\n}\n\n/**\n * Ensure a destination stays below an approved project root.\n *\n * @param root - Approved root\n * @param path - Candidate path\n */\nfunction assertContained(root: string, path: string): void {\n const child = relative(root, path);\n if (child === '..' || child.startsWith(`..${sep}`) || isAbsolute(child)) {\n throw new Error(`Refusing to modify path outside project root: ${path}`);\n }\n}\n\n/**\n * Enumerate generated file and directory paths allowed in an exact starter.\n *\n * @param files - Starter files\n * @returns POSIX relative paths\n */\nfunction starterRelativePaths(files: readonly PolicyStarterFile[]): Set<string> {\n const paths = new Set<string>(['input.json']);\n files.forEach(({ path }) => {\n paths.add(path);\n let parent = posix.dirname(path);\n while (parent !== '.') {\n paths.add(parent);\n parent = posix.dirname(parent);\n }\n });\n return paths;\n}\n\n/**\n * Add or classify one regular-file mutation.\n *\n * @param plan - Policy plan being assembled\n * @param input - Collected snapshots\n * @param options - Desired file\n */\nfunction addFileChange(\n plan: PolicyInitProjectPlan,\n input: PolicyInitPlanningInput,\n options: {\n /** Absolute destination path. */\n path: string;\n /** Complete desired contents. */\n contents: string;\n /** Human-readable plan description. */\n description: string;\n /** Refuse existing contents. */\n createOnly?: boolean;\n },\n): void {\n const change = planFileChange({\n snapshot: getPlanningFileSnapshot(input.snapshots, options.path),\n after: options.contents,\n description: options.description,\n ...(options.createOnly === undefined ? {} : { createOnly: options.createOnly }),\n });\n if (change) {\n plan.changes.push(change);\n } else {\n plan.unchanged.push(options.path);\n }\n}\n\n/**\n * Add one safe editor merge and its preservation warnings.\n *\n * @param plan - Policy plan being assembled\n * @param input - Collected snapshots\n * @param path - Absolute editor artifact path\n * @param result - Pure JSONC merge result\n * @param description - Human-readable plan description\n * @param cwd - Invocation directory for portable warning paths\n */\nfunction addEditorMerge(\n plan: PolicyInitProjectPlan,\n input: PolicyInitPlanningInput,\n path: string,\n result: PolicyEditorMergeResult,\n description: string,\n cwd: string,\n): void {\n addFileChange(plan, input, {\n path,\n contents: result.contents,\n description,\n });\n plan.warnings.push(\n ...result.warnings.map((warning) => `${warning} (${displayProjectPath(cwd, path)})`),\n );\n}\n\n/**\n * Build a safe policy project plan without reading the filesystem.\n *\n * Empty targets receive the complete starter. Existing targets are classified\n * only; no domain file is added, merged, or overwritten.\n *\n * @param input - Collected project state and path snapshots\n * @param options - Selected setup and pinned CLI version\n * @returns Validated policy initialization plan\n */\nexport function buildPolicyInitPlan(\n input: PolicyInitPlanningInput,\n options: PolicyInitPlanOptions,\n): PolicyInitProjectPlan {\n const { state } = input;\n const files = generatePolicyStarterFiles();\n const manifestPath = getPolicyManifestPath(state);\n const lintCommand = buildPolicyLintCommand(state);\n const resultPath = join(state.targetDirectory, 'policy_engine', 'example', 'result.rego');\n const plan: PolicyInitProjectPlan = {\n version: POLICY_INIT_RESULT_VERSION,\n command: 'init',\n rootDirectory: state.projectRoot,\n targetDirectory: state.targetDirectory,\n manifestPath,\n changes: [],\n unchanged: [],\n warnings: [],\n nextSteps: [lintCommand],\n features: [...options.features],\n };\n\n const candidatePaths = getPolicyInitPlanningCandidatePaths(state, options);\n assertContained(state.projectRoot, state.targetDirectory);\n candidatePaths.forEach((path) => assertContained(state.projectRoot, path));\n\n let hasDisposableExample = false;\n if (state.relativeFilePaths.length === 0) {\n hasDisposableExample = true;\n plan.directoryPreconditions = [\n {\n path: state.targetDirectory,\n relativePaths: [...state.relativePaths],\n },\n ];\n files.forEach((file) => {\n const path = join(state.targetDirectory, file.path);\n const snapshot = getPlanningPathSnapshot(input.snapshots, path);\n if (snapshot.kind !== 'absent') {\n throw new Error(`Expected an empty policy target, but found an entry at: ${path}`);\n }\n addFileChange(plan, input, {\n path,\n contents: file.contents,\n description: file.description,\n createOnly: true,\n });\n });\n } else {\n let allStarterFilesMatch = true;\n files.forEach((file) => {\n const path = join(state.targetDirectory, file.path);\n const snapshot = getPlanningPathSnapshot(input.snapshots, path);\n if (snapshot.kind === 'file' && snapshot.contents === file.contents) {\n plan.unchanged.push(path);\n return;\n }\n allStarterFilesMatch = false;\n if (snapshot.kind !== 'absent') {\n plan.unchanged.push(path);\n plan.warnings.push(\n `Existing policy scaffold path was left unchanged: ${displayProjectPath(\n state.invocationDirectory,\n path,\n )}`,\n );\n }\n });\n hasDisposableExample = allStarterFilesMatch;\n\n const allowedPaths = starterRelativePaths(files);\n const hasCustomPaths = state.relativeFilePaths.some((path) => !allowedPaths.has(path));\n if (!allStarterFilesMatch || hasCustomPaths) {\n plan.warnings.push(\n `Existing policy target contains custom or partial content, so no starter files were added or overwritten. ` +\n `Review ${displayProjectPath(\n state.invocationDirectory,\n state.targetDirectory,\n )} manually, then run \\`${lintCommand}\\`.`,\n );\n }\n }\n if (hasDisposableExample) {\n plan.disposableExamplePath = resultPath;\n plan.nextSteps.push(\n `Edit ${quoteShellArgument(displayProjectPath(state.invocationDirectory, resultPath))}`,\n );\n }\n\n const selected = new Set(options.features);\n const root = state.projectRoot;\n if (selected.has(PolicySetupFeature.Editor)) {\n const settingsPath = join(root, '.vscode', 'settings.json');\n const extensionsPath = join(root, '.vscode', 'extensions.json');\n const tasksPath = join(root, '.vscode', 'tasks.json');\n const editorArtifacts = [\n {\n path: settingsPath,\n description: 'Merge strict target-scoped OPA and Rego editor settings',\n merge: mergePolicyEditorSettings,\n },\n {\n path: extensionsPath,\n description: 'Recommend the OPA extension and discourage its syntax-only conflict',\n merge: (\n contents: string | null,\n _repositoryRoot: string,\n _targetDirectory: string,\n ): PolicyEditorMergeResult => mergePolicyEditorExtensions(contents),\n },\n {\n path: tasksPath,\n description: 'Add the default target-scoped policy lint task',\n merge: mergePolicyEditorTasks,\n },\n ];\n editorArtifacts.forEach(({ path, description, merge }) => {\n const snapshot = getPlanningPathSnapshot(input.snapshots, path);\n if (snapshot.kind !== 'absent' && snapshot.kind !== 'file') {\n plan.unchanged.push(path);\n plan.warnings.push(\n `Existing VS Code artifact is not a regular file and was left unchanged: ${displayProjectPath(\n state.invocationDirectory,\n path,\n )}`,\n );\n return;\n }\n addEditorMerge(\n plan,\n input,\n path,\n merge(snapshot.kind === 'file' ? snapshot.contents : null, root, state.targetDirectory),\n description,\n state.invocationDirectory,\n );\n });\n }\n\n if (selected.has(PolicySetupFeature.Skill)) {\n const skillPlan = planManagedAgentSkill({\n rootDirectory: root,\n existingDirectories: state.existingSkillDirectories,\n snapshots: input.snapshots,\n skill: POLICY_MANAGED_SKILL,\n preserveModified: true,\n });\n plan.changes.push(...skillPlan.changes);\n plan.unchanged.push(...skillPlan.unchanged);\n plan.warnings.push(\n ...skillPlan.warnings.map((warning) => {\n return skillPlan.unchanged.reduce(\n (rendered, path) =>\n rendered.replace(path, displayProjectPath(state.invocationDirectory, path)),\n warning,\n );\n }),\n );\n }\n\n if (selected.has(PolicySetupFeature.Ci)) {\n if (!state.repositoryRoot || !state.usesGithub) {\n plan.warnings.push(\n 'GitHub Actions setup was selected, but this target is not inside a detected GitHub repository.',\n );\n } else {\n const workflowPath = join(state.repositoryRoot, POLICY_CI_WORKFLOW_PATH);\n const target =\n relative(state.repositoryRoot, state.targetDirectory).split(sep).join('/') || '.';\n const workflowContents = generatePolicyGithubActionsWorkflow({\n cliVersion: options.cliVersion,\n targetDirectory: target,\n });\n const workflowSnapshot = getPlanningPathSnapshot(input.snapshots, workflowPath);\n if (workflowSnapshot.kind === 'absent') {\n addFileChange(plan, input, {\n path: workflowPath,\n contents: workflowContents,\n description: 'Add credential-free Policy Engine validation',\n createOnly: true,\n });\n } else if (\n workflowSnapshot.kind === 'file' &&\n workflowSnapshot.contents === workflowContents\n ) {\n plan.unchanged.push(workflowPath);\n } else {\n plan.unchanged.push(workflowPath);\n plan.warnings.push(\n `Existing GitHub Actions workflow was left unchanged: ${displayProjectPath(\n state.invocationDirectory,\n workflowPath,\n )}. Adapt it manually to run \\`${lintCommand}\\`.`,\n );\n }\n }\n }\n\n plan.changes.forEach(({ path }) => assertContained(state.projectRoot, path));\n return plan;\n}\n","import colors from 'colors';\n\nimport { version as CLI_VERSION } from '../../../constants.js';\nimport type { LocalContext } from '../../../context.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport {\n runCapturedProcess,\n type CapturedProcessResult,\n type CapturedProcessRunner,\n} from '../../../lib/cli/run-captured-process.js';\nimport {\n DEFAULT_POLICY_PROJECT_DIRECTORY,\n discoverPolicyProject,\n} from '../../../lib/policy/policy-project-discovery.js';\nimport {\n OPA_INSTALL_URL,\n OPA_MISSING_MESSAGE,\n parsePolicyToolVersion,\n MINIMUM_POLICY_STARTER_REGAL_VERSION,\n REGAL_INSTALL_URL,\n REGAL_MISSING_MESSAGE,\n unsupportedOpaVersionMessage,\n unsupportedRegalVersionMessage,\n} from '../../../lib/policy/policy-runtime.js';\nimport {\n PolicySetupFeature,\n type PolicySetupFeature as PolicySetupFeatureType,\n} from '../../../lib/policy/policy-scaffold-model.js';\nimport {\n buildPolicyInitAiHandoff,\n buildPolicyInitPlanResult,\n type PolicyInitToolVersions,\n} from '../../../lib/policy/policy-scaffold-output.js';\nimport {\n buildPolicyInitPlan,\n getPolicyInitPlanningCandidatePaths,\n} from '../../../lib/policy/policy-scaffold-planning.js';\nimport { collectPlanningSnapshots } from '../../../lib/scaffolding/project-discovery.js';\nimport { applyProjectPlan } from '../../../lib/scaffolding/project-plan-apply.js';\nimport {\n displayProjectPath,\n quoteShellArgument,\n renderProjectPlan,\n} from '../../../lib/scaffolding/project-plan-output.js';\nimport {\n PromptCancelledError,\n type PromptChoice,\n ScaffoldPrompts,\n} from '../../../lib/scaffolding/prompts.js';\n\n/** Flags for `transcend policy init`. */\nexport interface PolicyInitFlags {\n /** Install repository-level VS Code setup. */\n editor?: boolean;\n /** Install the Policy Engine Agent Skill. */\n skill?: boolean;\n /** Install validation-only GitHub Actions CI. */\n ci?: boolean;\n /** Disable prompts. */\n noInteractive: boolean;\n /** Render but do not apply the plan. */\n dryRun: boolean;\n /** Approve the final displayed plan. */\n yes: boolean;\n /** Emit one stable JSON result on stdout. */\n json: boolean;\n}\n\n/** User-facing optional setup labels. */\nconst SETUP_LABELS: Readonly<Record<PolicySetupFeatureType, string>> = {\n [PolicySetupFeature.Editor]: 'VS Code settings and lint task',\n [PolicySetupFeature.Skill]: 'Policy Engine Agent Skill',\n [PolicySetupFeature.Ci]: 'Validation-only GitHub Actions',\n};\n\n/** All optional setup features in stable prompt order. */\nconst ALL_SETUP_FEATURES = Object.values(PolicySetupFeature);\n\n/** Runtime compatibility detected before policy planning. */\ninterface PolicyRuntimeProbe {\n /** Compatible tool versions. */\n tools: PolicyInitToolVersions;\n /** Missing or incompatible runtime guidance. */\n warnings: string[];\n}\n\n/**\n * Whether this invocation can ask questions.\n *\n * @param flags - Interaction flags\n * @param stdinIsTTY - Whether standard input is interactive\n * @param stderrIsTTY - Whether prompt output is interactive\n * @returns Whether prompts are enabled\n */\nfunction isInteractiveInvocation(\n flags: Pick<PolicyInitFlags, 'json' | 'noInteractive'>,\n stdinIsTTY: boolean | undefined,\n stderrIsTTY: boolean | undefined,\n): boolean {\n return !flags.json && !flags.noInteractive && Boolean(stdinIsTTY && stderrIsTTY);\n}\n\n/**\n * Resolve setup from explicit flags or one default-selected checklist.\n *\n * @param prompts - Prompt adapters\n * @param flags - Setup flags\n * @param options - Interaction state\n * @returns Explicitly selected setup features\n */\nasync function resolveFeatures(\n prompts: ScaffoldPrompts,\n flags: PolicyInitFlags,\n options: {\n /** Whether prompts are available. */\n interactive: boolean;\n },\n): Promise<PolicySetupFeatureType[]> {\n const enabled: Readonly<Record<PolicySetupFeatureType, boolean | undefined>> = {\n [PolicySetupFeature.Editor]: flags.editor,\n [PolicySetupFeature.Skill]: flags.skill,\n [PolicySetupFeature.Ci]: flags.ci,\n };\n if (!options.interactive) {\n return ALL_SETUP_FEATURES.filter((feature) => enabled[feature] === true);\n }\n const choices: PromptChoice<PolicySetupFeatureType>[] = ALL_SETUP_FEATURES.map((feature) => ({\n name: SETUP_LABELS[feature],\n value: feature,\n checked: enabled[feature] !== false,\n }));\n return prompts.checkbox('Choose repository setup:', choices);\n}\n\n/**\n * Explain a failed version subprocess with official installation guidance.\n *\n * @param tool - Policy tool name\n * @param result - Failed captured process\n * @returns Actionable warning\n */\nfunction failedVersionProbeMessage(tool: 'OPA' | 'Regal', result: CapturedProcessResult): string {\n const detail = [result.stdout.trim(), result.stderr.trim()].filter(Boolean).join('\\n');\n const url = tool === 'OPA' ? OPA_INSTALL_URL : REGAL_INSTALL_URL;\n const requirement =\n tool === 'OPA' ? 'OPA 1.x' : `Regal ${MINIMUM_POLICY_STARTER_REGAL_VERSION} or newer`;\n return (\n `${requirement} is required, but \\`${tool.toLowerCase()} version\\` exited with code ` +\n `${result.code}${detail ? `: ${detail}` : '.'} ` +\n `Install or upgrade it using the official instructions: ${url}`\n );\n}\n\n/**\n * Probe both local policy runtimes without installing or modifying them.\n *\n * @param context - CLI context\n * @param cwd - Invocation working directory\n * @param runner - Captured subprocess runner\n * @returns Compatible versions and exact runtime guidance\n */\nasync function probePolicyRuntimes(\n context: LocalContext,\n cwd: string,\n runner: CapturedProcessRunner,\n): Promise<PolicyRuntimeProbe> {\n const tools: PolicyInitToolVersions = { opa: null, regal: null };\n const warnings: string[] = [];\n\n const opaResult = await runner('opa', ['version'], { cwd }, context);\n if (opaResult.error?.code === 'ENOENT') {\n warnings.push(OPA_MISSING_MESSAGE);\n } else {\n const output = `${opaResult.stdout}\\n${opaResult.stderr}`;\n const unsupported = unsupportedOpaVersionMessage(output);\n if (opaResult.code !== 0) {\n warnings.push(unsupported ?? failedVersionProbeMessage('OPA', opaResult));\n } else if (unsupported) {\n warnings.push(unsupported);\n } else {\n tools.opa = parsePolicyToolVersion(output)!.version;\n }\n }\n\n const regalResult = await runner('regal', ['version'], { cwd }, context);\n if (regalResult.error?.code === 'ENOENT') {\n warnings.push(REGAL_MISSING_MESSAGE);\n } else {\n const output = `${regalResult.stdout}\\n${regalResult.stderr}`;\n const unsupported = unsupportedRegalVersionMessage(\n output,\n MINIMUM_POLICY_STARTER_REGAL_VERSION,\n 'the generated OPA 1.13.1 capabilities configuration',\n );\n if (regalResult.code !== 0) {\n warnings.push(unsupported ?? failedVersionProbeMessage('Regal', regalResult));\n } else if (unsupported) {\n warnings.push(unsupported);\n } else {\n tools.regal = parsePolicyToolVersion(output)!.version;\n }\n }\n\n return { tools, warnings };\n}\n\n/**\n * Initialize a credential-free local Policy Engine project.\n *\n * @param this - CLI context\n * @param flags - Scaffold and interaction flags\n * @param directory - Target policy directory\n * @param runner - Captured policy tool runner\n */\nexport async function init(\n this: LocalContext,\n flags: PolicyInitFlags,\n directory: string = DEFAULT_POLICY_PROJECT_DIRECTORY,\n runner: CapturedProcessRunner = runCapturedProcess,\n): Promise<void> {\n doneInputValidation(this.process);\n try {\n const runtime = await probePolicyRuntimes(this, this.process.cwd(), runner);\n const state = discoverPolicyProject(this, directory);\n const prompts = new ScaffoldPrompts(this);\n const interactive = isInteractiveInvocation(\n flags,\n this.process.stdin.isTTY,\n this.process.stderr.isTTY,\n );\n const features = await resolveFeatures(prompts, flags, { interactive });\n const candidatePaths = getPolicyInitPlanningCandidatePaths(state, { features });\n const snapshots = collectPlanningSnapshots(this, state.projectRoot, candidatePaths);\n\n const plan = buildPolicyInitPlan(\n { state, snapshots },\n {\n features,\n cliVersion: CLI_VERSION,\n },\n );\n plan.warnings.push(...runtime.warnings);\n\n if (!flags.json) {\n this.logger.info(\n renderProjectPlan(plan, {\n cwd: this.process.cwd(),\n title: 'Policy initialization plan',\n details: [\n { label: 'Target', path: plan.targetDirectory },\n { label: 'Manifest', path: plan.manifestPath },\n ],\n }),\n );\n }\n\n let approved = plan.changes.length === 0 || flags.dryRun;\n if (plan.changes.length > 0 && !flags.dryRun) {\n if (flags.yes) {\n approved = true;\n } else if (interactive) {\n approved = await prompts.confirm('Apply this complete plan?', true);\n } else {\n throw new Error(\n 'The plan requires approval in a non-interactive invocation. Review with --dryRun, then pass --yes.',\n );\n }\n }\n\n if (approved && !flags.dryRun && plan.changes.length > 0) {\n await applyProjectPlan(this, plan);\n }\n const applied = approved && !flags.dryRun && plan.changes.length > 0;\n const setupAvailable = approved && !flags.dryRun;\n const aiHandoff = buildPolicyInitAiHandoff({\n projectPath: quoteShellArgument(\n displayProjectPath(this.process.cwd(), state.targetDirectory),\n ),\n ...(plan.disposableExamplePath\n ? {\n examplePath: quoteShellArgument(\n displayProjectPath(this.process.cwd(), plan.disposableExamplePath),\n ),\n }\n : {}),\n hasSkill: setupAvailable && features.includes(PolicySetupFeature.Skill),\n lintCommand: plan.nextSteps[0]!,\n });\n const result = buildPolicyInitPlanResult(plan, {\n applied,\n dryRun: flags.dryRun,\n cwd: this.process.cwd(),\n aiHandoff,\n tools: runtime.tools,\n });\n if (flags.json) {\n this.process.stdout.write(`${JSON.stringify(result)}\\n`);\n return;\n }\n if (flags.dryRun) {\n this.logger.info(colors.yellow('Dry run complete. No changes were written.'));\n return;\n }\n if (!approved) {\n this.logger.info(colors.yellow('No changes applied.'));\n return;\n }\n if (plan.changes.length === 0) {\n const message =\n plan.warnings.length === runtime.warnings.length\n ? 'Policy project is already initialized.'\n : 'Existing policy project was left unchanged.';\n this.logger.info(colors.green(message));\n } else {\n this.logger.info(colors.green('Policy project initialized.'));\n }\n if (plan.nextSteps.length > 0) {\n this.logger.info(`\\n${colors.bold('Next steps')}`);\n plan.nextSteps.forEach((step) => this.logger.info(step));\n }\n this.logger.info(`\\n${colors.bold('AI handoff — paste into your coding agent')}`);\n this.logger.info(aiHandoff);\n } catch (error) {\n if (error instanceof PromptCancelledError) {\n return this.process.exit(130);\n }\n throw error;\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./bulkRestartRequests-
|
|
2
|
-
//# sourceMappingURL=impl-
|
|
1
|
+
import{t as e}from"./bulkRestartRequests-CMdTpO-W.mjs";import{t}from"./done-input-validation-BUz-aVC5.mjs";async function n({auth:n,requestReceiptFolder:r,sombraAuth:i,actions:a,statuses:o,requestIds:s,createdAt:c,emailIsVerified:l,silentModeBefore:u,sendEmailReceipt:d,copyIdentifiers:f,restartIdentifierStrategy:p,skipWaitingPeriod:m,createdAtBefore:h,createdAtAfter:g,updatedAtBefore:_,updatedAtAfter:v,concurrency:y,transcendUrl:b}){t(this.process),await e({requestReceiptFolder:r,auth:n,sombraAuth:i,requestActions:a,requestStatuses:o,requestIds:s,createdAt:c,emailIsVerified:l,silentModeBefore:u,sendEmailReceipt:d,copyIdentifiers:f,restartIdentifierStrategy:p,skipWaitingPeriod:m,createdAtBefore:h,createdAtAfter:g,updatedAtBefore:_,updatedAtAfter:v,concurrency:y,transcendUrl:b})}export{n as restart};
|
|
2
|
+
//# sourceMappingURL=impl-Dzqr61LA.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impl-
|
|
1
|
+
{"version":3,"file":"impl-Dzqr61LA.mjs","names":[],"sources":["../src/commands/request/restart/impl.ts"],"sourcesContent":["import type {\n RequestAction,\n RequestStatus,\n RestartIdentifierStrategy,\n} from '@transcend-io/privacy-types';\n\nimport type { LocalContext } from '../../../context.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { bulkRestartRequests } from '../../../lib/requests/index.js';\n\nexport interface RestartCommandFlags {\n auth: string;\n actions: RequestAction[];\n statuses: RequestStatus[];\n transcendUrl: string;\n requestReceiptFolder: string;\n sombraAuth?: string;\n concurrency: number;\n requestIds?: string[];\n emailIsVerified: boolean;\n createdAt?: Date;\n silentModeBefore?: Date;\n createdAtBefore?: Date;\n createdAtAfter?: Date;\n updatedAtBefore?: Date;\n updatedAtAfter?: Date;\n sendEmailReceipt: boolean;\n copyIdentifiers: boolean;\n restartIdentifierStrategy?: RestartIdentifierStrategy;\n skipWaitingPeriod: boolean;\n}\n\nexport async function restart(\n this: LocalContext,\n {\n auth,\n requestReceiptFolder,\n sombraAuth,\n actions,\n statuses,\n requestIds,\n createdAt,\n emailIsVerified,\n silentModeBefore,\n sendEmailReceipt,\n copyIdentifiers,\n restartIdentifierStrategy,\n skipWaitingPeriod,\n createdAtBefore,\n createdAtAfter,\n updatedAtBefore,\n updatedAtAfter,\n concurrency,\n transcendUrl,\n }: RestartCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process);\n\n await bulkRestartRequests({\n requestReceiptFolder,\n auth,\n sombraAuth,\n requestActions: actions,\n requestStatuses: statuses,\n requestIds,\n createdAt,\n emailIsVerified,\n silentModeBefore,\n sendEmailReceipt,\n copyIdentifiers,\n restartIdentifierStrategy,\n skipWaitingPeriod,\n createdAtBefore,\n createdAtAfter,\n updatedAtBefore,\n updatedAtAfter,\n concurrency,\n transcendUrl,\n });\n}\n"],"mappings":"2GAgCA,eAAsB,EAEpB,CACE,OACA,uBACA,aACA,UACA,WACA,aACA,YACA,kBACA,mBACA,mBACA,kBACA,4BACA,oBACA,kBACA,iBACA,kBACA,iBACA,cACA,gBAEa,CACf,EAAoB,KAAK,QAAQ,CAEjC,MAAM,EAAoB,CACxB,uBACA,OACA,aACA,eAAgB,EAChB,gBAAiB,EACjB,aACA,YACA,kBACA,mBACA,mBACA,kBACA,4BACA,oBACA,kBACA,iBACA,kBACA,iBACA,cACA,eACD,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{r as e}from"./constants-
|
|
2
|
-
//# sourceMappingURL=impl-
|
|
1
|
+
import{r as e}from"./constants-BnIMwfNb.mjs";import{r as t}from"./readTranscendYaml-BNn6-Ofi.mjs";import{n,t as r}from"./mergeTranscendInputs-DFQcbh8b.mjs";import{t as i}from"./parseVariablesFromString-BOSfQ4QF.mjs";import{t as a}from"./validateTranscendAuth-D6Wr1cxY.mjs";import{t as o}from"./listFiles-BdFUbX5x.mjs";import{t as s}from"./done-input-validation-BUz-aVC5.mjs";import c from"node:path";import l from"colors";import{buildTranscendGraphQLClient as u}from"@transcend-io/sdk";import{mapSeries as d}from"@transcend-io/utils";async function f({transcendUrl:e,auth:t,pageSize:r,publishToPrivacyCenter:i,contents:a,deleteExtraAttributeValues:o=!1,classifyService:s=!1,logger:c}){let d=u(e,t);try{let e=await n(a,d,{pageSize:r,publishToPrivacyCenter:i,classifyService:s,deleteExtraAttributeValues:o,logger:c});return e.success||e.errors.forEach(({resource:e,item:t,message:n})=>{c.error(l.red(`Failed to sync ${e}${t?` "${t}"`:``}: ${n}`))}),e.success}catch(e){return c.error(l.red(`An unexpected error occurred syncing the schema: ${e.message}`)),!1}}async function p({file:n=`./transcend.yml`,transcendUrl:u,auth:p,variables:m,pageSize:h,publishToPrivacyCenter:g,classifyService:_,deleteExtraAttributeValues:v}){s(this.process);let y=await a(p,this),b=i(m),x;if(x=Array.isArray(y)&&this.fs.lstatSync(n).isDirectory()?o(this.fs.readdirSync(n)).map(e=>c.join(n,e)):n.split(`,`),x.length<1)throw Error(`No file specified!`);let S=x.map(e=>{this.fs.existsSync(e)?this.logger.info(l.magenta(`Reading file "${e}"...`)):(this.logger.error(l.red(`The file path does not exist on disk: ${e}. You can specify the filepath using --file=./examples/transcend.yml`)),this.process.exit(1));try{let n=t(this.fs.readFileSync(e,`utf8`),b,e);return this.logger.info(l.green(`Successfully read in "${e}"`)),{content:n,name:e.split(`/`).pop().replace(`.yml`,``)}}catch(e){this.logger.error(l.red(`The shape of your yaml file is invalid with the following errors: ${e.message}`)),this.process.exit(1)}});if(typeof y==`string`){let[t,...n]=S.map(({content:e})=>e);await f({transcendUrl:u,auth:y,contents:r(t,...n),publishToPrivacyCenter:g,deleteExtraAttributeValues:v,pageSize:h,classifyService:!!_,logger:this.logger})||(this.logger.info(l.red(`Sync encountered errors. View output above for more information, or check out ${e}`)),this.process.exit(1))}else{if(S.length!==1&&S.length!==y.length)throw Error(`Expected list of yml files to be equal to the list of API keys.Got ${S.length} YML file${S.length===1?``:`s`} and ${y.length} API key${y.length===1?``:`s`}`);let t=[];await d(y,async(e,n)=>{let r=`[${n+1}/${y.length}][${e.organizationName}] `;this.logger.info(l.magenta(`~~~\n\n${r}Attempting to push configuration...\n\n~~~`));let i=S.length===1?S[0].content:S.find(t=>t.name===e.organizationName)?.content;if(!i){this.logger.error(l.red(`${r}Failed to find transcend.yml file for organization: "${e.organizationName}".`)),t.push(e.organizationName);return}await f({transcendUrl:u,auth:e.apiKey,contents:i,pageSize:h,publishToPrivacyCenter:g,deleteExtraAttributeValues:v,classifyService:_,logger:this.logger})?this.logger.info(l.green(`${r}Successfully pushed configuration!`)):(this.logger.error(l.red(`${r}Failed to sync configuration.`)),t.push(e.organizationName))}),t.length>0&&(this.logger.info(l.red(`Sync encountered errors for "${t.join(`,`)}". View output above for more information, or check out ${e}`)),this.process.exit(1))}this.logger.info(l.green(`Successfully synced yaml file to Transcend! View at ${e}`))}export{p as push};
|
|
2
|
+
//# sourceMappingURL=impl-RgoaYjMi.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impl-DNzkRayg.mjs","names":[],"sources":["../src/commands/inventory/push/impl.ts"],"sourcesContent":["import path from 'node:path';\n\nimport { buildTranscendGraphQLClient } from '@transcend-io/sdk';\nimport { mapSeries } from '@transcend-io/utils';\nimport colors from 'colors';\n\nimport { TranscendInput } from '../../../codecs.js';\nimport { ADMIN_DASH_INTEGRATIONS } from '../../../constants.js';\nimport type { LocalContext } from '../../../context.js';\nimport { validateTranscendAuth, filterFileNames } from '../../../lib/api-keys/index.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { syncConfigurationToTranscend } from '../../../lib/graphql/index.js';\nimport { parseVariablesFromString } from '../../../lib/helpers/parseVariablesFromString.js';\nimport { mergeTranscendInputs } from '../../../lib/mergeTranscendInputs.js';\nimport { parseTranscendYaml } from '../../../lib/readTranscendYaml.js';\n\n/**\n * Sync configuration to Transcend\n *\n * @param options - Options\n * @returns True if synced successfully, false if error occurs\n */\nasync function syncConfiguration({\n transcendUrl,\n auth,\n pageSize,\n publishToPrivacyCenter,\n contents,\n deleteExtraAttributeValues = false,\n classifyService = false,\n logger,\n}: {\n /** Transcend YAML */\n contents: TranscendInput;\n /** Transcend URL */\n transcendUrl: string;\n /** API key */\n auth: string;\n /** Page size */\n pageSize: number;\n /** Skip privacy center publish step */\n publishToPrivacyCenter: boolean;\n /** classify data flow service if missing */\n classifyService?: boolean;\n /** Delete attributes when syncing */\n deleteExtraAttributeValues?: boolean;\n /** Logger for reporting sync progress and errors */\n logger: LocalContext['logger'];\n}): Promise<boolean> {\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Sync to Transcend\n try {\n const result = await syncConfigurationToTranscend(contents, client, {\n pageSize,\n publishToPrivacyCenter,\n classifyService,\n deleteExtraAttributeValues,\n logger,\n });\n if (!result.success) {\n result.errors.forEach(({ resource, item, message }) => {\n logger.error(\n colors.red(`Failed to sync ${resource}${item ? ` \"${item}\"` : ''}: ${message}`),\n );\n });\n }\n return result.success;\n } catch (err) {\n logger.error(colors.red(`An unexpected error occurred syncing the schema: ${err.message}`));\n return false;\n }\n}\n\nexport interface PushCommandFlags {\n auth: string;\n file: string;\n transcendUrl: string;\n pageSize: number;\n variables: string;\n publishToPrivacyCenter: boolean;\n classifyService: boolean;\n deleteExtraAttributeValues: boolean;\n}\n\nexport async function push(\n this: LocalContext,\n {\n file = './transcend.yml',\n transcendUrl,\n auth,\n variables,\n pageSize,\n publishToPrivacyCenter,\n classifyService,\n deleteExtraAttributeValues,\n }: PushCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process);\n\n // Parse authentication as API key or path to list of API keys\n const apiKeyOrList = await validateTranscendAuth(auth, this);\n\n const vars = parseVariablesFromString(variables);\n\n // check if we are being passed a list of API keys and a list of files\n let fileList: string[];\n if (Array.isArray(apiKeyOrList) && this.fs.lstatSync(file).isDirectory()) {\n fileList = filterFileNames(this.fs.readdirSync(file)).map((filePath) =>\n path.join(file, filePath),\n );\n } else {\n fileList = file.split(',');\n }\n\n // Ensure at least one file is parsed\n if (fileList.length < 1) {\n throw new Error('No file specified!');\n }\n\n // eslint-disable-next-line array-callback-return,consistent-return\n const transcendInputs = fileList.map((filePath) => {\n // Ensure yaml file exists on disk\n if (!this.fs.existsSync(filePath)) {\n this.logger.error(\n colors.red(\n `The file path does not exist on disk: ${filePath}. You can specify the filepath using --file=./examples/transcend.yml`,\n ),\n );\n this.process.exit(1);\n } else {\n this.logger.info(colors.magenta(`Reading file \"${filePath}\"...`));\n }\n\n try {\n // Read in the yaml file and validate it's shape\n const newContents = parseTranscendYaml(\n this.fs.readFileSync(filePath, 'utf8'),\n vars,\n filePath,\n );\n this.logger.info(colors.green(`Successfully read in \"${filePath}\"`));\n return {\n content: newContents,\n name: filePath.split('/').pop()!.replace('.yml', ''),\n };\n } catch (err) {\n this.logger.error(\n colors.red(\n `The shape of your yaml file is invalid with the following errors: ${err.message}`,\n ),\n );\n this.process.exit(1);\n }\n });\n\n // process a single API key\n if (typeof apiKeyOrList === 'string') {\n // if passed multiple inputs, merge them together\n const [base, ...rest] = transcendInputs.map(({ content }) => content);\n const contents = mergeTranscendInputs(base, ...rest);\n\n // sync the configuration\n const success = await syncConfiguration({\n transcendUrl,\n auth: apiKeyOrList,\n contents,\n publishToPrivacyCenter,\n deleteExtraAttributeValues,\n pageSize,\n classifyService: !!classifyService,\n logger: this.logger,\n });\n\n // exist with error code\n if (!success) {\n this.logger.info(\n colors.red(\n `Sync encountered errors. View output above for more information, or check out ${ADMIN_DASH_INTEGRATIONS}`,\n ),\n );\n\n this.process.exit(1);\n }\n } else {\n // if passed multiple inputs, expect them to be one per instance\n if (transcendInputs.length !== 1 && transcendInputs.length !== apiKeyOrList.length) {\n throw new Error(\n 'Expected list of yml files to be equal to the list of API keys.' +\n `Got ${transcendInputs.length} YML file${\n transcendInputs.length === 1 ? '' : 's'\n } and ${apiKeyOrList.length} API key${apiKeyOrList.length === 1 ? '' : 's'}`,\n );\n }\n\n const encounteredErrors: string[] = [];\n await mapSeries(apiKeyOrList, async (apiKey, ind) => {\n const prefix = `[${ind + 1}/${apiKeyOrList.length}][${apiKey.organizationName}] `;\n this.logger.info(\n colors.magenta(`~~~\\n\\n${prefix}Attempting to push configuration...\\n\\n~~~`),\n );\n\n // use the merged contents if 1 yml passed, else use the contents that map to that organization\n const useContents =\n transcendInputs.length === 1\n ? transcendInputs[0].content\n : transcendInputs.find((input) => input.name === apiKey.organizationName)?.content;\n\n // Throw error if cannot find a yml file matching that organization name\n if (!useContents) {\n this.logger.error(\n colors.red(\n `${prefix}Failed to find transcend.yml file for organization: \"${apiKey.organizationName}\".`,\n ),\n );\n encounteredErrors.push(apiKey.organizationName);\n return;\n }\n\n const success = await syncConfiguration({\n transcendUrl,\n auth: apiKey.apiKey,\n contents: useContents,\n pageSize,\n publishToPrivacyCenter,\n deleteExtraAttributeValues,\n classifyService,\n logger: this.logger,\n });\n\n if (success) {\n this.logger.info(colors.green(`${prefix}Successfully pushed configuration!`));\n } else {\n this.logger.error(colors.red(`${prefix}Failed to sync configuration.`));\n encounteredErrors.push(apiKey.organizationName);\n }\n });\n\n if (encounteredErrors.length > 0) {\n this.logger.info(\n colors.red(\n `Sync encountered errors for \"${encounteredErrors.join(\n ',',\n )}\". View output above for more information, or check out ${ADMIN_DASH_INTEGRATIONS}`,\n ),\n );\n\n this.process.exit(1);\n }\n }\n\n // Indicate success\n this.logger.info(\n colors.green(`Successfully synced yaml file to Transcend! View at ${ADMIN_DASH_INTEGRATIONS}`),\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"impl-RgoaYjMi.mjs","names":[],"sources":["../src/commands/inventory/push/impl.ts"],"sourcesContent":["import path from 'node:path';\n\nimport { buildTranscendGraphQLClient } from '@transcend-io/sdk';\nimport { mapSeries } from '@transcend-io/utils';\nimport colors from 'colors';\n\nimport { TranscendInput } from '../../../codecs.js';\nimport { ADMIN_DASH_INTEGRATIONS } from '../../../constants.js';\nimport type { LocalContext } from '../../../context.js';\nimport { validateTranscendAuth, filterFileNames } from '../../../lib/api-keys/index.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { syncConfigurationToTranscend } from '../../../lib/graphql/index.js';\nimport { parseVariablesFromString } from '../../../lib/helpers/parseVariablesFromString.js';\nimport { mergeTranscendInputs } from '../../../lib/mergeTranscendInputs.js';\nimport { parseTranscendYaml } from '../../../lib/readTranscendYaml.js';\n\n/**\n * Sync configuration to Transcend\n *\n * @param options - Options\n * @returns True if synced successfully, false if error occurs\n */\nasync function syncConfiguration({\n transcendUrl,\n auth,\n pageSize,\n publishToPrivacyCenter,\n contents,\n deleteExtraAttributeValues = false,\n classifyService = false,\n logger,\n}: {\n /** Transcend YAML */\n contents: TranscendInput;\n /** Transcend URL */\n transcendUrl: string;\n /** API key */\n auth: string;\n /** Page size */\n pageSize: number;\n /** Skip privacy center publish step */\n publishToPrivacyCenter: boolean;\n /** classify data flow service if missing */\n classifyService?: boolean;\n /** Delete attributes when syncing */\n deleteExtraAttributeValues?: boolean;\n /** Logger for reporting sync progress and errors */\n logger: LocalContext['logger'];\n}): Promise<boolean> {\n const client = buildTranscendGraphQLClient(transcendUrl, auth);\n\n // Sync to Transcend\n try {\n const result = await syncConfigurationToTranscend(contents, client, {\n pageSize,\n publishToPrivacyCenter,\n classifyService,\n deleteExtraAttributeValues,\n logger,\n });\n if (!result.success) {\n result.errors.forEach(({ resource, item, message }) => {\n logger.error(\n colors.red(`Failed to sync ${resource}${item ? ` \"${item}\"` : ''}: ${message}`),\n );\n });\n }\n return result.success;\n } catch (err) {\n logger.error(colors.red(`An unexpected error occurred syncing the schema: ${err.message}`));\n return false;\n }\n}\n\nexport interface PushCommandFlags {\n auth: string;\n file: string;\n transcendUrl: string;\n pageSize: number;\n variables: string;\n publishToPrivacyCenter: boolean;\n classifyService: boolean;\n deleteExtraAttributeValues: boolean;\n}\n\nexport async function push(\n this: LocalContext,\n {\n file = './transcend.yml',\n transcendUrl,\n auth,\n variables,\n pageSize,\n publishToPrivacyCenter,\n classifyService,\n deleteExtraAttributeValues,\n }: PushCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process);\n\n // Parse authentication as API key or path to list of API keys\n const apiKeyOrList = await validateTranscendAuth(auth, this);\n\n const vars = parseVariablesFromString(variables);\n\n // check if we are being passed a list of API keys and a list of files\n let fileList: string[];\n if (Array.isArray(apiKeyOrList) && this.fs.lstatSync(file).isDirectory()) {\n fileList = filterFileNames(this.fs.readdirSync(file)).map((filePath) =>\n path.join(file, filePath),\n );\n } else {\n fileList = file.split(',');\n }\n\n // Ensure at least one file is parsed\n if (fileList.length < 1) {\n throw new Error('No file specified!');\n }\n\n // eslint-disable-next-line array-callback-return,consistent-return\n const transcendInputs = fileList.map((filePath) => {\n // Ensure yaml file exists on disk\n if (!this.fs.existsSync(filePath)) {\n this.logger.error(\n colors.red(\n `The file path does not exist on disk: ${filePath}. You can specify the filepath using --file=./examples/transcend.yml`,\n ),\n );\n this.process.exit(1);\n } else {\n this.logger.info(colors.magenta(`Reading file \"${filePath}\"...`));\n }\n\n try {\n // Read in the yaml file and validate it's shape\n const newContents = parseTranscendYaml(\n this.fs.readFileSync(filePath, 'utf8'),\n vars,\n filePath,\n );\n this.logger.info(colors.green(`Successfully read in \"${filePath}\"`));\n return {\n content: newContents,\n name: filePath.split('/').pop()!.replace('.yml', ''),\n };\n } catch (err) {\n this.logger.error(\n colors.red(\n `The shape of your yaml file is invalid with the following errors: ${err.message}`,\n ),\n );\n this.process.exit(1);\n }\n });\n\n // process a single API key\n if (typeof apiKeyOrList === 'string') {\n // if passed multiple inputs, merge them together\n const [base, ...rest] = transcendInputs.map(({ content }) => content);\n const contents = mergeTranscendInputs(base, ...rest);\n\n // sync the configuration\n const success = await syncConfiguration({\n transcendUrl,\n auth: apiKeyOrList,\n contents,\n publishToPrivacyCenter,\n deleteExtraAttributeValues,\n pageSize,\n classifyService: !!classifyService,\n logger: this.logger,\n });\n\n // exist with error code\n if (!success) {\n this.logger.info(\n colors.red(\n `Sync encountered errors. View output above for more information, or check out ${ADMIN_DASH_INTEGRATIONS}`,\n ),\n );\n\n this.process.exit(1);\n }\n } else {\n // if passed multiple inputs, expect them to be one per instance\n if (transcendInputs.length !== 1 && transcendInputs.length !== apiKeyOrList.length) {\n throw new Error(\n 'Expected list of yml files to be equal to the list of API keys.' +\n `Got ${transcendInputs.length} YML file${\n transcendInputs.length === 1 ? '' : 's'\n } and ${apiKeyOrList.length} API key${apiKeyOrList.length === 1 ? '' : 's'}`,\n );\n }\n\n const encounteredErrors: string[] = [];\n await mapSeries(apiKeyOrList, async (apiKey, ind) => {\n const prefix = `[${ind + 1}/${apiKeyOrList.length}][${apiKey.organizationName}] `;\n this.logger.info(\n colors.magenta(`~~~\\n\\n${prefix}Attempting to push configuration...\\n\\n~~~`),\n );\n\n // use the merged contents if 1 yml passed, else use the contents that map to that organization\n const useContents =\n transcendInputs.length === 1\n ? transcendInputs[0].content\n : transcendInputs.find((input) => input.name === apiKey.organizationName)?.content;\n\n // Throw error if cannot find a yml file matching that organization name\n if (!useContents) {\n this.logger.error(\n colors.red(\n `${prefix}Failed to find transcend.yml file for organization: \"${apiKey.organizationName}\".`,\n ),\n );\n encounteredErrors.push(apiKey.organizationName);\n return;\n }\n\n const success = await syncConfiguration({\n transcendUrl,\n auth: apiKey.apiKey,\n contents: useContents,\n pageSize,\n publishToPrivacyCenter,\n deleteExtraAttributeValues,\n classifyService,\n logger: this.logger,\n });\n\n if (success) {\n this.logger.info(colors.green(`${prefix}Successfully pushed configuration!`));\n } else {\n this.logger.error(colors.red(`${prefix}Failed to sync configuration.`));\n encounteredErrors.push(apiKey.organizationName);\n }\n });\n\n if (encounteredErrors.length > 0) {\n this.logger.info(\n colors.red(\n `Sync encountered errors for \"${encounteredErrors.join(\n ',',\n )}\". View output above for more information, or check out ${ADMIN_DASH_INTEGRATIONS}`,\n ),\n );\n\n this.process.exit(1);\n }\n }\n\n // Indicate success\n this.logger.info(\n colors.green(`Successfully synced yaml file to Transcend! View at ${ADMIN_DASH_INTEGRATIONS}`),\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{n as e}from"./buildXdiSyncEndpoint-
|
|
2
|
-
//# sourceMappingURL=impl-
|
|
1
|
+
import{n as e}from"./buildXdiSyncEndpoint-D8YJpLZd.mjs";import{t}from"./validateTranscendAuth-D6Wr1cxY.mjs";import{t as n}from"./done-input-validation-BUz-aVC5.mjs";import r from"colors";async function i({auth:i,xdiLocation:a,file:o,removeIpAddresses:s,domainBlockList:c,xdiAllowedCommands:l,transcendUrl:u}){n(this.process);let{syncGroups:d,html:f}=await e(await t(i,this),{xdiLocation:a,transcendUrl:u,removeIpAddresses:s,domainBlockList:c.length>0?c:void 0,xdiAllowedCommands:l});this.logger.info(r.green(`Successfully constructed sync endpoint for sync groups: ${JSON.stringify(d,null,2)}`)),this.fs.writeFileSync(o,f),this.logger.info(r.green(`Wrote configuration to file "${o}"!`))}export{i as buildXdiSyncEndpoint};
|
|
2
|
+
//# sourceMappingURL=impl-RuQc4nQ6.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impl-
|
|
1
|
+
{"version":3,"file":"impl-RuQc4nQ6.mjs","names":["buildXdiSyncEndpointHelper"],"sources":["../src/commands/consent/build-xdi-sync-endpoint/impl.ts"],"sourcesContent":["import colors from 'colors';\n\nimport type { LocalContext } from '../../../context.js';\nimport { validateTranscendAuth } from '../../../lib/api-keys/index.js';\nimport { doneInputValidation } from '../../../lib/cli/done-input-validation.js';\nimport { buildXdiSyncEndpoint as buildXdiSyncEndpointHelper } from '../../../lib/consent-manager/index.js';\n\nexport interface BuildXdiSyncEndpointCommandFlags {\n auth: string;\n xdiLocation: string;\n file: string;\n removeIpAddresses: boolean;\n domainBlockList: string[];\n xdiAllowedCommands: string;\n transcendUrl: string;\n}\n\nexport async function buildXdiSyncEndpoint(\n this: LocalContext,\n {\n auth,\n xdiLocation,\n file,\n removeIpAddresses,\n domainBlockList,\n xdiAllowedCommands,\n transcendUrl,\n }: BuildXdiSyncEndpointCommandFlags,\n): Promise<void> {\n doneInputValidation(this.process);\n\n // Parse authentication as API key or path to list of API keys\n const apiKeyOrList = await validateTranscendAuth(auth, this);\n\n // Build the sync endpoint\n const { syncGroups, html } = await buildXdiSyncEndpointHelper(apiKeyOrList, {\n xdiLocation,\n transcendUrl,\n removeIpAddresses,\n domainBlockList: domainBlockList.length > 0 ? domainBlockList : undefined,\n xdiAllowedCommands,\n });\n\n // Log success\n this.logger.info(\n colors.green(\n `Successfully constructed sync endpoint for sync groups: ${JSON.stringify(\n syncGroups,\n null,\n 2,\n )}`,\n ),\n );\n\n // Write to disk\n this.fs.writeFileSync(file, html);\n this.logger.info(colors.green(`Wrote configuration to file \"${file}\"!`));\n}\n"],"mappings":"2LAiBA,eAAsB,EAEpB,CACE,OACA,cACA,OACA,oBACA,kBACA,qBACA,gBAEa,CACf,EAAoB,KAAK,QAAQ,CAMjC,GAAM,CAAE,aAAY,QAAS,MAAMA,EAA2B,MAHnC,EAAsB,EAAM,KAAK,CAGgB,CAC1E,cACA,eACA,oBACA,gBAAiB,EAAgB,OAAS,EAAI,EAAkB,IAAA,GAChE,qBACD,CAAC,CAGF,KAAK,OAAO,KACV,EAAO,MACL,2DAA2D,KAAK,UAC9D,EACA,KACA,EACD,GACF,CACF,CAGD,KAAK,GAAG,cAAc,EAAM,EAAK,CACjC,KAAK,OAAO,KAAK,EAAO,MAAM,gCAAgC,EAAK,IAAI,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{g as e}from"./constants-
|
|
2
|
-
//# sourceMappingURL=impl-
|
|
1
|
+
import{g as e}from"./constants-BnIMwfNb.mjs";import{t}from"./done-input-validation-BUz-aVC5.mjs";import{h as n,n as r,p as i,r as a,t as o}from"./prompts-ClBXdELk.mjs";import{a as s,r as c,t as l}from"./deno-runtime-DV52X8-P.mjs";import{t as u}from"./run-captured-process-BXwWXuTh.mjs";import{t as d}from"./scaffold-model-BAbYTR0q.mjs";import{t as f}from"./project-plan-apply-Dvndx455.mjs";import{c as p,i as m,n as h,s as g}from"./scaffold-planning-CNv83t_v.mjs";import _ from"colors";import{CUSTOM_FUNCTION_TYPES_VERSION as v}from"@transcend-io/custom-function-types";const y={[d.Deno]:`Deno configuration`,[d.Editor]:`VS Code settings`,[d.Skill]:`Agent skill`,[d.Ci]:`GitHub Actions`},b=Object.values(d);function x(e,t,n){return!e.json&&!e.noInteractive&&!!(t&&n)}async function S(e,t,n){let r={[d.Deno]:t.deno,[d.Editor]:t.editor,[d.Skill]:t.skill,[d.Ci]:t.ci};if(!n.interactive)return b.filter(e=>r[e]===!0);let i=b.map(e=>({name:y[e],value:e,checked:r[e]!==!1}));return e.checkbox(`Choose repository setup:`,i)}async function C(y,b){t(this.process);try{let t=s(this,{...b?{directory:b}:{},...y.manifest?{manifest:y.manifest}:{}}),o=new r(this),C=x(y,this.process.stdin.isTTY,this.process.stderr.isTTY),w=await S(o,y,{interactive:C}),T=h({state:t,snapshots:a(this,t.projectRoot,m(t,{features:w})),contractVersion:v,cliVersion:e},{features:w});if(w.includes(d.Deno)){let e=await u(`deno`,[`--version`],{cwd:this.process.cwd()},this);if(e.error?.code===`ENOENT`)T.warnings.push(`Deno 2.x is not installed. Install it from ${l}`);else if(e.code!==0)T.warnings.push(`Deno was found, but its version could not be determined. Deno 2.x is required. See ${l}`);else{let t=c(e.stdout);t.level!==`compatible`&&T.warnings.push(t.message)}}y.json||this.logger.info(n(T,{cwd:this.process.cwd(),title:`Custom Function plan`,details:[{label:`Target`,path:T.targetDirectory},{label:`Manifest`,path:T.manifestPath}]}));let E=T.changes.length===0||y.dryRun;if(T.changes.length>0&&!y.dryRun)if(y.yes)E=!0;else if(C)E=await o.confirm(`Apply this complete plan?`,!0);else throw Error(`The plan requires approval in a non-interactive invocation. Review with --dryRun, then pass --yes.`);E&&!y.dryRun&&T.changes.length>0&&await f(this,T);let D=E&&!y.dryRun&&T.changes.length>0,O=E&&!y.dryRun,k=p({targetDirectory:i(this.process.cwd(),t.targetDirectory),manifestPath:i(this.process.cwd(),t.manifestPath),cliVersion:e,hasSkill:O&&w.includes(d.Skill),hasGithubWorkflow:O&&w.includes(d.Ci)&&!!(t.repositoryRoot&&t.usesGithub)}),A=g(T,{applied:D,dryRun:y.dryRun,cwd:this.process.cwd(),aiHandoff:k});if(y.json){this.process.stdout.write(`${JSON.stringify(A)}\n`);return}if(y.dryRun){this.logger.info(_.yellow(`Dry run complete. No changes were written.`));return}if(!E){this.logger.info(_.yellow(`No changes applied.`));return}if(T.changes.length===0){this.logger.info(_.green(`Custom Function project is already initialized.`));return}this.logger.info(_.green(`Custom Function project initialized.`)),T.nextSteps.length>0&&(this.logger.info(`\n${_.bold(`Next steps`)}`),T.nextSteps.forEach(e=>this.logger.info(e))),this.logger.info(`\n${_.bold(`AI handoff — paste into your coding agent`)}`),this.logger.info(k)}catch(e){throw e instanceof o&&this.process.exit(130),e}}export{C as init};
|
|
2
|
+
//# sourceMappingURL=impl-Yb5jtD4V.mjs.map
|