@team-semicolon/semicolony-cli 4.18.62 → 4.18.64
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/bundle.js
CHANGED
|
@@ -2965,7 +2965,7 @@ Spec: semo-ops docs/superpowers/specs/2026-07-20-semo-semicolony-local-separatio
|
|
|
2965
2965
|
`)}function S4n(t){let e=t._warnings??[];return e.length>0?{id:"config",label:"config.toml forward-compat",level:"warn",detail:e.join("; ")}:t._source?.startsWith("<default:")?{id:"config",label:"config.toml",level:"warn",detail:`\uC5C6\uC74C \u2014 \uAE30\uBCF8\uAC12(profile=${t.profile}) \uC0AC\uC6A9 \uC911. \`semicolony init\` \uC73C\uB85C \uBCF8\uC778 \uD658\uACBD \uACE0\uC815 \uAD8C\uC7A5`}:{id:"config",label:`config.toml (schema ${t.schema_version}, profile=${t.profile})`,level:"ok",detail:t._source}}function Q4n(){let t=[];for(let e of[AA(),hA(),sv()])Bs.existsSync(e)||t.push(e);return t.length>0?{id:"layout",label:"SemiColony 3-layer \uB514\uB809\uD130\uB9AC",level:"fail",detail:`\uB204\uB77D: ${t.join(", ")} \u2014 \`semicolony init\` \uC2E4\uD589 \uD544\uC694`}:{id:"layout",label:"SemiColony 3-layer \uB514\uB809\uD130\uB9AC",level:"ok"}}function Jnt(t,e,n){let r=`sqlite:${t}`,i=`SQLite ${t} DB`;if(!e)return{id:r,label:i,level:"skip",detail:"driver \uAC00 sqlite \uAC00 \uC544\uB2D8"};if(!Bs.existsSync(e))return{id:r,label:i,level:"fail",detail:`${e} \uC5C6\uC74C \u2014 \`semicolony migrate-sqlite --target ${t}\` \uC2E4\uD589`};let s=ks.join(n,t);if(!Bs.existsSync(s))return{id:r,label:i,level:"warn",detail:`migrations-sqlite/${t} \uB514\uB809\uD130\uB9AC \uC5C6\uC74C`};let o=Bs.readdirSync(s).filter(c=>c.endsWith(".sql")).map(c=>c.replace(/\.sql$/,"")),a=new gle.default(e,{readonly:!0});try{if(!a.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='schema_migrations'").get())return{id:r,label:i,level:"warn",detail:`schema_migrations \uD14C\uC774\uBE14 \uC5C6\uC74C \u2014 \`semicolony migrate-sqlite --target ${t}\``};let l=a.prepare("SELECT version FROM schema_migrations").all().map(A=>A.version),u=new Set(l),d=o.filter(A=>!u.has(A));return d.length>0?{id:r,label:i,level:"warn",detail:`\uBBF8\uC801\uC6A9 ${d.length}: ${d.join(", ")} \u2014 \`semicolony migrate-sqlite --target ${t}\``}:{id:r,label:i,level:"ok",detail:`${e} (applied ${l.length})`}}finally{a.close()}}async function D4n(t,e,n=fetch){let r=(t??process.env.OLLAMA_HOST??"http://127.0.0.1:11434").replace(/\/$/,""),i="ollama";try{let s=await n(`${r}/api/tags`);if(!s.ok)return[{id:i,label:"Ollama \uC11C\uBC84",level:"fail",detail:`HTTP ${s.status} from ${r}`}];let a=((await s.json()).models??[]).map(l=>l.name??"").filter(Boolean),c=[{id:i,label:`Ollama \uC11C\uBC84 (${r})`,level:"ok",detail:`${a.length}\uAC1C \uBAA8\uB378`}];for(let l of e){let u=a.some(d=>d===l||d.startsWith(`${l}:`));c.push({id:`ollama:model:${l}`,label:`Ollama \uBAA8\uB378 ${l}`,level:u?"ok":"fail",detail:u?void 0:`\`ollama pull ${l}\` \uD544\uC694`})}return c}catch(s){return[{id:i,label:`Ollama \uC11C\uBC84 (${r})`,level:"fail",detail:`\uB3C4\uB2EC \uBD88\uAC00: ${s.message} \u2014 \`brew install ollama && ollama serve\``},...e.map(o=>({id:`ollama:model:${o}`,label:`Ollama \uBAA8\uB378 ${o}`,level:"skip",detail:"ollama \uC11C\uBC84 \uBBF8\uB3C4\uB2EC"}))]}}function R4n(t,e=process.env){let n=[];if(t.includes("discord")){let r=!!(e.DISCORD_TOKEN||e.DISCORD_BOT_TOKEN);n.push({id:"messaging:discord",label:"Discord \uBD07 \uD1A0\uD070 (DISCORD_TOKEN)",level:r?"ok":"fail",detail:r?void 0:"Discord Developer Portal \uC5D0\uC11C bot token \uBC1C\uAE09 \uD6C4 \uD658\uACBD\uBCC0\uC218 \uC124\uC815"})}if(t.includes("slack")){let r=!!(e.SLACK_BOT_TOKEN&&e.SLACK_APP_TOKEN);n.push({id:"messaging:slack",label:"Slack \uD1A0\uD070 (SLACK_BOT_TOKEN + SLACK_APP_TOKEN)",level:r?"ok":"fail",detail:r?void 0:"bot token (xoxb-) + app token (xapp-) \uC591\uCABD \uD544\uC694"})}return n}function M4n(t,e=process.env){let n=t.execution.target;if(n==="anthropic-api"){let r=t.execution.api_key_env??"ANTHROPIC_API_KEY",i=!!e[r];return{id:"execution",label:`execution=anthropic-api (${r})`,level:i?"ok":"fail",detail:i?void 0:`\uD658\uACBD\uBCC0\uC218 ${r} \uC124\uC815 \uD544\uC694`}}if(n==="openai"||n==="gemini"){let r=t.execution.api_key_env??(n==="openai"?"OPENAI_API_KEY":"GEMINI_API_KEY"),i=!!e[r];return{id:"execution",label:`execution=${n} (${r})`,level:i?"ok":"fail",detail:i?void 0:`\uD658\uACBD\uBCC0\uC218 ${r} \uC124\uC815 \uD544\uC694`}}return n==="claude-code"?{id:"execution",label:"execution=claude-code",level:"ok",detail:"\uC138\uC158\uD480\uC5D0\uC11C \uAD00\uB9AC\uB428 (\uBCC4\uB3C4 preflight \uC5C6\uC74C)"}:n==="ollama"||n==="mlx"?{id:"execution",label:`execution=${n}`,level:"ok",detail:"ollama \uCCB4\uD06C \uD56D\uBAA9 \uCC38\uC870"}:{id:"execution",label:`execution=${n}`,level:"warn",detail:"\uC54C \uC218 \uC5C6\uB294 \uD0C0\uAE43"}}function T4n(t){let e="seats",n="bot seat pool";if(!t)return{id:e,label:n,level:"skip",detail:"ops \uAC00 sqlite \uAC00 \uC544\uB2D8"};if(!Bs.existsSync(t))return{id:e,label:n,level:"skip",detail:"ops DB \uC5C6\uC74C"};let r=new gle.default(t,{readonly:!0});try{if(!r.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='bot_seats'").get())return{id:e,label:n,level:"skip",detail:"bot_seats \uD14C\uC774\uBE14 \uC5C6\uC74C"};let s=r.prepare("SELECT COUNT(*) AS n FROM bot_seats").get();if(s.n===0)return{id:e,label:n,level:"warn",detail:"\uBE48 pool \u2014 `semicolony seats add` \uB85C \uCD5C\uC18C 1\uAC1C \uD655\uBCF4 \uD544\uC694 (bot \uC0DD\uC131 \uC2DC)"};let o=r.prepare("SELECT COUNT(*) AS n FROM bot_seats WHERE status='available'").get();return o.n===0?{id:e,label:n,level:"warn",detail:`${s.n}\uAC1C seat \uBAA8\uB450 \uD560\uB2F9\uB428 \u2014 \uC2E0\uADDC bot \uC0DD\uC131 \uC2DC \`semicolony seats add\` \uB610\uB294 \uAE30\uC874 \uBD07 retire`}:{id:e,label:n,level:"ok",detail:`available ${o.n}/${s.n}`}}finally{r.close()}}function O4n(t){let e="kernel-skills",n="kernel skills \uBA38\uD2F0\uB9AC\uC5BC\uB77C\uC774\uC988";if(t.length===0)return{id:e,label:n,level:"skip",detail:"BUILTIN_KERNEL_SKILLS \uC5C6\uC74C"};let r=ks.join(AA(),"skills");if(!Bs.existsSync(r))return{id:e,label:n,level:"fail",detail:`${r} \uC5C6\uC74C \u2014 \`semicolony update\` \uC2E4\uD589 \uD544\uC694`};let i=[];for(let s of t){let o=ks.join(r,s,"SKILL.md");Bs.existsSync(o)||i.push(s)}return i.length>0?{id:e,label:n,level:"fail",detail:`\uB204\uB77D: ${i.join(", ")} \u2014 \`semicolony update\` \uC2E4\uD589`}:{id:e,label:n,level:"ok",detail:`${t.length}\uAC1C`}}function N4n(t){let e="embedding";if(!t.embedding)return{id:e,label:"embedding provider",level:"warn",detail:"\uBBF8\uC124\uC815 \u2014 FTS5 \uD0A4\uC6CC\uB4DC \uAC80\uC0C9\uB9CC \uAC00\uB2A5 (\uD55C\uAD6D\uC5B4 \uC758\uBBF8 \uAC80\uC0C9 \uC5C6\uC74C)"};if(t.embedding.provider==="none")return{id:e,label:"embedding=none",level:"ok",detail:"FTS5 \uC804\uC6A9"};if(t.embedding.provider==="openai"){let n=t.embedding.api_key_env??"OPENAI_API_KEY",r=!!process.env[n];return{id:e,label:`embedding=openai (${n})`,level:r?"ok":"fail",detail:r?void 0:`${n} \uD658\uACBD\uBCC0\uC218 \uD544\uC694`}}return{id:e,label:`embedding=${t.embedding.provider}`,level:"ok",detail:t.embedding.model??void 0}}function nrt(t,e={}){let n={ok:0,warn:0,fail:0,skip:0};for(let i of t)n[i.level]+=1;let r=n.fail>0||e.strict&&n.warn>0?1:0;return{checks:t,summary:n,exitCode:r}}function rrt(t){return Bs.existsSync(t)?Bs.readFileSync(t,"utf8"):null}function P4n(t){let e=rrt(t.filePath);if(!e)return{id:"worker:env-file",label:"worker env file",level:"warn",detail:`${t.filePath} \uC5C6\uC74C \u2014 ${qA(t.surface)} worker setup \uC2E4\uD589 \uD544\uC694`};let n=[];return!e.includes(`${t.gatewayUrlEnv}=`)&&!e.includes("SEMICOLONY_KB_GATEWAY_URL=")&&n.push("gateway url env"),!e.includes(`${t.tokenEnv}=`)&&!e.includes("SEMICOLONY_WORKER_KB_TOKEN=")&&n.push("worker token env"),e.includes("DATABASE_URL=")&&n.push("DATABASE_URL must not be stored"),n.length>0?{id:"worker:env-file",label:"worker env file",level:"warn",detail:`\uBD88\uC644\uC804: ${n.join(", ")} \u2014 token \uAC12\uC740 \uCD9C\uB825\uD558\uC9C0 \uC54A\uC74C`}:{id:"worker:env-file",label:"worker env file",level:"ok",detail:`${t.filePath} (token redacted)`}}function F4n(t){let e=rrt(t.filePath);if(!e)return{id:"worker:mcp-config",label:"read-only KB MCP config",level:"warn",detail:`${t.filePath} \uC5C6\uC74C \u2014 \uD544\uC694\uD558\uBA74 ${qA(t.surface)} worker setup --with-kb-mcp`};try{let n=JSON.parse(e),r=JSON.stringify(n),i=[];return!r.includes(t.gatewayUrlEnv)&&!r.includes("SEMICOLONY_KB_GATEWAY_URL")&&i.push("gateway url env reference"),!r.includes(t.tokenEnv)&&!r.includes("SEMICOLONY_WORKER_KB_TOKEN")&&i.push("worker token env reference"),r.includes("wck_")&&i.push("plaintext worker token must not be embedded"),i.length>0?{id:"worker:mcp-config",label:"read-only KB MCP config",level:"warn",detail:`\uBD88\uC644\uC804: ${i.join(", ")}`}:{id:"worker:mcp-config",label:"read-only KB MCP config",level:"ok",detail:t.filePath}}catch(n){return{id:"worker:mcp-config",label:"read-only KB MCP config",level:"warn",detail:`JSON \uD30C\uC2F1 \uC2E4\uD328: ${n.message}`}}}function L4n(t){if(!Bs.existsSync(t))return{id:"worker:state-file",label:"worker local state",level:"warn",detail:`${t} \uC5C6\uC74C \u2014 worker setup \uC7AC\uC2E4\uD589 \uC2DC \uC0DD\uC131`};try{let e=ud(t);if(!e)return{id:"worker:state-file",label:"worker local state",level:"warn",detail:"state is empty"};let n=[];e.worker_id||n.push("worker_id"),e.device_id||n.push("device_id"),e.profile_id||n.push("profile_id"),e.installed_profile_version||n.push("installed_profile_version");let r=JSON.stringify(e);if((r.includes("wck_")||r.includes("DATABASE_URL"))&&n.push("secret material must not be stored"),n.length>0)return{id:"worker:state-file",label:"worker local state",level:"warn",detail:`\uBD88\uC644\uC804: ${n.join(", ")}`};let i=KG(e);return i!=="current"?{id:"worker:state-file",label:"worker local state",level:"warn",detail:`${e.worker_id}/${e.device_id} capability=${i}; \uB85C\uCEEC snapshot\uC740 \uAD8C\uD55C \uADFC\uAC70\uAC00 \uC544\uB2C8\uBA70 protected command\uAC00 DB lease\uB97C \uC7AC\uC870\uD68C\uD574\uC57C \uD568`}:{id:"worker:state-file",label:"worker local state",level:"ok",detail:`${e.worker_id}/${e.device_id} profile=${e.profile_id}@${e.installed_profile_version}; capability snapshot current (\uC124\uBA85\uC6A9 cache)`}}catch(e){return{id:"worker:state-file",label:"worker local state",level:"warn",detail:`JSON \uD30C\uC2F1 \uC2E4\uD328: ${e.message}`}}}function oT(t,e){return e.source!=="legacy"?t:{...t,detail:`${t.detail??e.filePath} (read-only legacy fallback)`}}function HH(t,e,n){return{id:t,label:e,level:"warn",detail:`${n.source} worker file rejected: ${n.reason} (${n.filePath})`}}function U4n(t,e){let n=jo(t),r=Uc(t,n.releaseState,Ll(t,"release-state.json"));if(r.status==="rejected")return{check:HH("worker:release-state","worker local release state",r),state:null,readable:null};if(r.status==="absent")return{check:{id:"worker:release-state",label:"worker local release state",level:e?"skip":"warn",detail:e?"release activation in progress; state is persisted after doctor passes":`${n.releaseState} \uC5C6\uC74C \u2014 semo worker update`},state:null,readable:null};try{let i=ew(r.filePath);if(!i)return{check:{id:"worker:release-state",label:"worker local release state",level:"warn",detail:"release state is empty"},state:null,readable:r};let s=Number.isNaN(Date.parse(i.applied_at))||Number.isNaN(Date.parse(i.last_doctor_at));return{check:oT({id:"worker:release-state",label:"worker local release state",level:s?"warn":"ok",detail:s?"release state timestamps are invalid":`${i.applied_release_id}@${i.applied_release_version}`},r),state:i,readable:r}}catch(i){return{check:oT({id:"worker:release-state",label:"worker local release state",level:"warn",detail:`invalid release state: ${i.message}`},r),state:null,readable:r}}}function Knt(t){let e="";try{let a=Bs.lstatSync(t);if(!a.isFile()||a.isSymbolicLink())throw new Error("managed context target is not a regular file");e=Bs.readFileSync(t,"utf8")}catch(a){if(a.code!=="ENOENT")throw a}let n=/<!-- SEMO_OPS_WORKER_RELEASE:([^:\r\n>]+):(BEGIN|END) -->/g,r="<!-- SEMO_OPS_WORKER_RELEASE:",i=[...e.matchAll(n)];if(i.length!==e.split(r).length-1)throw new Error("invalid managed context marker");let s=new Map;for(let a of i){let c=a[1],l=a[2],u=s.get(c)??{};if(l==="BEGIN"){if(u.begin)throw new Error(`managed context ${c} has duplicate markers`);u.begin={index:a.index,length:a[0].length}}else{if(u.end)throw new Error(`managed context ${c} has duplicate markers`);u.end={index:a.index,length:a[0].length}}s.set(c,u)}let o=new Map;for(let[a,c]of s){if(!c.begin||!c.end||c.begin.index>=c.end.index)throw new Error(`managed context ${a} has unpaired markers`);let l=c.begin.index+c.begin.length;e.startsWith(`\r
|
|
2966
2966
|
`,l)?l+=2:e.startsWith(`
|
|
2967
2967
|
`,l)&&(l+=1),o.set(a,{content:e.slice(l,c.end.index)})}return o}function ple(t){return(0,ert.createHash)("sha256").update(t).digest("hex")}function znt(t,e){return ple(t)===e?!0:t.endsWith(`
|
|
2968
|
-
`)&&ple(t.slice(0,-1))===e}function Znt(t,e){let n=`context:${e}:`;return new Map(Object.entries(t.managed_target_digests).filter(([r])=>r.startsWith(n)).map(([r,i])=>[r.slice(n.length),i]))}function GH(t,e){return t.size===e.size&&[...t.keys()].every(n=>e.has(n))}function q4n(t,e,n){try{let r=Knt(ks.join(t,".claude","CLAUDE.md")),i=Knt(ks.join(t,".codex","AGENTS.md"));if(!GH(r,i))return{id:"worker:managed-context-parity",label:"managed Claude/Codex context parity",level:"warn",detail:"managed context blocks must be paired in both harnesses"};if(n)return{id:"worker:managed-context-parity",label:"managed Claude/Codex context parity",level:"ok",detail:`${r.size} paired managed context block(s); activation in progress`};if(!e)return{id:"worker:managed-context-parity",label:"managed Claude/Codex context parity",level:"warn",detail:"no valid local release state is available for managed digest validation"};let s=Znt(e,"claude"),o=Znt(e,"codex");if(!GH(s,o)||!GH(r,s)||!GH(i,o))return{id:"worker:managed-context-parity",label:"managed Claude/Codex context parity",level:"warn",detail:"managed context ids do not match the local release state in both harnesses"};for(let[a,c]of r){if(!znt(c.content,s.get(a)))return{id:"worker:managed-context-parity",label:"managed Claude/Codex context parity",level:"warn",detail:`Claude managed context ${a} digest drift`};if(!znt(i.get(a).content,o.get(a)))return{id:"worker:managed-context-parity",label:"managed Claude/Codex context parity",level:"warn",detail:`Codex managed context ${a} digest drift`}}return{id:"worker:managed-context-parity",label:"managed Claude/Codex context parity",level:"ok",detail:`${r.size} paired managed context block(s) match local release state`}}catch(r){return{id:"worker:managed-context-parity",label:"managed Claude/Codex context parity",level:"warn",detail:r.message}}}function j4n(t,e){let n=/^skill:(claude|agents):([a-z0-9][a-z0-9-]*)$/.exec(e);return n?ks.join(t,n[1]==="claude"?".claude":".agents","skills",n[2],"SKILL.md"):e==="asset:shared-script:feedback-capture.py"?ks.join(t,".semo","shared","scripts","feedback-capture.py"):null}function $4n(t,e){let n=ks.resolve(t),r=ks.resolve(e),i=ks.relative(n,r);if(i===""||i.startsWith("..")||ks.isAbsolute(i))throw new Error("managed target escapes the worker home");let s=n;for(let a of i.split(ks.sep))if(s=ks.join(s,a),Bs.lstatSync(s).isSymbolicLink())throw new Error("managed target traverses a symlink");let o=Bs.lstatSync(r);if(!o.isFile()||o.isSymbolicLink())throw new Error("managed target is not a regular file");return{content:Bs.readFileSync(r),mode:o.mode&511}}function G4n(t,e,n){let r={id:"worker:managed-targets",label:"managed worker release files"};if(n)return{...r,level:"skip",detail:"activation in progress"};if(!e)return{...r,level:"warn",detail:"no valid local release state is available for managed file validation"};let i=Object.entries(e.managed_target_digests).filter(([s])=>!s.startsWith("context:"));for(let[s,o]of i){let a=j4n(t,s);if(!a)return{...r,level:"warn",detail:`unknown managed target key: ${s}`};try{let c=$4n(t,a);if(ple(c.content)!==o)return{...r,level:"warn",detail:`${s} digest drift`};let l=e.managed_target_modes?.[s]??(s.startsWith("skill:")?"0644":void 0);if(!l)return{...r,level:"warn",detail:`${s} expected mode is not recorded`};if(c.mode!==Number.parseInt(l,8))return{...r,level:"warn",detail:`${s} mode drift (expected ${l})`}}catch(c){let l=c.code;return{...r,level:"warn",detail:`${s} ${l==="ENOENT"?"is missing":c.message}`}}}return{...r,level:"ok",detail:`${i.length} managed skill/asset file(s) match local release state`}}function H4n(t,e){return t?{id:"worker:last-update-doctor",label:"latest successful worker update doctor",level:t.last_doctor_status==="pass"&&!Number.isNaN(Date.parse(t.last_doctor_at))?"ok":"warn",detail:`${t.last_doctor_status} at ${t.last_doctor_at}`}:{id:"worker:last-update-doctor",label:"latest successful worker update doctor",level:e?"skip":"warn",detail:e?"first release activation is awaiting doctor completion":"no successful worker release update is recorded"}}function W4n(t,e,n={}){return new Promise(r=>{(0,Xnt.execFile)(t,e,{env:n.env??process.env,timeout:n.timeoutMs??8e3,windowsHide:!0},(i,s,o)=>{let a=i?.code;r({exitCode:typeof a=="number"?a:i?1:0,stdout:String(s??""),stderr:String(o??"")})})})}async function V4n(t,e){let n=await e(t,["--version"],{timeoutMs:5e3});if(n.exitCode!==0)return{id:`worker:cli:${t}`,label:`${t} CLI binary`,level:"warn",detail:`${t} --version \uC2E4\uD328 \u2014 PATH/global install \uD655\uC778 \uD544\uC694`};let r=n.stdout.split(/\r?\n/).find(Boolean)?.slice(0,120)??"version ok";return{id:`worker:cli:${t}`,label:`${t} CLI binary`,level:"ok",detail:r}}async function Y4n(t,e,n={}){let r=[];r.push(S4n(t)),r.push(Q4n()),t.kb.driver==="sqlite"&&r.push(Jnt("kb",t.kb.sqlite_path,e)),t.ops.driver==="sqlite"&&(r.push(Jnt("ops",t.ops.sqlite_path,e)),r.push(T4n(t.ops.sqlite_path))),r.push(...R4n(t.messaging.sources)),r.push(M4n(t)),r.push(N4n(t));try{let c=((await Promise.resolve().then(()=>(rs(),kA))).BUILTIN_KERNEL_SKILLS??[]).map(l=>l.id);r.push(O4n(c))}catch{r.push({id:"kernel-skills",label:"kernel skills \uBA38\uD2F0\uB9AC\uC5BC\uB77C\uC774\uC988",level:"skip",detail:"@team-semicolon/semicolony-common \uBBF8\uB85C\uB529"})}let i=[],s=t.execution.target==="ollama"?t.execution.ollama_host:t.embedding?.host;return(t.execution.target==="ollama"||t.embedding?.provider==="ollama")&&(t.execution.target==="ollama"&&t.execution.model&&i.push(t.execution.model),t.embedding?.provider==="ollama"&&t.embedding.model&&i.push(t.embedding.model),r.push(...await D4n(s,i,n.fetchImpl))),nrt(r,{strict:n.strict})}async function aT(t={}){let e=t.env??process.env,n=t.homeDir??e.HOME??trt.homedir(),r=t.surface??"semicolony",i=[],s=by(e,r),o=Ey(e,{surface:r}),a=s.value?.replace(/\/$/,""),c=o.value,l=s.envName??XE(r),u=o.envName??bx(r),d=jo(n),A=t.updateInProgress===!0;if(!a||!c){let E=[a?null:s.candidates.join(" or "),c?null:o.candidates.join(" or ")].filter(Boolean);i.push({id:"worker:gateway-env",label:"worker KB gateway env",level:"fail",detail:`\uB204\uB77D: ${E.join(", ")} \u2014 Semi\uC5D0\uAC8C worker token \uBC1C\uAE09\uC744 \uC694\uCCAD\uD558\uC138\uC694`})}else c.startsWith("wck_")?i.push({id:"worker:gateway-env",label:"worker KB gateway env",level:"ok",detail:`${a}${s.envName?` (${s.envName})`:""}`}):i.push({id:"worker:gateway-env",label:"worker KB gateway env",level:"fail",detail:`${o.envName??"worker token"} \uC740 worker-scoped \`wck_\` \uD1A0\uD070\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4`});i.push({id:"worker:direct-db",label:"worker direct DB env",level:e.DATABASE_URL?.trim()?"warn":"ok",detail:e.DATABASE_URL?.trim()?"DATABASE_URL \uC124\uC815\uB428 \u2014 worker profile\uC740 \uAE30\uBCF8\uC801\uC73C\uB85C gateway\uB9CC \uC0AC\uC6A9\uD574\uC57C \uD569\uB2C8\uB2E4":"DATABASE_URL unset"});let h=Uc(n,d.env,Ll(n,".env")),f=Uc(n,d.kbMcp,Ll(n,"kb-mcp.json")),g=Uc(n,d.workerState,Ll(n,"worker-state.json")),m=null;if(g.status==="rejected")i.push(HH("worker:state-file","worker local state",g));else if(g.status==="absent")i.push({id:"worker:state-file",label:"worker local state",level:"warn",detail:`${d.workerState} \uC5C6\uC74C \u2014 worker setup \uC7AC\uC2E4\uD589 \uC2DC \uC0DD\uC131`});else{let E=oT(L4n(g.filePath),g);i.push(A&&E.level==="warn"&&E.detail?.includes("capability=")?{...E,level:"ok",detail:`${E.detail}; release activation in progress`}:E);try{m=ud(g.filePath)}catch{m=null}}if(h.status==="rejected"?i.push(HH("worker:env-file","worker env file",h)):h.status==="absent"?i.push({id:"worker:env-file",label:"worker env file",level:"warn",detail:`${d.env} \uC5C6\uC74C \u2014 ${qA(r)} worker setup \uC2E4\uD589 \uD544\uC694`}):i.push(oT(P4n({filePath:h.filePath,surface:r,gatewayUrlEnv:l,tokenEnv:u}),h)),f.status==="rejected")i.push(HH("worker:mcp-config","read-only KB MCP config",f));else if(f.status==="absent"){let E=m?.tool_adapters_enabled.includes("kb-mcp")??!1;i.push({id:"worker:mcp-config",label:"read-only KB MCP config",level:E?"warn":"skip",detail:E?`${d.kbMcp} \uC5C6\uC74C \u2014 ${qA(r)} worker setup --with-kb-mcp`:"kb-mcp adapter is not enabled; config is optional"})}else i.push(oT(F4n({filePath:f.filePath,surface:r,gatewayUrlEnv:l,tokenEnv:u}),f));i.push(...fle(n));let y=U4n(n,A);i.push(y.check),i.push(q4n(n,y.state,A)),i.push(G4n(n,y.state,A)),i.push(H4n(y.state,A));let b=!!(a&&c?.startsWith("wck_")),w=[{id:"worker:kb:hive-service",label:"KB read smoke: hive-service",domain:"semicolon",key:"glossary",subKey:"hive-service"},{id:"worker:kb:setup-guide",label:"KB read smoke: worker setup guide",domain:"semicolon",key:"process",subKey:"worker-environment-setup-via-semi"}];for(let E of w){if(!b){i.push({id:E.id,label:E.label,level:"skip",detail:"worker gateway env \uBBF8\uCDA9\uC871"});continue}try{await wy({baseUrl:a,token:c},E.domain,E.key,E.subKey,t.fetchImpl),i.push({id:E.id,label:E.label,level:"ok",detail:`${E.domain}/${E.key}${E.subKey?`/${E.subKey}`:""}`})}catch(C){i.push({id:E.id,label:E.label,level:"fail",detail:C.message.slice(0,240)})}}if(t.runExternalChecks){let E=t.commandRunner??W4n;i.push(await V4n("semo",E))}return nrt(i,{strict:t.strict})}function J4n(t){return t==="ok"?Vc.default.green("\u2713"):t==="warn"?Vc.default.yellow("\u26A0"):t==="fail"?Vc.default.red("\u2717"):Vc.default.gray("\u25CB")}function WH(t){let e=[""];for(let r of t.checks)e.push(` ${J4n(r.level)} ${r.label}${r.detail?Vc.default.gray(` \u2014 ${r.detail}`):""}`);e.push("");let n=t.summary;if(e.push(` ${Vc.default.bold("\uC694\uC57D")}: ${Vc.default.green(`${n.ok} ok`)} \xB7 ${Vc.default.yellow(`${n.warn} warn`)} \xB7 ${Vc.default.red(`${n.fail} fail`)} \xB7 ${Vc.default.gray(`${n.skip} skip`)}`),t.exitCode===0&&n.fail===0){let r=t.checks.some(i=>i.id.startsWith("worker:"));e.push(" "+Vc.default.green(r?"\u2192 Worker profile \uC900\uBE44 \uC644\uB8CC":"\u2192 Personal \uC2A4\uD0DD \uC900\uBE44 \uC644\uB8CC"))}else n.fail>0&&e.push(" "+Vc.default.red("\u2192 \uBE14\uB85C\uCEE4 \uC788\uC74C \u2014 \uC704 fail \uD56D\uBAA9 \uD574\uACB0 \uD6C4 \uC7AC\uC2E4\uD589"));return e.push(""),e.join(`
|
|
2968
|
+
`)&&ple(t.slice(0,-1))===e}function Znt(t,e){let n=`context:${e}:`;return new Map(Object.entries(t.managed_target_digests).filter(([r])=>r.startsWith(n)).map(([r,i])=>[r.slice(n.length),i]))}function GH(t,e){return t.size===e.size&&[...t.keys()].every(n=>e.has(n))}function q4n(t,e,n){try{let r=Knt(ks.join(t,".claude","CLAUDE.md")),i=Knt(ks.join(t,".codex","AGENTS.md"));if(!GH(r,i))return{id:"worker:managed-context-parity",label:"managed Claude/Codex context parity",level:"warn",detail:"managed context blocks must be paired in both harnesses"};if(n)return{id:"worker:managed-context-parity",label:"managed Claude/Codex context parity",level:"ok",detail:`${r.size} paired managed context block(s); activation in progress`};if(!e)return{id:"worker:managed-context-parity",label:"managed Claude/Codex context parity",level:"warn",detail:"no valid local release state is available for managed digest validation"};let s=Znt(e,"claude"),o=Znt(e,"codex");if(!GH(s,o)||!GH(r,s)||!GH(i,o))return{id:"worker:managed-context-parity",label:"managed Claude/Codex context parity",level:"warn",detail:"managed context ids do not match the local release state in both harnesses"};for(let[a,c]of r){if(!znt(c.content,s.get(a)))return{id:"worker:managed-context-parity",label:"managed Claude/Codex context parity",level:"warn",detail:`Claude managed context ${a} digest drift`};if(!znt(i.get(a).content,o.get(a)))return{id:"worker:managed-context-parity",label:"managed Claude/Codex context parity",level:"warn",detail:`Codex managed context ${a} digest drift`}}return{id:"worker:managed-context-parity",label:"managed Claude/Codex context parity",level:"ok",detail:`${r.size} paired managed context block(s) match local release state`}}catch(r){return{id:"worker:managed-context-parity",label:"managed Claude/Codex context parity",level:"warn",detail:r.message}}}function j4n(t,e){let n=/^skill:(claude|agents):([a-z0-9][a-z0-9-]*)$/.exec(e);return n?ks.join(t,n[1]==="claude"?".claude":".agents","skills",n[2],"SKILL.md"):e==="asset:shared-script:feedback-capture.py"?ks.join(t,".semo","shared","scripts","feedback-capture.py"):null}function $4n(t,e){let n=ks.resolve(t),r=ks.resolve(e),i=ks.relative(n,r);if(i===""||i.startsWith("..")||ks.isAbsolute(i))throw new Error("managed target escapes the worker home");let s=n;for(let a of i.split(ks.sep))if(s=ks.join(s,a),Bs.lstatSync(s).isSymbolicLink())throw new Error("managed target traverses a symlink");let o=Bs.lstatSync(r);if(!o.isFile()||o.isSymbolicLink())throw new Error("managed target is not a regular file");return{content:Bs.readFileSync(r),mode:o.mode&511}}function G4n(t,e,n){let r={id:"worker:managed-targets",label:"managed worker release files"};if(n)return{...r,level:"skip",detail:"activation in progress"};if(!e)return{...r,level:"warn",detail:"no valid local release state is available for managed file validation"};let i=Object.entries(e.managed_target_digests).filter(([s])=>!s.startsWith("context:"));for(let[s,o]of i){let a=j4n(t,s);if(!a)return{...r,level:"warn",detail:`unknown managed target key: ${s}`};try{let c=$4n(t,a);if(ple(c.content)!==o)return{...r,level:"warn",detail:`${s} digest drift`};let l=e.managed_target_modes?.[s]??(s.startsWith("skill:")?"0644":void 0);if(!l)return{...r,level:"warn",detail:`${s} expected mode is not recorded`};if(c.mode!==Number.parseInt(l,8))return{...r,level:"warn",detail:`${s} mode drift (expected ${l})`}}catch(c){let l=c.code;return{...r,level:"warn",detail:`${s} ${l==="ENOENT"?"is missing":c.message}`}}}return{...r,level:"ok",detail:`${i.length} managed skill/asset file(s) match local release state`}}function H4n(t,e){return t?{id:"worker:last-update-doctor",label:"latest successful worker update doctor",level:t.last_doctor_status==="pass"&&!Number.isNaN(Date.parse(t.last_doctor_at))?"ok":"warn",detail:`${t.last_doctor_status} at ${t.last_doctor_at}`}:{id:"worker:last-update-doctor",label:"latest successful worker update doctor",level:e?"skip":"warn",detail:e?"first release activation is awaiting doctor completion":"no successful worker release update is recorded"}}function W4n(t,e,n={}){return new Promise(r=>{(0,Xnt.execFile)(t,e,{env:n.env??process.env,timeout:n.timeoutMs??8e3,windowsHide:!0},(i,s,o)=>{let a=i?.code;r({exitCode:typeof a=="number"?a:i?1:0,stdout:String(s??""),stderr:String(o??"")})})})}async function V4n(t,e){let n=await e(t,["--version"],{timeoutMs:5e3});if(n.exitCode!==0)return{id:`worker:cli:${t}`,label:`${t} CLI binary`,level:"warn",detail:`${t} --version \uC2E4\uD328 \u2014 PATH/global install \uD655\uC778 \uD544\uC694`};let r=n.stdout.split(/\r?\n/).find(Boolean)?.slice(0,120)??"version ok";return{id:`worker:cli:${t}`,label:`${t} CLI binary`,level:"ok",detail:r}}async function Y4n(t,e,n={}){let r=[];r.push(S4n(t)),r.push(Q4n()),t.kb.driver==="sqlite"&&r.push(Jnt("kb",t.kb.sqlite_path,e)),t.ops.driver==="sqlite"&&(r.push(Jnt("ops",t.ops.sqlite_path,e)),r.push(T4n(t.ops.sqlite_path))),r.push(...R4n(t.messaging.sources)),r.push(M4n(t)),r.push(N4n(t));try{let c=((await Promise.resolve().then(()=>(rs(),kA))).BUILTIN_KERNEL_SKILLS??[]).map(l=>l.id);r.push(O4n(c))}catch{r.push({id:"kernel-skills",label:"kernel skills \uBA38\uD2F0\uB9AC\uC5BC\uB77C\uC774\uC988",level:"skip",detail:"@team-semicolon/semicolony-common \uBBF8\uB85C\uB529"})}let i=[],s=t.execution.target==="ollama"?t.execution.ollama_host:t.embedding?.host;return(t.execution.target==="ollama"||t.embedding?.provider==="ollama")&&(t.execution.target==="ollama"&&t.execution.model&&i.push(t.execution.model),t.embedding?.provider==="ollama"&&t.embedding.model&&i.push(t.embedding.model),r.push(...await D4n(s,i,n.fetchImpl))),nrt(r,{strict:n.strict})}async function aT(t={}){let e=t.env??process.env,n=t.homeDir??e.HOME??trt.homedir(),r=t.surface??"semicolony",i=[],s=by(e,r),o=Ey(e,{surface:r}),a=s.value?.replace(/\/$/,""),c=o.value,l=s.envName??XE(r),u=o.envName??bx(r),d=jo(n),A=t.updateInProgress===!0;if(!a||!c){let E=[a?null:s.candidates.join(" or "),c?null:o.candidates.join(" or ")].filter(Boolean);i.push({id:"worker:gateway-env",label:"worker KB gateway env",level:"fail",detail:`\uB204\uB77D: ${E.join(", ")} \u2014 Semi\uC5D0\uAC8C worker token \uBC1C\uAE09\uC744 \uC694\uCCAD\uD558\uC138\uC694`})}else c.startsWith("wck_")?i.push({id:"worker:gateway-env",label:"worker KB gateway env",level:"ok",detail:`${a}${s.envName?` (${s.envName})`:""}`}):i.push({id:"worker:gateway-env",label:"worker KB gateway env",level:"fail",detail:`${o.envName??"worker token"} \uC740 worker-scoped \`wck_\` \uD1A0\uD070\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4`});i.push({id:"worker:direct-db",label:"worker direct DB env",level:e.DATABASE_URL?.trim()?"warn":"ok",detail:e.DATABASE_URL?.trim()?"DATABASE_URL \uC124\uC815\uB428 \u2014 worker profile\uC740 \uAE30\uBCF8\uC801\uC73C\uB85C gateway\uB9CC \uC0AC\uC6A9\uD574\uC57C \uD569\uB2C8\uB2E4":"DATABASE_URL unset"});let h=Uc(n,d.env,Ll(n,".env")),f=Uc(n,d.kbMcp,Ll(n,"kb-mcp.json")),g=Uc(n,d.workerState,Ll(n,"worker-state.json")),m=null;if(g.status==="rejected")i.push(HH("worker:state-file","worker local state",g));else if(g.status==="absent")i.push({id:"worker:state-file",label:"worker local state",level:"warn",detail:`${d.workerState} \uC5C6\uC74C \u2014 worker setup \uC7AC\uC2E4\uD589 \uC2DC \uC0DD\uC131`});else{let E=oT(L4n(g.filePath),g);i.push(A&&E.level==="warn"&&E.detail?.includes("capability=")?{...E,level:"ok",detail:`${E.detail}; release activation in progress`}:E);try{m=ud(g.filePath)}catch{m=null}}if(h.status==="rejected"?i.push(HH("worker:env-file","worker env file",h)):h.status==="absent"?i.push({id:"worker:env-file",label:"worker env file",level:"warn",detail:`${d.env} \uC5C6\uC74C \u2014 ${qA(r)} worker setup \uC2E4\uD589 \uD544\uC694`}):i.push(oT(P4n({filePath:h.filePath,surface:r,gatewayUrlEnv:l,tokenEnv:u}),h)),f.status==="rejected")i.push(HH("worker:mcp-config","read-only KB MCP config",f));else if(f.status==="absent"){let E=m?.tool_adapters_enabled.includes("kb-mcp")??!1;i.push({id:"worker:mcp-config",label:"read-only KB MCP config",level:E?"warn":"skip",detail:E?`${d.kbMcp} \uC5C6\uC74C \u2014 ${qA(r)} worker setup --with-kb-mcp`:"kb-mcp adapter is not enabled; config is optional"})}else i.push(oT(F4n({filePath:f.filePath,surface:r,gatewayUrlEnv:l,tokenEnv:u}),f));i.push(...fle(n).map(E=>A&&E.id==="semicolony-home-residue"&&E.level==="warn"?{...E,level:"skip",detail:`${E.detail}; historical residue is not changed by release activation`}:E));let y=U4n(n,A);i.push(y.check),i.push(q4n(n,y.state,A)),i.push(G4n(n,y.state,A)),i.push(H4n(y.state,A));let b=!!(a&&c?.startsWith("wck_")),w=[{id:"worker:kb:hive-service",label:"KB read smoke: hive-service",domain:"semicolon",key:"glossary",subKey:"hive-service"},{id:"worker:kb:setup-guide",label:"KB read smoke: worker setup guide",domain:"semicolon",key:"process",subKey:"worker-environment-setup-via-semi"}];for(let E of w){if(!b){i.push({id:E.id,label:E.label,level:"skip",detail:"worker gateway env \uBBF8\uCDA9\uC871"});continue}try{await wy({baseUrl:a,token:c},E.domain,E.key,E.subKey,t.fetchImpl),i.push({id:E.id,label:E.label,level:"ok",detail:`${E.domain}/${E.key}${E.subKey?`/${E.subKey}`:""}`})}catch(C){i.push({id:E.id,label:E.label,level:"fail",detail:C.message.slice(0,240)})}}if(t.runExternalChecks){let E=t.commandRunner??W4n;i.push(await V4n("semo",E))}return nrt(i,{strict:t.strict})}function J4n(t){return t==="ok"?Vc.default.green("\u2713"):t==="warn"?Vc.default.yellow("\u26A0"):t==="fail"?Vc.default.red("\u2717"):Vc.default.gray("\u25CB")}function WH(t){let e=[""];for(let r of t.checks)e.push(` ${J4n(r.level)} ${r.label}${r.detail?Vc.default.gray(` \u2014 ${r.detail}`):""}`);e.push("");let n=t.summary;if(e.push(` ${Vc.default.bold("\uC694\uC57D")}: ${Vc.default.green(`${n.ok} ok`)} \xB7 ${Vc.default.yellow(`${n.warn} warn`)} \xB7 ${Vc.default.red(`${n.fail} fail`)} \xB7 ${Vc.default.gray(`${n.skip} skip`)}`),t.exitCode===0&&n.fail===0){let r=t.checks.some(i=>i.id.startsWith("worker:"));e.push(" "+Vc.default.green(r?"\u2192 Worker profile \uC900\uBE44 \uC644\uB8CC":"\u2192 Personal \uC2A4\uD0DD \uC900\uBE44 \uC644\uB8CC"))}else n.fail>0&&e.push(" "+Vc.default.red("\u2192 \uBE14\uB85C\uCEE4 \uC788\uC74C \u2014 \uC704 fail \uD56D\uBAA9 \uD574\uACB0 \uD6C4 \uC7AC\uC2E4\uD589"));return e.push(""),e.join(`
|
|
2969
2969
|
`)}function irt(t){t.command("doctor").description("SemiColony \uC2A4\uD0DD \uD504\uB9AC\uD50C\uB77C\uC774\uD2B8 \uD5EC\uC2A4\uCCB4\uD06C (config/DB/migrations/Ollama/credentials)").option("--json","JSON \uC73C\uB85C \uCD9C\uB825 (\uBA38\uC2E0 \uD30C\uC2F1\uC6A9)").option("--strict","warn \uB3C4 \uC2E4\uD328\uB85C \uAC04\uC8FC (CI \uC6A9)").option("--profile <profile>","doctor profile (worker|default)","default").action(async e=>{if(e.profile==="worker"){let o=await aT({strict:e.strict,runExternalChecks:!0});e.json?console.log(JSON.stringify(o,null,2)):console.log(WH(o)),process.exitCode=o.exitCode;return}if(e.profile&&e.profile!=="default"){console.error(Vc.default.red(`\uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 doctor profile: ${e.profile}`)),process.exitCode=1;return}let n=ln(),r=ks.resolve(__dirname,"..","migrations-sqlite"),i=Bs.existsSync(r)?r:ks.resolve(__dirname,"..","..","migrations-sqlite"),s=await Y4n(n,i,{strict:e.strict});e.json?console.log(JSON.stringify(s,null,2)):console.log(WH(s)),process.exitCode=s.exitCode})}var Vd=x(Oe());function ZUr(t,e){if(e){if(e!=="discord"&&e!=="slack")throw new Error(`--platform \uC740 discord \uB610\uB294 slack \uB9CC \uD5C8\uC6A9 (\uBC1B\uC74C: ${e})`);return e}let n=t.messaging.sources??[];if(n.includes("discord"))return"discord";if(n.includes("slack"))return"slack";throw new Error("config.toml messaging.sources \uC5D0 discord \uB610\uB294 slack \uC774 \uC5C6\uC74C \u2014 --platform \uC73C\uB85C \uBA85\uC2DC\uD558\uAC70\uB098 `semicolony init` \uC73C\uB85C \uC7AC\uC124\uC815")}async function XUr(){try{return{start:(await Promise.resolve().then(()=>(UHt(),LHt))).startDiscordRouter}}catch(t){let e=t instanceof Error?t.message:String(t);throw console.error(Vd.default.red(`
|
|
2970
2970
|
\u2717 @team-semicolon/semicolony-discord-router \uB85C\uB4DC \uC2E4\uD328`)),console.error(Vd.default.gray(` ${e}`)),console.error(Vd.default.yellow(`
|
|
2971
2971
|
\uC124\uCE58 \uC0C1\uD0DC \uD655\uC778:`)),console.error(" monorepo: packages/discord-router/ \uC874\uC7AC \uC5EC\uBD80"),console.error(" \uAE00\uB85C\uBC8C : npm list -g @team-semicolon/semicolony-discord-router"),console.error(Vd.default.gray(`
|
|
@@ -3174,7 +3174,7 @@ ${a}${i}`;if(s===0){let d=t.length===0||t.endsWith(`
|
|
|
3174
3174
|
`,r)&&(r+=1),t.slice(r,e.end)}function lWt(t,e){return uI(t)===e?!0:t.endsWith(`
|
|
3175
3175
|
`)&&uI(t.slice(0,-1))===e}function uWt(t,e){let n=GJ(e,"BEGIN"),r=GJ(e,"END"),i=t.indexOf(n),s=t.indexOf(r,i+n.length);if(i<0||s<i)throw new Error(`worker release context ${e} has unpaired managed markers`);return`${t.slice(0,i)}${t.slice(s+r.length)}`}function yWt(t,e,n,r){let i=aWt(t,"Claude"),s=aWt(e,"Codex"),o=new Set(n.manifest.contexts.map(({id:l})=>l)),a=new Set([...i.keys(),...s.keys()]),c=[];for(let l of a){if(!i.has(l)||!s.has(l))throw new Error(`worker release context ${l} is not present in both harnesses`);if(!o.has(l)){let u=r?.managed_target_digests[`context:claude:${l}`],d=r?.managed_target_digests[`context:codex:${l}`];if(!u||!d)throw new Error(`worker release context ${l} is an orphan managed marker`);if(!lWt(cWt(t,i.get(l)),u)||!lWt(cWt(e,s.get(l)),d))throw new Error(`worker release context ${l} changed since the prior managed snapshot; refusing removal`);c.push(l)}}return c}function HJ(t){let e=ph(t);if(!e)return"";if(!e.isFile()||e.isSymbolicLink())throw new Error("worker release context target is not a regular file");return bt.readFileSync(t,"utf8")}function Wqr(t,e,n){let r=Ft.join(t,".claude","CLAUDE.md"),i=Ft.join(t,".codex","AGENTS.md"),s=HJ(r),o=HJ(i),a=yWt(s,o,e,n);for(let c of a)s=uWt(s,c),o=uWt(o,c);for(let c of e.manifest.contexts)s=oWt(s,c.id,c.claude_content),o=oWt(o,c.id,c.codex_content);return[{key:"context-file:claude",targetPath:r,content:Buffer.from(s),mode:384},{key:"context-file:codex",targetPath:i,content:Buffer.from(o),mode:384},...e.manifest.skills.flatMap(c=>[{key:`skill:claude:${c.name}`,targetPath:Ft.join(t,".claude","skills",c.name,"SKILL.md"),content:Buffer.from(c.content),mode:420},{key:`skill:agents:${c.name}`,targetPath:Ft.join(t,".agents","skills",c.name,"SKILL.md"),content:Buffer.from(c.content),mode:420}]),...e.manifest.assets.map(c=>({key:`asset:${c.target}`,targetPath:cBe(t,c.target),content:c.content,mode:c.mode==="0755"?493:420}))]}function Vqr(t,e){yWt(HJ(Ft.join(t,".claude","CLAUDE.md")),HJ(Ft.join(t,".codex","AGENTS.md")),e,null)}function Yqr(t,e){let n=/^skill:(claude|agents):([a-z0-9][a-z0-9-]*)$/.exec(e);if(n){let r=n[1]==="claude"?".claude":".agents";return Ft.join(t,r,"skills",n[2],"SKILL.md")}if(e.startsWith("asset:")){let r=e.slice(6);if(!gWt.has(r))throw new Error(`worker release prior state has an unknown managed asset target: ${r}`);return cBe(t,r)}if(/^context:(claude|codex):[a-z0-9][a-z0-9-]*$/.test(e))return null;throw new Error(`worker release prior state has an unknown managed target: ${e}`)}function Jqr(t,e,n){if(!n)return[];let r=EWt(e),i=[];for(let[s,o]of Object.entries(n.managed_target_digests)){let a=Yqr(t,s);if(r[s]||a===null)continue;Su(t,a);let c=ph(a);if(c){if(!c.isFile()||c.isSymbolicLink())throw new Error(`worker release managed target ${s} is not a regular file`);if(uI(bt.readFileSync(a))!==o)throw new Error(`worker release managed target ${s} digest changed; refusing removal`);i.push({key:s,targetPath:a})}}return i}function Kqr(t,e){let n=new Map,r=Ft.join(t,"staged");return bt.mkdirSync(r,{recursive:!0,mode:448}),e.forEach((i,s)=>{let o=Ft.join(r,`target-${s}`);bt.writeFileSync(o,i.content,{mode:i.mode}),bt.chmodSync(o,i.mode),n.set(i.key,o)}),n}function lBe(t,e){let n=[],r=Ft.dirname(t);for(;!ph(r);){n.push(r);let i=Ft.dirname(r);if(i===r)break;r=i}bt.mkdirSync(Ft.dirname(t),{recursive:!0,mode:448}),e.push(...n.reverse())}function zqr(t,e,n){let r=Ft.join(t,"backup");return bt.mkdirSync(r,{recursive:!0,mode:448}),e.map((i,s)=>{let o=ph(i),a=Ft.join(r,`target-${s}`);if(!o)return{targetPath:i,backupPath:a,existed:!1};if(!o.isFile()||o.isSymbolicLink())throw new Error("worker release backup target is not a regular file");return lBe(a,n),bt.copyFileSync(i,a),bt.chmodSync(a,o.mode&511),{targetPath:i,backupPath:a,existed:!0,mode:o.mode&511}})}function bWt(t,e,n){let r=Ft.join(Ft.dirname(e),`.semo-worker-release-${process.pid}-${Date.now()}.tmp`);try{bt.copyFileSync(t,r),bt.chmodSync(r,n),bt.renameSync(r,e)}catch(i){try{bt.unlinkSync(r)}catch(s){s.code}throw i}}function Zqr(t,e,n){for(let r of t){let i=e.get(r.key);if(!i)throw new Error("worker release staged target is missing");lBe(r.targetPath,n),bWt(i,r.targetPath,r.mode)}}function Xqr(t){for(let e of t){let n=ph(e.targetPath);if(n){if(!n.isFile()||n.isSymbolicLink())throw new Error(`worker release managed target ${e.key} cannot be removed safely`);bt.unlinkSync(e.targetPath)}}}function EWt(t){let e={};for(let n of t.manifest.contexts)e[`context:claude:${n.id}`]=uI(n.claude_content),e[`context:codex:${n.id}`]=uI(n.codex_content);for(let n of t.manifest.skills)e[`skill:claude:${n.name}`]=n.sha256.toLowerCase(),e[`skill:agents:${n.name}`]=n.sha256.toLowerCase();for(let n of t.manifest.assets)e[`asset:${n.target}`]=n.sha256.toLowerCase();return e}function ejr(t){let e={};for(let n of t.manifest.skills)e[`skill:claude:${n.name}`]="0644",e[`skill:agents:${n.name}`]="0644";for(let n of t.manifest.assets)e[`asset:${n.target}`]=n.mode;return e}function dWt(t,e){if(t.exitCode!==0||t.summary.fail>0)return"fail";let n=new Map(t.checks.map(r=>[r.id,r.level]));return e.some(r=>n.get(r)!=="ok")?"fail":t.summary.warn>0||t.checks.some(r=>r.level==="warn")?"warn":"pass"}function aBe(t,e="doctor"){return{phase:e,summary:t.summary,checks:t.checks.map(({id:n,level:r})=>({id:n,level:r}))}}function tjr(t,e,n){Su(t,e),bt.mkdirSync(Ft.dirname(e),{recursive:!0,mode:448}),Su(t,e);let r;try{r=bt.openSync(e,"wx",384)}catch(s){throw s.code==="EEXIST"?new Error("worker release update is already in progress"):s}try{bt.writeFileSync(r,`${JSON.stringify({schema_version:1,pid:process.pid,started_at:n.toISOString()})}
|
|
3176
3176
|
`,"utf8"),bt.fsyncSync(r)}catch(s){try{bt.closeSync(r)}catch{}try{bt.unlinkSync(e)}catch{}throw s}let i=bt.fstatSync(r);return()=>{let s=!0;try{bt.closeSync(r)}catch{s=!1}try{Su(t,e);let o=ph(e);if(!o)return s;if(o.isSymbolicLink()||!o.isFile()||o.dev!==i.dev||o.ino!==i.ino)return!1;bt.unlinkSync(e)}catch{s=!1}return s}}function njr(t){for(let e of[...t].reverse())try{bt.rmdirSync(e)}catch(n){if(!["ENOENT","ENOTEMPTY"].includes(n.code??""))throw n}}function rjr(t,e,n){for(let r of[...e].reverse()){Su(t,r.targetPath);let i=ph(r.targetPath);if(i?.isDirectory())throw new Error("worker release rollback target became a directory");i&&bt.unlinkSync(r.targetPath),r.existed&&(lBe(r.targetPath,n),bWt(r.backupPath,r.targetPath,r.mode??384))}njr(n)}function ijr(t,e){let n=Ft.resolve(jo(t).root),r=Ft.relative(n,Ft.resolve(e));if(r===""||r.startsWith("..")||Ft.isAbsolute(r))throw new Error("worker release diagnostic escapes the worker root")}function sjr(t,e,n,r){ijr(t,e),Su(t,e),bt.mkdirSync(Ft.dirname(e),{recursive:!0,mode:448}),Su(t,e);let i=Ft.join(Ft.dirname(e),`.release-update-rollback-failure-${process.pid}-${Date.now()}.tmp`);Su(t,i);let s=`${JSON.stringify({schema_version:1,release_id:n,rollback_failed:!0,recorded_at:r.toISOString()},null,2)}
|
|
3177
|
-
`,o;try{o=bt.openSync(i,"wx",384),bt.writeFileSync(o,s,"utf8"),bt.fsyncSync(o),bt.closeSync(o),o=void 0,Su(t,e),bt.renameSync(i,e)}catch(a){if(o!==void 0)try{bt.closeSync(o)}catch{}try{bt.unlinkSync(i)}catch{}throw a}}function sBe(t,e){try{Su(t,Ft.join(e,".cleanup-safety-check"));let n=ph(e);return n?!n.isDirectory()||n.isSymbolicLink()?!1:(bt.rmSync(e,{recursive:!0,force:!0}),!0):!0}catch{return!1}}function AWt(t,e){try{Su(t,e);let n=ph(e);return n?!n.isFile()||n.isSymbolicLink()?!1:(bt.unlinkSync(e),!0):!0}catch{return!1}}async function bb(t,e,n,r={}){let i={release_id:e.releaseId,manifest_sha256:e.manifestSha256,doctor_status:r.doctorStatus??"fail",doctor_summary:r.doctorReport?{...aBe(r.doctorReport,n),rollback:r.rollback??"not-needed"}:{phase:n,rollback:r.rollback??"not-needed"}};try{await t.reportUpdate(i)}catch{}}async function wWt(t){let e=t.env??process.env,n=t.homeDir??e.HOME??fWt.homedir(),r=t.surface??"semicolony",i=t.client??qH({env:e,surface:r,fetchImpl:t.fetchImpl}),s=t.doctor??(h=>aT({env:e,homeDir:n,surface:r,fetchImpl:t.fetchImpl,runExternalChecks:!
|
|
3177
|
+
`,o;try{o=bt.openSync(i,"wx",384),bt.writeFileSync(o,s,"utf8"),bt.fsyncSync(o),bt.closeSync(o),o=void 0,Su(t,e),bt.renameSync(i,e)}catch(a){if(o!==void 0)try{bt.closeSync(o)}catch{}try{bt.unlinkSync(i)}catch{}throw a}}function sBe(t,e){try{Su(t,Ft.join(e,".cleanup-safety-check"));let n=ph(e);return n?!n.isDirectory()||n.isSymbolicLink()?!1:(bt.rmSync(e,{recursive:!0,force:!0}),!0):!0}catch{return!1}}function AWt(t,e){try{Su(t,e);let n=ph(e);return n?!n.isFile()||n.isSymbolicLink()?!1:(bt.unlinkSync(e),!0):!0}catch{return!1}}async function bb(t,e,n,r={}){let i={release_id:e.releaseId,manifest_sha256:e.manifestSha256,doctor_status:r.doctorStatus??"fail",doctor_summary:r.doctorReport?{...aBe(r.doctorReport,n),rollback:r.rollback??"not-needed"}:{phase:n,rollback:r.rollback??"not-needed"}};try{await t.reportUpdate(i)}catch{}}async function wWt(t){let e=t.env??process.env,n=t.homeDir??e.HOME??fWt.homedir(),r=t.surface??"semicolony",i=t.client??qH({env:e,surface:r,fetchImpl:t.fetchImpl}),s=t.doctor??(h=>aT({env:e,homeDir:n,surface:r,fetchImpl:t.fetchImpl,runExternalChecks:!0,commandRunner:t.commandRunner,updateInProgress:h?.updateInProgress===!0})),o=await i.fetchActiveRelease(),a=mWt(o),c;try{c=Gqr(o)}catch(h){throw t.check||await bb(i,a,"validation"),h}try{sWt(n,c)}catch(h){throw t.check||await bb(i,a,"preflight"),h}let l=jo(n);if(t.check){let h=ew(l.releaseState),f=h?.applied_release_id===c.releaseId&&h.manifest_sha256===c.manifestSha256;return{mode:"check",installed:h?.applied_release_version??null,target:c.version,up_to_date:f,status:f?"pass":"available"}}let u=(t.now??(()=>new Date))(),d=tjr(n,l.updateLock,u),A={mode:"update",installed:c.version,target:c.version,up_to_date:!0,status:"pass"};try{try{sWt(n,c)}catch(V){throw await bb(i,a,"preflight"),V}let h=ew(l.releaseState);if(h?.applied_release_id===c.releaseId&&h.manifest_sha256===c.manifestSha256){try{Vqr(n,c)}catch(K){throw await bb(i,a,"projection-validation"),K}let V;try{V=await s({updateInProgress:!1});let K=dWt(V,c.manifest.required_doctor_checks);if(K!=="pass")throw await bb(i,a,"doctor",{doctorStatus:K,doctorReport:V}),new fQ(K,V);let z=await i.reportUpdate({release_id:c.releaseId,manifest_sha256:c.manifestSha256,doctor_status:"pass",doctor_summary:aBe(V),applied_at:u.toISOString()});if(!z.reported||!z.applied)throw new Error("worker release Gateway did not accept the pass report");return A}catch(K){throw K instanceof fQ||await bb(i,a,V?"report":"doctor",{doctorReport:V}),K}}let g=Ft.join(n,".semo","staging","worker-release",c.releaseId),m={schema_version:1,profile_id:ud(l.workerState)?.profile_id??YG,applied_release_id:c.releaseId,applied_release_version:c.version,manifest_sha256:c.manifestSha256,managed_target_digests:EWt(c),managed_target_modes:ejr(c),applied_at:u.toISOString(),last_doctor_status:"pass",last_doctor_at:u.toISOString()},y,b;try{y=Wqr(n,c,h),b=Jqr(n,c,h)}catch(V){throw await bb(i,a,"projection-validation"),V}let w=[l.workerState,l.releaseState],E=[],C=[],v=!1,O="staging",R,Q=!1;try{Su(n,g);let V=Kqr(g,y);C=zqr(g,[...new Set([...y.map(({targetPath:ut})=>ut),...b.map(({targetPath:ut})=>ut),...w])],E),O="swap",Zqr(y,V,E),Xqr(b),v=!0,O="doctor",R=await s({updateInProgress:!0});let K=dWt(R,c.manifest.required_doctor_checks);if(K!=="pass")throw new fQ(K,R);O="state";let z=ud(l.workerState);z&&!ph(l.workerState)&&wx(l.workerState,z),nKe(l.releaseState,m),O="report";let fe=await i.reportUpdate({release_id:c.releaseId,manifest_sha256:c.manifestSha256,doctor_status:"pass",doctor_summary:aBe(R),applied_at:u.toISOString()});if(!fe.reported||!fe.applied)throw new Error("worker release Gateway did not accept the pass report");return Q=!0,sBe(n,g),AWt(n,l.rollbackFailure),A}catch(V){if(Q)return sBe(n,g),AWt(n,l.rollbackFailure),A;let K="not-needed";if(v||C.length>0)try{rjr(n,C,E),K="pass"}catch{K="fail";try{sjr(n,l.rollbackFailure,c.releaseId,u)}catch{}}sBe(n,g);let z=V instanceof fQ?V:null;throw await bb(i,a,O,{doctorStatus:z?.doctorStatus,doctorReport:z?.report??R,rollback:K}),V}}finally{d()}}function CWt(t){return[`installed=${t.installed??"none"}`,`target=${t.target}`,`up_to_date=${String(t.up_to_date)}`,`status=${t.status}`].join(`
|
|
3178
3178
|
`)}function IWt(t,e={}){let n=e.surface??"semicolony",r=qA(n),i=t.command("worker").description(n==="semo-ops"?"SEMO Ops worker device setup, verification, and sync":"Worker operator-kit setup, verification, and sync");iWt(i,r),i.command("update").description("\uD65C\uC131 SEMO Ops worker release\uB97C Gateway\uC5D0\uC11C \uD655\uC778\uD558\uAC70\uB098 \uBA85\uC2DC\uC801\uC73C\uB85C \uC801\uC6A9\uD569\uB2C8\uB2E4").option("--check","\uD65C\uC131 release\uC640 local release state\uB9CC \uBE44\uAD50\uD558\uACE0 \uC544\uBB34\uAC83\uB3C4 \uC4F0\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4").option("--json","JSON \uCD9C\uB825").action(async o=>{try{let a=await wWt({check:o.check,surface:n});console.log(o.json?JSON.stringify(a,null,2):CWt(a)),process.exitCode=0}catch(a){console.error(im.default.red(`${r} worker update \uC2E4\uD328: ${a instanceof Error?a.message:a}`)),process.exitCode=1}}),i.command("register").description("SEMO Ops worker device\uB97C \uC911\uC559 DB registry\uC5D0 \uB4F1\uB85D/\uAC31\uC2E0\uD569\uB2C8\uB2E4").requiredOption("--worker <id>","worker id/domain, \uC608: roki").requiredOption("--device <id>","device id, \uC608: roki-pc").option("--display-name <name>","\uD45C\uC2DC\uBA85").option("--hostname <name>","\uD638\uC2A4\uD2B8\uBA85 (\uBBF8\uC9C0\uC815 \uC2DC \uD604\uC7AC \uBA38\uC2E0)").option("--os <name>","OS \uC124\uBA85 (\uBBF8\uC9C0\uC815 \uC2DC \uD604\uC7AC \uBA38\uC2E0)").option("--shell <path>","\uAE30\uBCF8 shell").option("--workspace-root <path>","workspace root").option("--profile-id <id>","installed profile id","semo-ops-worker").option("--profile-version <version>","installed profile version").option("--adapter <csv>","\uD65C\uC131 \uB3C4\uAD6C \uC5B4\uB311\uD130, \uC608: codex,claude-code").option("--kb-access-mode <mode>","worker-gateway|direct-db-bootstrap|kb-portable|none","worker-gateway").option("--credential-id <uuid>","gateway_credentials.id (\uD3C9\uBB38 \uD1A0\uD070 \uAE08\uC9C0)").option("--doctor-status <status>","unknown|pending|pass|warn|fail","pending").option("--doctor-summary-json <json>","doctor summary JSON object").option("--progress <key=value>","setup progress pair (repeatable)",(o,a)=>(a.push(o),a),[]).option("--progress-json <json>","setup progress JSON object").option("--status <status>","pending-auth|pending-setup|active|blocked|stale|revoked|retired","pending-setup").option("--metadata-json <json>","metadata JSON object").option("--json","JSON \uCD9C\uB825").action(async o=>{try{let a=tWt(o),c=await XHt({workerId:o.worker,deviceId:o.device,displayName:o.displayName,hostname:o.hostname,osName:o.os,shell:o.shell,workspaceRoot:o.workspaceRoot,installedProfileId:o.profileId,installedProfileVersion:o.profileVersion,toolAdaptersEnabled:a.toolAdaptersEnabled??[],kbAccessMode:o.kbAccessMode,gatewayCredentialId:o.credentialId,lastDoctorStatus:o.doctorStatus,lastDoctorSummary:a.lastDoctorSummary,setupProgress:a.setupProgress,status:o.status,metadata:a.metadata});o.json?console.log(JSON.stringify(HN(c),null,2)):console.log(nBe([c]))}catch(a){console.error(im.default.red(`${r} worker register \uC2E4\uD328: ${a instanceof Error?a.message:a}`)),process.exitCode=1}finally{await S()}}),i.command("status").description("\uC911\uC559 DB registry\uC758 SEMO Ops worker device \uC0C1\uD0DC\uB97C \uC870\uD68C\uD569\uB2C8\uB2E4").option("--worker <id>","worker id/domain").option("--device <id>","device id").option("--json","JSON \uCD9C\uB825").action(async o=>{try{let a=await NJ({workerId:o.worker,deviceId:o.device});o.json?console.log(JSON.stringify(a.map(HN),null,2)):console.log(nBe(a))}catch(a){console.error(im.default.red(`${r} worker status \uC2E4\uD328: ${a instanceof Error?a.message:a}`)),process.exitCode=1}finally{await S()}}),i.command("local-hive").description("\uC608\uC678\uC801\uC778 local hive workload \uB4F1\uB85D/\uC870\uD68C").command("register").description("worker device\uC5D0 local hive exception\uC744 \uB4F1\uB85D/\uAC31\uC2E0\uD569\uB2C8\uB2E4").requiredOption("--hive <id>","local hive id").requiredOption("--device <id>","device id").requiredOption("--worker <id>","worker id/domain").requiredOption("--workload-type <type>","hive-bridge|hive-agent|hive-cron|hive-link|hive-watch|other").requiredOption("--reason <text>","\uB85C\uCEEC\uC5D0 \uB0A8\uACA8\uC57C \uD558\uB294 \uC774\uC720").requiredOption("--migration-target <target>","\uCD5C\uC885 \uC774\uAD00 \uB300\uC0C1, \uC608: hive@workstation").option("--cannot-move-reason <text>","\uC9C0\uAE08 \uC774\uAD00\uD560 \uC218 \uC5C6\uB294 \uC0C1\uC138 \uC0AC\uC720").option("--expiry-at <iso>","\uC608\uC678 \uB9CC\uB8CC \uC2DC\uAC01").option("--status <status>","approved|expiring|migrated|retired","approved").option("--json","JSON \uCD9C\uB825").action(async o=>{try{let a=await eWt({localHiveId:o.hive,deviceId:o.device,workerId:o.worker,workloadType:o.workloadType,reason:o.reason,migrationTarget:o.migrationTarget,cannotMoveReason:o.cannotMoveReason,expiryAt:o.expiryAt,status:o.status});o.json?console.log(JSON.stringify(a,null,2)):console.log(im.default.green(`\u2714 local hive \uB4F1\uB85D: ${a.local_hive_id}`))}catch(a){console.error(im.default.red(`${r} worker local-hive register \uC2E4\uD328: ${a instanceof Error?a.message:a}`)),process.exitCode=1}finally{await S()}}),i.command("setup").description("SEMO Ops worker device \uD658\uACBD\uC744 \uC124\uC815\uD569\uB2C8\uB2E4").option("--gateway-url <url>","worker profile KB gateway URL").option("--worker-token-env <name>","worker token env var name").option("--worker <id>","worker id/domain, \uC608: roki").option("--device <id>","device id, \uC608: roki-pc").option("--profile-version <version>","workspace profile version").option("--with-kb-mcp","read-only KB MCP config \uC0DD\uC131").option("-f, --force","\uAE30\uC874 worker env \uB36E\uC5B4\uC4F0\uAE30").action(async o=>{try{let a=await TJ({force:o.force,gatewayUrl:o.gatewayUrl,tokenEnv:o.workerTokenEnv,workerId:o.worker,deviceId:o.device,profileVersion:o.profileVersion,withKbMcp:o.withKbMcp,surface:n});console.log(OJ(a))}catch(a){console.error(im.default.red(`${r} worker setup \uC2E4\uD328: ${a instanceof Error?a.message:a}`)),process.exitCode=1}}),i.command("sync").description("\uD65C\uC131 SEMO Ops worker release\uC640 local release state\uB97C \uC810\uAC80\uD569\uB2C8\uB2E4").option("--dry-run","Gateway release\uC640 local state\uB97C \uBE44\uAD50\uD558\uACE0 \uC544\uBB34\uAC83\uB3C4 \uC4F0\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4").action(async o=>{try{let a=o.dryRun?await sT({surface:n}):await Ynt({surface:n});console.log($H(a)),process.exitCode=a.summary.fail>0?1:0}catch(a){console.error(im.default.red(`${r} worker sync \uC2E4\uD328: ${a instanceof Error?a.message:a}`)),process.exitCode=1}}),i.command("daily-check").description("Claude/Codex \uC138\uC158 \uC2DC\uC791 \uC2DC \uD558\uB8E8 1\uD68C worker profile drift\uB97C \uC810\uAC80\uD569\uB2C8\uB2E4").option("--force","\uC624\uB298 \uC774\uBBF8 \uC810\uAC80\uD588\uC5B4\uB3C4 \uB2E4\uC2DC \uC2E4\uD589").option("--json","JSON \uCD9C\uB825").option("--quiet","\uC815\uC0C1/\uC2A4\uD0B5 \uACB0\uACFC\uB294 \uCD9C\uB825\uD558\uC9C0 \uC54A\uACE0 \uACBD\uACE0 \uC774\uC0C1\uB9CC \uCD9C\uB825").action(async o=>{try{let a=await JHt({surface:n,force:o.force});o.json?console.log(JSON.stringify(a,null,2)):(!o.quiet||!a.skipped&&a.state.status!=="ok")&&console.log(KHt(a)),process.exitCode=0}catch(a){o.quiet||console.error(im.default.red(`${r} worker daily-check \uC2E4\uD328: ${a instanceof Error?a.message:a}`)),process.exitCode=1}}),i.command("doctor").description("SEMO Ops worker device \uC124\uC815\uC744 \uAC80\uC99D\uD569\uB2C8\uB2E4").option("--json","JSON \uC73C\uB85C \uCD9C\uB825 (\uBA38\uC2E0 \uD30C\uC2F1\uC6A9)").option("--strict","warn \uB3C4 \uC2E4\uD328\uB85C \uAC04\uC8FC (CI \uC6A9)").action(async o=>{let a=await aT({strict:o.strict,surface:n,runExternalChecks:!0});o.json?console.log(JSON.stringify(a,null,2)):console.log(WH(a)),process.exitCode=a.exitCode})}var Mb=require("node:fs"),Rb=require("node:path"),H8t=require("node:child_process"),W8t=x(G3());var Qb=require("node:fs"),Jd=require("node:path"),h8t=x(G3());var H3="semicolon.dev/v1alpha1",W3="ProjectWorkspace",xQ=["single-app","monorepo","infra","content","mixed"],sr=class extends Error{constructor(n,r){super(`${n}: ${r}`);this.code=n;this.name="WorkspaceContractError"}};var Hke=(0,Jd.join)(".semo","project.yaml"),MHr=/^[a-z][a-z0-9-]{0,99}$/,THr=/^(?!\/)(?![A-Za-z]:[/\\])(?!.*(?:^|\/)\.\.(?:\/|$))[A-Za-z0-9._-]+(?:\/[A-Za-z0-9._-]+)*$/;function OHr(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function vP(t,e){if(!OHr(t))throw new sr("WSP003",`${e} must be an object`);return t}function xP(t,e,n){let r=Object.keys(t).sort(),i=[...e].sort();if(r.length!==i.length||r.some((s,o)=>s!==i[o]))throw new sr("WSP003",`${n} keys must be exactly ${i.join(", ")}`)}function A8t(t,e){if(typeof t!="string"||!MHr.test(t))throw new sr("WSP003",`${e} must be a lowercase slug`);return t}function Gke(t,e){if(typeof t!="boolean")throw new sr("WSP006",`${e} must be boolean`);return t}function NHr(t,e){if(typeof t!="string"||!THr.test(t))throw new sr("WSP004",`${e} must be a normalized repository-relative path`);return t}function PHr(t){if(typeof t!="string"||!xQ.includes(t))throw new sr("WSP005",`spec.layout must be one of ${xQ.join(", ")}`);return t}function Qu(t=process.cwd()){let e=(0,Jd.resolve)(t);(0,Qb.existsSync)(e)&&(0,Qb.statSync)(e).isFile()&&(e=(0,Jd.dirname)(e));let n=(0,Jd.parse)(e).root;for(;;){if((0,Qb.existsSync)((0,Jd.join)(e,Hke)))return e;if(e===n)return null;e=(0,Jd.dirname)(e)}}function Wke(t){let e=(0,h8t.parseDocument)(t,{prettyErrors:!0,uniqueKeys:!0});if(e.errors.length>0)throw new sr("WSP003",`invalid .semo/project.yaml: ${e.errors[0].message}`);let n;try{n=e.toJS({maxAliasCount:0})}catch{throw new sr("WSP003","YAML aliases are not allowed")}let r=vP(n,"workspace");if(xP(r,["apiVersion","kind","metadata","spec"],"workspace"),r.apiVersion!==H3||r.kind!==W3)throw new sr("WSP001",`expected ${H3} ${W3}`);let i=vP(r.metadata,"metadata");xP(i,["domain","name"],"metadata");let s=A8t(i.domain,"metadata.domain"),o=A8t(i.name,"metadata.name"),a=vP(r.spec,"spec");xP(a,["layout","sourceRoots","knowledge","capabilities"],"spec");let c=PHr(a.layout);if(!Array.isArray(a.sourceRoots)||a.sourceRoots.length===0)throw new sr("WSP004","spec.sourceRoots must not be empty");let l=a.sourceRoots.map((h,f)=>NHr(h,`spec.sourceRoots[${f}]`));if(new Set(l).size!==l.length)throw new sr("WSP004","spec.sourceRoots must be unique");let u=vP(a.knowledge,"spec.knowledge");xP(u,["pipelineConfig"],"spec.knowledge");let d=u.pipelineConfig;if(d!==`${s}/pipeline/config`)throw new sr("WSP002","metadata.domain and spec.knowledge.pipelineConfig do not match");let A=vP(a.capabilities,"spec.capabilities");return xP(A,["skills","resources","credentials"],"spec.capabilities"),{apiVersion:H3,kind:W3,metadata:{domain:s,name:o},spec:{layout:c,sourceRoots:l,knowledge:{pipelineConfig:d},capabilities:{skills:Gke(A.skills,"spec.capabilities.skills"),resources:Gke(A.resources,"spec.capabilities.resources"),credentials:Gke(A.credentials,"spec.capabilities.credentials")}}}}function am(t){let e=(0,Jd.join)((0,Jd.resolve)(t),Hke);if(!(0,Qb.existsSync)(e))throw new sr("WSP001",`missing ${Hke}`);return Wke((0,Qb.readFileSync)(e,"utf8"))}var f8t=require("node:crypto"),Cl=require("node:fs/promises"),Du=require("node:fs"),Kd=require("node:path");var FHr=[".env",".env.*","!.env.example",".env.e2e.local",".semo/state.json",".semo/state/",".semo/cache/",".semo/staging/","resources/cache/","skills/*/","!skills/manifest.yaml"];function Vke(t,e){let n=(0,Kd.resolve)(t),r=(0,Kd.resolve)(n,e),i=(0,Kd.relative)(n,r);if(i===".."||i.startsWith(`..${Kd.sep}`)||i.startsWith(Kd.sep))throw new sr("WSP004",`path escapes workspace: ${e}`);return r}function LHr(t){let e=`apiVersion: semicolon.dev/v1alpha1
|
|
3179
3179
|
kind: ProjectWorkspace
|
|
3180
3180
|
metadata:
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
-- 171_worker_release_gateway_privileges.sql
|
|
2
|
+
--
|
|
3
|
+
-- The Gateway runs as sc_app. A worker release read needs only the bound
|
|
4
|
+
-- device, its profile's active release, and the immutable release manifest;
|
|
5
|
+
-- reporting needs only the six health/application columns on that device.
|
|
6
|
+
-- Keep credential issuance and all other device mutations owner-controlled.
|
|
7
|
+
|
|
8
|
+
GRANT USAGE ON SCHEMA semicolony TO sc_app;
|
|
9
|
+
|
|
10
|
+
REVOKE ALL PRIVILEGES ON TABLE
|
|
11
|
+
semicolony.worker_devices,
|
|
12
|
+
semicolony.workspace_profiles,
|
|
13
|
+
semicolony.worker_profile_releases
|
|
14
|
+
FROM PUBLIC, sc_provider;
|
|
15
|
+
|
|
16
|
+
REVOKE INSERT, DELETE, TRUNCATE, REFERENCES, TRIGGER ON TABLE
|
|
17
|
+
semicolony.worker_devices,
|
|
18
|
+
semicolony.workspace_profiles,
|
|
19
|
+
semicolony.worker_profile_releases
|
|
20
|
+
FROM sc_app;
|
|
21
|
+
|
|
22
|
+
GRANT SELECT (
|
|
23
|
+
device_id,
|
|
24
|
+
worker_id,
|
|
25
|
+
gateway_credential_id,
|
|
26
|
+
status,
|
|
27
|
+
installed_profile_id,
|
|
28
|
+
applied_release_id,
|
|
29
|
+
applied_release_version,
|
|
30
|
+
applied_at
|
|
31
|
+
) ON TABLE semicolony.worker_devices TO sc_app;
|
|
32
|
+
|
|
33
|
+
GRANT UPDATE (
|
|
34
|
+
last_seen_at,
|
|
35
|
+
last_doctor_status,
|
|
36
|
+
last_doctor_summary,
|
|
37
|
+
applied_release_id,
|
|
38
|
+
applied_release_version,
|
|
39
|
+
applied_at
|
|
40
|
+
) ON TABLE semicolony.worker_devices TO sc_app;
|
|
41
|
+
|
|
42
|
+
GRANT SELECT (profile_id, active_release_id)
|
|
43
|
+
ON TABLE semicolony.workspace_profiles TO sc_app;
|
|
44
|
+
|
|
45
|
+
GRANT SELECT (release_id, profile_id, version, status, manifest, manifest_sha256)
|
|
46
|
+
ON TABLE semicolony.worker_profile_releases TO sc_app;
|