@yunhozz/arc 0.1.2 → 0.1.3
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/MANIFEST.sha256 +75 -36
- package/claude/agents/arc-coder.md +10 -9
- package/claude/agents/arc-planner.md +13 -12
- package/claude/agents/arc-qa.md +9 -8
- package/claude/agents/arc-reviewer.md +11 -10
- package/claude/agents/arc-scouter.md +10 -9
- package/claude/skill/SKILL.md +13 -17
- package/claude/skill/hooks/role-git-guard.mjs +3 -83
- package/claude/skill/hooks/runtime-gate.mjs +12 -0
- package/claude/skill/models.toml +11 -11
- package/claude/skill/references/commit.md +8 -9
- package/claude/skill/references/git-recovery.md +1 -1
- package/claude/skill/references/handoff-prep.md +8 -8
- package/claude/skill/references/handoff.md +8 -8
- package/claude/skill/references/limits.md +4 -4
- package/claude/skill/references/planning.md +9 -9
- package/claude/skill/references/verification.md +10 -10
- package/claude/skill/references/visual-companion.md +2 -3
- package/claude/skill/runtime/adapters/claude.mjs +81 -0
- package/claude/skill/runtime/adapters/codex.mjs +63 -0
- package/claude/skill/runtime/capabilities.mjs +32 -0
- package/claude/skill/runtime/evaluate.mjs +103 -0
- package/claude/skill/runtime/gate.mjs +71 -0
- package/claude/skill/runtime/git-evidence.mjs +114 -0
- package/claude/skill/runtime/git-query.mjs +88 -0
- package/claude/skill/runtime/identity.mjs +27 -0
- package/claude/skill/runtime/operations.mjs +6 -0
- package/claude/skill/runtime/role-policy.json +607 -0
- package/claude/skill/runtime/schema.mjs +78 -0
- package/claude/skill/runtime/store.mjs +63 -0
- package/claude/skill/scripts/model_config.py +78 -18
- package/codex/agents/arc-coder.toml +8 -8
- package/codex/agents/arc-planner.toml +9 -9
- package/codex/agents/arc-qa.toml +6 -6
- package/codex/agents/arc-reviewer.toml +7 -7
- package/codex/agents/arc-scouter.toml +6 -6
- package/codex/skill/SKILL.md +15 -19
- package/codex/skill/hooks/runtime-gate.mjs +10 -0
- package/codex/skill/models.toml +11 -11
- package/codex/skill/references/commit.md +9 -9
- package/codex/skill/references/git-recovery.md +1 -1
- package/codex/skill/references/handoff-prep.md +9 -10
- package/codex/skill/references/handoff-worktree.md +1 -1
- package/codex/skill/references/handoff.md +9 -9
- package/codex/skill/references/limits.md +4 -4
- package/codex/skill/references/planning.md +11 -12
- package/codex/skill/references/verification.md +10 -11
- package/codex/skill/references/visual-companion.md +3 -3
- package/codex/skill/runtime/adapters/claude.mjs +81 -0
- package/codex/skill/runtime/adapters/codex.mjs +63 -0
- package/codex/skill/runtime/capabilities.mjs +32 -0
- package/codex/skill/runtime/evaluate.mjs +103 -0
- package/codex/skill/runtime/gate.mjs +71 -0
- package/codex/skill/runtime/git-evidence.mjs +114 -0
- package/codex/skill/runtime/git-query.mjs +88 -0
- package/codex/skill/runtime/identity.mjs +27 -0
- package/codex/skill/runtime/operations.mjs +6 -0
- package/codex/skill/runtime/role-policy.json +607 -0
- package/codex/skill/runtime/schema.mjs +78 -0
- package/codex/skill/runtime/store.mjs +63 -0
- package/lib/models/profiles.mjs +41 -4
- package/lib/policy/claude-hook.mjs +57 -17
- package/lib/policy/render.mjs +1 -0
- package/lib/policy/role-policy.json +38 -8
- package/lib/runtime/adapters/claude.mjs +81 -0
- package/lib/runtime/adapters/codex.mjs +63 -0
- package/lib/runtime/capabilities.mjs +32 -0
- package/lib/runtime/evaluate.mjs +103 -0
- package/lib/runtime/gate.mjs +71 -0
- package/lib/runtime/git-evidence.mjs +114 -0
- package/lib/runtime/git-query.mjs +88 -0
- package/lib/runtime/identity.mjs +27 -0
- package/lib/runtime/operations.mjs +6 -0
- package/lib/runtime/schema.mjs +78 -0
- package/lib/runtime/store.mjs +63 -0
- package/package.json +1 -1
- package/scripts/probe-runtime-hooks.mjs +55 -0
- package/scripts/update-runtime-assets.mjs +19 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import {pathToFileURL} from 'node:url';
|
|
5
|
+
import {summarizeProbe} from '../lib/runtime/capabilities.mjs';
|
|
6
|
+
|
|
7
|
+
// This tool does not install hooks, grant trust, or execute the tool being probed.
|
|
8
|
+
// Host-result receipts must be supplied by the trusted probe host after checking
|
|
9
|
+
// actual non-execution. A hook-decision receipt alone never verifies denial.
|
|
10
|
+
export function writeProbeReceipt(receipt,data,write = fs.writeFileSync) {
|
|
11
|
+
let fd;
|
|
12
|
+
try {
|
|
13
|
+
fd=fs.openSync(receipt,fs.constants.O_WRONLY|fs.constants.O_CREAT|fs.constants.O_EXCL|fs.constants.O_NOFOLLOW,0o600);
|
|
14
|
+
write(fd,JSON.stringify(data)+'\n');
|
|
15
|
+
} catch(error) {
|
|
16
|
+
if(fd !== undefined) fs.unlinkSync(receipt);
|
|
17
|
+
throw error;
|
|
18
|
+
} finally { if(fd !== undefined) fs.closeSync(fd); }
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if(process.argv[1] && import.meta.url === pathToFileURL(path.resolve(process.argv[1])).href) {
|
|
22
|
+
try {
|
|
23
|
+
const [mode,...args] = process.argv.slice(2);
|
|
24
|
+
const options = {};
|
|
25
|
+
for(let i=0;i<args.length;i+=2) {
|
|
26
|
+
if(!['--platform','--session','--version','--receipt','--attempt','--scratch'].includes(args[i]) || !args[i+1]) throw new Error('Invalid probe options');
|
|
27
|
+
options[args[i].slice(2)] = args[i+1];
|
|
28
|
+
}
|
|
29
|
+
const {platform,session:sessionRef,version:platformVersion,attempt:attemptRef,scratch,receipt} = options;
|
|
30
|
+
if(!['codex','claude'].includes(platform) || !sessionRef || !platformVersion || !attemptRef || !receipt || !path.isAbsolute(receipt)) throw new Error('Explicit platform, session, version and absolute scratch receipt required');
|
|
31
|
+
if(mode === 'summary') {
|
|
32
|
+
const parsed = JSON.parse(fs.readFileSync(receipt,'utf8'));
|
|
33
|
+
console.log(JSON.stringify(summarizeProbe(Array.isArray(parsed)?parsed:[parsed],{platform,sessionRef,platformVersion,attemptRef})));
|
|
34
|
+
} else if(mode === 'hook') {
|
|
35
|
+
const input = JSON.parse(fs.readFileSync(0,'utf8'));
|
|
36
|
+
if(input.hook_event_name !== 'PreToolUse' || typeof input.tool_name !== 'string' || !/^[A-Za-z_][A-Za-z0-9_]{0,79}$/.test(input.tool_name)) throw new Error('Only PreToolUse canary requests supported');
|
|
37
|
+
if(!scratch || !path.isAbsolute(scratch)) throw new Error('Explicit private scratch directory required');
|
|
38
|
+
const realScratch=fs.realpathSync(scratch);
|
|
39
|
+
const stat=fs.lstatSync(scratch);
|
|
40
|
+
if(stat.isSymbolicLink() || !stat.isDirectory() || (stat.mode & 0o077) !== 0 ||
|
|
41
|
+
(typeof process.getuid === 'function' && stat.uid !== process.getuid()) ||
|
|
42
|
+
path.dirname(realScratch) !== fs.realpathSync(os.tmpdir()) ||
|
|
43
|
+
!path.basename(realScratch).startsWith('arc-runtime-probe-') ||
|
|
44
|
+
fs.realpathSync(path.dirname(path.resolve(receipt))) !== realScratch) throw new Error('Receipt must be directly inside private probe scratch');
|
|
45
|
+
const data={source:'native',kind:'hook-decision',platform,platformVersion,sessionRef,attemptRef,
|
|
46
|
+
event:'PreToolUse',toolPath:input.tool_name,
|
|
47
|
+
operation:input.tool_name === 'Agent' ? (platform === 'codex' ? 'spawn_agent' : 'Agent') : null,decision:'deny'};
|
|
48
|
+
// Exclusive creation prevents truncation and symlink following. No staging
|
|
49
|
+
// file is needed; remove our own new receipt if its write fails.
|
|
50
|
+
writeProbeReceipt(receipt,data);
|
|
51
|
+
console.log(JSON.stringify({hookSpecificOutput:{hookEventName:'PreToolUse',permissionDecision:'deny',permissionDecisionReason:'ARC scratch canary deny'}}));
|
|
52
|
+
} else throw new Error('Expected hook or summary mode');
|
|
53
|
+
} catch(error) { console.error(error.message); process.exitCode=1; }
|
|
54
|
+
|
|
55
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import {fileURLToPath} from 'node:url';
|
|
4
|
+
const args=process.argv.slice(2);const i=args.indexOf('--root');
|
|
5
|
+
const root=i<0?fileURLToPath(new URL('../',import.meta.url)):path.resolve(args[i+1]);
|
|
6
|
+
const check=args.includes('--check');
|
|
7
|
+
function safe(filename,directory=false){
|
|
8
|
+
const relative=path.relative(root,filename);if(relative.startsWith('..')||path.isAbsolute(relative))throw Error('Payload outside root');
|
|
9
|
+
let cursor=root;for(const part of relative.split(path.sep).filter(Boolean)){cursor=path.join(cursor,part);let stat;try{stat=fs.lstatSync(cursor);}catch(error){if(error.code==='ENOENT')continue;throw error;}if(stat.isSymbolicLink()||(!stat.isFile()&&!stat.isDirectory()))throw Error(`Unsafe runtime asset: ${cursor}`);}
|
|
10
|
+
if(fs.existsSync(filename)){const s=fs.lstatSync(filename);if(directory?!s.isDirectory():!s.isFile())throw Error(`Unexpected runtime asset type: ${filename}`);}
|
|
11
|
+
}
|
|
12
|
+
function sources(relative){const dir=path.join(root,relative);safe(dir,true);const result=[];for(const entry of fs.readdirSync(dir).sort()){const rel=path.join(relative,entry);const file=path.join(root,rel);safe(file,fs.lstatSync(file).isDirectory());if(fs.lstatSync(file).isDirectory())result.push(...sources(rel));else if(entry.endsWith('.mjs'))result.push(rel);else throw Error(`Unexpected canonical runtime file: ${rel}`);}return result;}
|
|
13
|
+
try{
|
|
14
|
+
safe(root,true);const entries=sources('lib/runtime').map(name=>[path.relative('lib/runtime',name),fs.readFileSync(path.join(root,name))]);
|
|
15
|
+
const policy=path.join(root,'lib/policy/role-policy.json');safe(policy);entries.push(['role-policy.json',fs.readFileSync(policy)]);
|
|
16
|
+
const outputs=[];for(const platform of ['codex','claude'])for(const [name,bytes]of entries){const filename=path.join(root,platform,'skill/runtime',name);safe(filename);outputs.push({filename,bytes});}
|
|
17
|
+
let drift=false;for(const {filename,bytes}of outputs){if(!fs.existsSync(filename)||!fs.readFileSync(filename).equals(bytes)){drift=true;if(!check){fs.mkdirSync(path.dirname(filename),{recursive:true});fs.writeFileSync(filename,bytes);}}}
|
|
18
|
+
if(check&&drift){console.error('Runtime payload drift');process.exitCode=1;}else console.log(`Runtime payload ${check?'verified':'generated'} (${outputs.length} files)`);
|
|
19
|
+
}catch(error){console.error(error.message);process.exitCode=1;}
|