@jc_stack/ez-agents 0.1.0-beta.29 → 0.1.0-beta.31
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/CHANGELOG.md +15 -0
- package/package.json +1 -1
- package/src/updates/binding.mjs +1 -1
- package/templates/agent-guidance.md +10 -0
- package/test/agent-guidance.test.ts +8 -0
- package/test/updates.test.mjs +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.1.0-beta.31
|
|
6
|
+
|
|
7
|
+
- Make the owner-authorized contribution lifecycle explicit in shipped agent
|
|
8
|
+
guidance: take a coherent change through independent final-head review, CI,
|
|
9
|
+
applicable QA and, when authorized, merge. Release authority includes the
|
|
10
|
+
merge needed for publication, which continues through the reviewed GitHub
|
|
11
|
+
publisher, registry readback and eligible runtime verification. Preserve local
|
|
12
|
+
QA, diagnostics, auth-only work and deployment as separate boundaries.
|
|
13
|
+
|
|
14
|
+
## 0.1.0-beta.30
|
|
15
|
+
|
|
16
|
+
- Bind installed native command launchers to the deployment's canonical control
|
|
17
|
+
directory. This makes application registration use the owning agent's state
|
|
18
|
+
and prevents caller environment variables from redirecting that authority.
|
|
19
|
+
|
|
5
20
|
## 0.1.0-beta.29
|
|
6
21
|
|
|
7
22
|
- Republish the beta.28 Voice connection and web-serving contract at a monotonic
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jc_stack/ez-agents",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.31",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "A lightweight foundation for persistent business AI assistants using existing AI harnesses, workspaces and plugins.",
|
package/src/updates/binding.mjs
CHANGED
|
@@ -19,7 +19,7 @@ export async function bindUpdates(home,hostConfig,packageRoot=fileURLToPath(new
|
|
|
19
19
|
await fs.writeFile(path.join(bin,'ez'),`#!${process.execPath}\nimport fs from 'node:fs';import {pathToFileURL} from 'node:url';const c=JSON.parse(fs.readFileSync(${configFile}));const m=await import(pathToFileURL(c.packageRoot+'/src/plugins/manager.mjs'));m.main(['--home',${JSON.stringify(home)},...process.argv.slice(2)]).catch(e=>{console.error(e.message);process.exitCode=1});\n`,{mode:0o700});
|
|
20
20
|
for(const [name,entry] of Object.entries(pkg.bin)) {
|
|
21
21
|
const dest=path.join(bin,name);await fs.rm(dest,{force:true});
|
|
22
|
-
await fs.writeFile(dest,`#!${process.execPath}\nimport fs from 'node:fs';import {spawn} from 'node:child_process';const c=JSON.parse(fs.readFileSync(${configFile}));const child=spawn(c.packageRoot+'/'+${JSON.stringify(entry)},process.argv.slice(2),{stdio:'inherit',env:{...process.env,EZ_DEPLOYMENT_DIR:c.deploymentDir}});for(const s of ['SIGTERM','SIGINT'])process.on(s,()=>child.kill(s));child.on('error',e=>{console.error(e.message);process.exitCode=1});child.on('close',c=>process.exitCode=c??1);\n`,{mode:0o700});
|
|
22
|
+
await fs.writeFile(dest,`#!${process.execPath}\nimport fs from 'node:fs';import {spawn} from 'node:child_process';const c=JSON.parse(fs.readFileSync(${configFile}));const child=spawn(c.packageRoot+'/'+${JSON.stringify(entry)},process.argv.slice(2),{stdio:'inherit',env:{...process.env,EZ_DEPLOYMENT_DIR:c.deploymentDir,EZ_CONTROL_DIR:c.deploymentDir+'/control'}});for(const s of ['SIGTERM','SIGINT'])process.on(s,()=>child.kill(s));child.on('error',e=>{console.error(e.message);process.exitCode=1});child.on('close',c=>process.exitCode=c??1);\n`,{mode:0o700});
|
|
23
23
|
}
|
|
24
24
|
await bindToolDiscovery(home,config.workspace);
|
|
25
25
|
return {ok:true,home,deploymentDir,packageRoot,policy:'Automatic compatible beta-channel updates by default; saved stable-only or manual policies take precedence. Local candidates require an explicit owner request.'};
|
|
@@ -67,6 +67,16 @@ a conflicting runner, context/prompt reconstruction or competing agent-turn queu
|
|
|
67
67
|
Revise a violating patch before approval or merge; document real capability gaps
|
|
68
68
|
instead of weakening the boundary to fit existing code.
|
|
69
69
|
|
|
70
|
+
For an owner-authorized product, fix or contribution, complete one coherent
|
|
71
|
+
loop: current main, focused PR, independent final-head review, required CI and
|
|
72
|
+
applicable QA. When the owner request or saved maintainer mandate includes merge
|
|
73
|
+
or release authority, then merge; release authority includes the merge needed for
|
|
74
|
+
the release. Otherwise leave the reviewed PR ready and state the remaining
|
|
75
|
+
authority. When release authority applies, continue through immutable
|
|
76
|
+
artifact publication, the repository's reviewed GitHub publisher, registry
|
|
77
|
+
readback and eligible installed-runtime verification. Local QA,
|
|
78
|
+
diagnostics, auth-only work and deployment remain separate authority boundaries.
|
|
79
|
+
|
|
70
80
|
Within the owner's request or saved contribution mandate, you may report evidenced
|
|
71
81
|
existing violations and submit focused fixes. Check existing issues, PRs and active
|
|
72
82
|
owners first; add sanitized evidence and a concrete next action to the existing
|
|
@@ -25,6 +25,14 @@ test('shared guidance makes direct owner chat replies a native transport action'
|
|
|
25
25
|
assert.match(guidance, /unchanged scheduled\nmonitoring stays quiet/)
|
|
26
26
|
})
|
|
27
27
|
|
|
28
|
+
test('shared guidance completes authorized contribution and release loops', () => {
|
|
29
|
+
const guidance = agentGuidance()
|
|
30
|
+
assert.match(guidance, /independent final-head review, required CI and\napplicable QA/)
|
|
31
|
+
assert.match(guidance, /mandate includes merge\nor release authority, then merge; release authority includes the merge needed for\nthe release. Otherwise leave the reviewed PR ready and state the remaining\nauthority/)
|
|
32
|
+
assert.match(guidance, /immutable\nartifact publication, the repository's reviewed GitHub publisher, registry\nreadback/)
|
|
33
|
+
assert.match(guidance, /Local QA,\ndiagnostics, auth-only work and deployment remain separate authority boundaries/)
|
|
34
|
+
})
|
|
35
|
+
|
|
28
36
|
test('package guidance resolution ignores a workspace shadow file', async () => {
|
|
29
37
|
const root = path.join(tmpdir(), `ez-guidance-${randomUUID()}`)
|
|
30
38
|
await mkdir(root, { recursive: true })
|
package/test/updates.test.mjs
CHANGED
|
@@ -210,8 +210,9 @@ test('bound dispatch follows active package root and retains private scope',asyn
|
|
|
210
210
|
assert.match(await fs.readFile(path.join(f.agent.workspace,'AGENTS.md'),'utf8'),/tools list --details/);
|
|
211
211
|
const config=await read(path.join(f.home,'config.json'));config.packageRoot=f.source;await atomic(path.join(f.home,'config.json'),config);
|
|
212
212
|
// A native launcher from the real package looks up its entry point in the active root.
|
|
213
|
-
await fs.writeFile(path.join(f.source,'bin/ezenciel-agents.mjs'),'#!/usr/bin/env node\nconsole.log(process.env.EZ_DEPLOYMENT_DIR)',{mode:0o755});
|
|
214
|
-
const result=await exec(path.join(f.home,'bin/ezenciel-agents'),['--version']
|
|
213
|
+
await fs.writeFile(path.join(f.source,'bin/ezenciel-agents.mjs'),'#!/usr/bin/env node\nconsole.log(process.env.EZ_DEPLOYMENT_DIR+"|"+process.env.EZ_CONTROL_DIR)',{mode:0o755});
|
|
214
|
+
const result=await exec(path.join(f.home,'bin/ezenciel-agents'),['--version'],{env:{...process.env,EZ_CONTROL_DIR:'/attacker'}});
|
|
215
|
+
assert.equal(result.stdout.trim(),f.config.deploymentDir+'|'+f.agent.controlDir);
|
|
215
216
|
assert((await fs.readFile(path.join(f.agent.workspace,'TOOLS.md'),'utf8')).startsWith('My notes'));
|
|
216
217
|
});
|
|
217
218
|
test('upgrade subprocess environment never inherits relay/provider secrets',()=>{
|