agentsys 5.11.0 → 5.12.0
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/.claude-plugin/marketplace.json +13 -13
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +7 -0
- package/lib/binary/index.js +203 -3
- package/package.json +1 -1
- package/site/content.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentsys",
|
|
3
3
|
"description": "20 specialized plugins for AI workflow automation - task orchestration, PR workflow, slop detection, code review, drift detection, enhancement analysis, documentation sync, unified static analysis, perf investigations, topic research, agent config linting, cross-tool AI consultation, structured AI debate, workflow pattern learning, codebase onboarding, contributor guidance, and Zig language support",
|
|
4
|
-
"version": "5.
|
|
4
|
+
"version": "5.12.0",
|
|
5
5
|
"owner": {
|
|
6
6
|
"name": "Avi Fenesh",
|
|
7
7
|
"url": "https://github.com/avifenesh"
|
|
@@ -40,11 +40,11 @@
|
|
|
40
40
|
"source": {
|
|
41
41
|
"source": "url",
|
|
42
42
|
"url": "https://github.com/agent-sh/prepare-delivery.git",
|
|
43
|
-
"commit": "
|
|
44
|
-
"ref": "v0.1.
|
|
43
|
+
"commit": "0e9685fe0e93e058af5ca9a0374f4f97e1db878c",
|
|
44
|
+
"ref": "v0.1.2"
|
|
45
45
|
},
|
|
46
46
|
"description": "Pre-ship quality gates: deslop, simplify, agnix, enhance, review loop, delivery validation, docs sync",
|
|
47
|
-
"version": "0.1.
|
|
47
|
+
"version": "0.1.2",
|
|
48
48
|
"category": "productivity",
|
|
49
49
|
"homepage": "https://github.com/agent-sh/prepare-delivery"
|
|
50
50
|
},
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
"source": {
|
|
79
79
|
"source": "url",
|
|
80
80
|
"url": "https://github.com/agent-sh/deslop.git",
|
|
81
|
-
"commit": "
|
|
81
|
+
"commit": "00301b9ce81d12caa38063e4a65b535ba5b011b2"
|
|
82
82
|
},
|
|
83
83
|
"description": "3-phase AI slop detection: regex patterns (HIGH), multi-pass analyzers (MEDIUM), CLI tools (LOW)",
|
|
84
84
|
"version": "1.0.0",
|
|
@@ -90,11 +90,11 @@
|
|
|
90
90
|
"source": {
|
|
91
91
|
"source": "url",
|
|
92
92
|
"url": "https://github.com/agent-sh/audit-project.git",
|
|
93
|
-
"commit": "
|
|
94
|
-
"ref": "v1.0.
|
|
93
|
+
"commit": "f703facec38765b6fd8cb5a2076c98bf14e5998e",
|
|
94
|
+
"ref": "v1.0.2"
|
|
95
95
|
},
|
|
96
96
|
"description": "Multi-agent iterative code review until zero issues remain",
|
|
97
|
-
"version": "1.0.
|
|
97
|
+
"version": "1.0.2",
|
|
98
98
|
"category": "development",
|
|
99
99
|
"homepage": "https://github.com/agent-sh/audit-project"
|
|
100
100
|
},
|
|
@@ -103,7 +103,7 @@
|
|
|
103
103
|
"source": {
|
|
104
104
|
"source": "url",
|
|
105
105
|
"url": "https://github.com/agent-sh/drift-detect.git",
|
|
106
|
-
"commit": "
|
|
106
|
+
"commit": "576aca37402068aef175c8a6002584e19cb6ea74"
|
|
107
107
|
},
|
|
108
108
|
"description": "Deep repository analysis to realign project plans with code reality - detects drift, gaps, and creates prioritized reconstruction plans",
|
|
109
109
|
"version": "1.0.0",
|
|
@@ -115,7 +115,7 @@
|
|
|
115
115
|
"source": {
|
|
116
116
|
"source": "url",
|
|
117
117
|
"url": "https://github.com/agent-sh/enhance.git",
|
|
118
|
-
"commit": "
|
|
118
|
+
"commit": "93f299e494a3a9ea74e82bd2d15bc1c517ce8f0c"
|
|
119
119
|
},
|
|
120
120
|
"description": "Master enhancement orchestrator: parallel analyzer execution for plugins, agents, docs, CLAUDE.md, and prompts with unified reporting",
|
|
121
121
|
"version": "1.0.0",
|
|
@@ -127,7 +127,7 @@
|
|
|
127
127
|
"source": {
|
|
128
128
|
"source": "url",
|
|
129
129
|
"url": "https://github.com/agent-sh/sync-docs.git",
|
|
130
|
-
"commit": "
|
|
130
|
+
"commit": "410e06739da101583b7238669f4acad7f5aea7ab"
|
|
131
131
|
},
|
|
132
132
|
"description": "Standalone documentation sync: find outdated refs, update CHANGELOG, flag stale examples based on code changes",
|
|
133
133
|
"version": "1.0.0",
|
|
@@ -165,7 +165,7 @@
|
|
|
165
165
|
"source": {
|
|
166
166
|
"source": "url",
|
|
167
167
|
"url": "https://github.com/agent-sh/learn.git",
|
|
168
|
-
"commit": "
|
|
168
|
+
"commit": "b3025d376a83841078f3ab5cf53b62c6960e46c3"
|
|
169
169
|
},
|
|
170
170
|
"description": "Research topics online and create comprehensive learning guides with RAG-optimized indexes",
|
|
171
171
|
"version": "1.0.0",
|
|
@@ -190,7 +190,7 @@
|
|
|
190
190
|
"source": {
|
|
191
191
|
"source": "url",
|
|
192
192
|
"url": "https://github.com/agent-sh/consult.git",
|
|
193
|
-
"commit": "
|
|
193
|
+
"commit": "8ce96f86c0ae67f732383a8b45c9994a7cd64d2a"
|
|
194
194
|
},
|
|
195
195
|
"description": "Cross-tool AI consultation: get second opinions from Gemini CLI, Codex CLI, Claude Code, OpenCode, or Copilot CLI with model and thinking effort control",
|
|
196
196
|
"version": "1.0.0",
|
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
9
9
|
|
|
10
10
|
## [Unreleased]
|
|
11
11
|
|
|
12
|
+
## [5.12.0] - 2026-04-26
|
|
13
|
+
|
|
14
|
+
### Propagated upstream releases
|
|
15
|
+
- agent-core v0.4.4 (fixer.js symlink + TOCTOU) -> v0.4.5 (client-side SLSA verification + sync allowlist) synced into all 13 consumers.
|
|
16
|
+
- agent-analyzer v0.8.0 -> v0.8.1 (cargo-deny CI).
|
|
17
|
+
- prepare-delivery v0.1.2, audit-project v1.0.2 (reviewer-contract markers + orchestrator blocked handling).
|
|
18
|
+
|
|
12
19
|
## [5.11.0] - 2026-04-26
|
|
13
20
|
|
|
14
21
|
### Changed
|
package/lib/binary/index.js
CHANGED
|
@@ -19,6 +19,22 @@
|
|
|
19
19
|
* script validates every zip entry before extracting it and rejects
|
|
20
20
|
* absolute, UNC, and parent-traversal entries.
|
|
21
21
|
*
|
|
22
|
+
* Verification chain (in order, each gate must pass to proceed):
|
|
23
|
+
* 1. TLS - https.get() pins the GitHub CA chain at the OS level.
|
|
24
|
+
* 2. SHA-256 sidecar - `<asset>.sha256` fetched from the same release and
|
|
25
|
+
* verified against the downloaded bytes. Closes basic tampering.
|
|
26
|
+
* 3. SLSA build provenance (optional / required) - `gh attestation verify`
|
|
27
|
+
* checks the Sigstore-signed attestation that agent-analyzer's release
|
|
28
|
+
* workflow publishes via `actions/attest-build-provenance`. This closes
|
|
29
|
+
* the "stolen release token uploads attacker binary + attacker sha256"
|
|
30
|
+
* hole that steps 1 and 2 cannot see.
|
|
31
|
+
*
|
|
32
|
+
* SLSA verification is SOFT by default: if `gh` is not on PATH we log
|
|
33
|
+
* a warning and proceed with just SHA-256. Set env var
|
|
34
|
+
* `AGENT_ANALYZER_REQUIRE_ATTESTATION=1` to make a missing `gh` a hard
|
|
35
|
+
* failure (recommended for CI). A present `gh` that reports a failed
|
|
36
|
+
* verification is ALWAYS a hard failure regardless of the env var.
|
|
37
|
+
*
|
|
22
38
|
* @module lib/binary
|
|
23
39
|
*/
|
|
24
40
|
|
|
@@ -572,6 +588,117 @@ function findBinaryInScratch(scratch, binaryBaseName) {
|
|
|
572
588
|
return null;
|
|
573
589
|
}
|
|
574
590
|
|
|
591
|
+
// ---------------------------------------------------------------------------
|
|
592
|
+
// SLSA build provenance verification
|
|
593
|
+
// ---------------------------------------------------------------------------
|
|
594
|
+
|
|
595
|
+
/**
|
|
596
|
+
* Result of an attempted SLSA attestation verification.
|
|
597
|
+
* @typedef {Object} SlsaResult
|
|
598
|
+
* @property {'verified'|'skipped'|'failed'} status
|
|
599
|
+
* @property {string} [reason] human-readable detail (for skipped/failed)
|
|
600
|
+
* @property {string} [stderr] captured stderr from `gh` (failed only)
|
|
601
|
+
*/
|
|
602
|
+
|
|
603
|
+
/**
|
|
604
|
+
* Default runner: spawn `gh attestation verify` and return the captured
|
|
605
|
+
* exit code, stdout, and stderr. Injectable for tests.
|
|
606
|
+
* @param {string} filePath
|
|
607
|
+
* @param {string} repo e.g. `agent-sh/agent-analyzer`
|
|
608
|
+
* @returns {{ status: number|null, stdout: string, stderr: string }}
|
|
609
|
+
*/
|
|
610
|
+
function defaultGhRunner(filePath, repo) {
|
|
611
|
+
try {
|
|
612
|
+
const stdout = cp.execFileSync(
|
|
613
|
+
'gh',
|
|
614
|
+
['attestation', 'verify', filePath, '--repo', repo, '--format', 'json'],
|
|
615
|
+
{
|
|
616
|
+
encoding: 'utf8',
|
|
617
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
618
|
+
timeout: 60000,
|
|
619
|
+
windowsHide: true
|
|
620
|
+
}
|
|
621
|
+
);
|
|
622
|
+
return { status: 0, stdout: stdout || '', stderr: '' };
|
|
623
|
+
} catch (err) {
|
|
624
|
+
return {
|
|
625
|
+
status: typeof err.status === 'number' ? err.status : null,
|
|
626
|
+
stdout: err.stdout ? String(err.stdout) : '',
|
|
627
|
+
stderr: err.stderr ? String(err.stderr) : (err.message || '')
|
|
628
|
+
};
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
/**
|
|
633
|
+
* Returns true if the `gh` CLI is on PATH. Uses a short, non-privileged probe.
|
|
634
|
+
* @param {function} [runner] optional probe; defaults to real `gh --version`
|
|
635
|
+
* @returns {boolean}
|
|
636
|
+
*/
|
|
637
|
+
function isGhAvailable(runner) {
|
|
638
|
+
if (typeof runner === 'function') {
|
|
639
|
+
try { return !!runner(); } catch (e) { return false; }
|
|
640
|
+
}
|
|
641
|
+
try {
|
|
642
|
+
cp.execFileSync('gh', ['--version'], {
|
|
643
|
+
stdio: 'ignore',
|
|
644
|
+
timeout: 5000,
|
|
645
|
+
windowsHide: true
|
|
646
|
+
});
|
|
647
|
+
return true;
|
|
648
|
+
} catch (e) {
|
|
649
|
+
return false;
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
/**
|
|
654
|
+
* Verify a downloaded asset's SLSA build provenance attestation via the
|
|
655
|
+
* GitHub CLI. The check is SOFT by default: if `gh` is not installed the
|
|
656
|
+
* function returns { status: 'skipped' } and the caller logs a warning. Set
|
|
657
|
+
* `requireAttestation` (or the env var) to make a missing `gh` a failure.
|
|
658
|
+
*
|
|
659
|
+
* A present `gh` that reports verification failure ALWAYS returns
|
|
660
|
+
* { status: 'failed' } regardless of `requireAttestation`; the caller is
|
|
661
|
+
* expected to abort in that case.
|
|
662
|
+
*
|
|
663
|
+
* @param {string} filePath absolute path to the downloaded archive
|
|
664
|
+
* @param {Object} [options]
|
|
665
|
+
* @param {string} [options.repo] e.g. `agent-sh/agent-analyzer`
|
|
666
|
+
* @param {boolean} [options.requireAttestation] defaults to env
|
|
667
|
+
* `AGENT_ANALYZER_REQUIRE_ATTESTATION === '1'`
|
|
668
|
+
* @param {function} [options.ghRunner] injectable runner for tests. Receives
|
|
669
|
+
* (filePath, repo), returns { status, stdout, stderr }.
|
|
670
|
+
* @param {function} [options.ghProbe] injectable gh-on-PATH probe for tests.
|
|
671
|
+
* @returns {SlsaResult}
|
|
672
|
+
*/
|
|
673
|
+
function verifySlsaAttestation(filePath, options) {
|
|
674
|
+
const opts = options || {};
|
|
675
|
+
const repo = opts.repo || GITHUB_REPO;
|
|
676
|
+
const runner = typeof opts.ghRunner === 'function' ? opts.ghRunner : defaultGhRunner;
|
|
677
|
+
const require_ = typeof opts.requireAttestation === 'boolean'
|
|
678
|
+
? opts.requireAttestation
|
|
679
|
+
: process.env.AGENT_ANALYZER_REQUIRE_ATTESTATION === '1';
|
|
680
|
+
|
|
681
|
+
const ghPresent = isGhAvailable(opts.ghProbe);
|
|
682
|
+
if (!ghPresent) {
|
|
683
|
+
const reason = '`gh` CLI not found on PATH';
|
|
684
|
+
if (require_) {
|
|
685
|
+
return { status: 'failed', reason: reason + ' (AGENT_ANALYZER_REQUIRE_ATTESTATION=1)' };
|
|
686
|
+
}
|
|
687
|
+
return { status: 'skipped', reason: reason };
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
const result = runner(filePath, repo);
|
|
691
|
+
if (result && result.status === 0) {
|
|
692
|
+
return { status: 'verified' };
|
|
693
|
+
}
|
|
694
|
+
return {
|
|
695
|
+
status: 'failed',
|
|
696
|
+
reason: 'gh attestation verify exited with status ' +
|
|
697
|
+
(result && result.status !== null ? result.status : 'unknown'),
|
|
698
|
+
stderr: (result && result.stderr) || ''
|
|
699
|
+
};
|
|
700
|
+
}
|
|
701
|
+
|
|
575
702
|
// ---------------------------------------------------------------------------
|
|
576
703
|
// Download + install
|
|
577
704
|
// ---------------------------------------------------------------------------
|
|
@@ -582,11 +709,19 @@ function findBinaryInScratch(scratch, binaryBaseName) {
|
|
|
582
709
|
* @param {Object} [options]
|
|
583
710
|
* @param {boolean} [options.skipChecksum=false] LOCAL DEV ONLY. Skips the
|
|
584
711
|
* `.sha256` sidecar fetch and verification. NEVER set this in production.
|
|
712
|
+
* @param {boolean} [options.skipAttestation=false] LOCAL DEV ONLY. Skips the
|
|
713
|
+
* SLSA attestation check entirely.
|
|
714
|
+
* @param {boolean} [options.requireAttestation] when true, a missing `gh`
|
|
715
|
+
* CLI becomes a hard failure. Defaults to
|
|
716
|
+
* `process.env.AGENT_ANALYZER_REQUIRE_ATTESTATION === '1'`.
|
|
717
|
+
* @param {function} [options.ghRunner] injectable runner for tests.
|
|
718
|
+
* @param {function} [options.ghProbe] injectable gh-on-PATH probe for tests.
|
|
585
719
|
* @returns {Promise<string>} path to the installed binary
|
|
586
720
|
*/
|
|
587
721
|
async function downloadBinary(ver, options) {
|
|
588
722
|
const opts = options || {};
|
|
589
723
|
const skipChecksum = opts.skipChecksum === true;
|
|
724
|
+
const skipAttestation = opts.skipAttestation === true;
|
|
590
725
|
|
|
591
726
|
const platformKey = getPlatformKey();
|
|
592
727
|
if (!platformKey) {
|
|
@@ -643,6 +778,47 @@ async function downloadBinary(ver, options) {
|
|
|
643
778
|
verifySha256(buf, expected, filename);
|
|
644
779
|
}
|
|
645
780
|
|
|
781
|
+
// --- 2b. Verify SLSA build provenance (optional / required) ------------
|
|
782
|
+
if (skipAttestation) {
|
|
783
|
+
process.stderr.write(
|
|
784
|
+
'[WARN] skipAttestation=true - SLSA verification disabled. ' +
|
|
785
|
+
'This is LOCAL DEV ONLY and MUST NOT be used in production.\n'
|
|
786
|
+
);
|
|
787
|
+
} else {
|
|
788
|
+
// `gh attestation verify` needs a real file. Persist buf to a tmp path,
|
|
789
|
+
// verify, then drop it. Extraction continues from the in-memory buf so
|
|
790
|
+
// we don't need the tmp file beyond the verify call.
|
|
791
|
+
const attestDir = fs.mkdtempSync(path.join(os.tmpdir(), 'agent-analyzer-slsa-'));
|
|
792
|
+
const attestFile = path.join(attestDir, filename);
|
|
793
|
+
try {
|
|
794
|
+
fs.writeFileSync(attestFile, buf);
|
|
795
|
+
const result = verifySlsaAttestation(attestFile, {
|
|
796
|
+
repo: GITHUB_REPO,
|
|
797
|
+
requireAttestation: opts.requireAttestation,
|
|
798
|
+
ghRunner: opts.ghRunner,
|
|
799
|
+
ghProbe: opts.ghProbe
|
|
800
|
+
});
|
|
801
|
+
if (result.status === 'verified') {
|
|
802
|
+
process.stderr.write('[OK] SLSA attestation verified for ' + filename + '\n');
|
|
803
|
+
} else if (result.status === 'skipped') {
|
|
804
|
+
process.stderr.write(
|
|
805
|
+
'[WARN] SLSA attestation check skipped: ' + result.reason + '. ' +
|
|
806
|
+
'Install the GitHub CLI (`gh`) to enable provenance verification. ' +
|
|
807
|
+
'Set AGENT_ANALYZER_REQUIRE_ATTESTATION=1 to require it.\n'
|
|
808
|
+
);
|
|
809
|
+
} else {
|
|
810
|
+
// 'failed'
|
|
811
|
+
throw new Error(
|
|
812
|
+
'SLSA attestation verification failed for ' + filename + ': ' +
|
|
813
|
+
result.reason + '. Refusing to execute binary.' +
|
|
814
|
+
(result.stderr ? '\n--- gh stderr ---\n' + result.stderr : '')
|
|
815
|
+
);
|
|
816
|
+
}
|
|
817
|
+
} finally {
|
|
818
|
+
rmrf(attestDir);
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
|
|
646
822
|
// --- 3. Extract to isolated scratch dir + validate entries -------------
|
|
647
823
|
const binaryBaseName = path.basename(binPath);
|
|
648
824
|
let scratch;
|
|
@@ -707,7 +883,13 @@ async function ensureBinary(options) {
|
|
|
707
883
|
}
|
|
708
884
|
}
|
|
709
885
|
|
|
710
|
-
return downloadBinary(targetVer, {
|
|
886
|
+
return downloadBinary(targetVer, {
|
|
887
|
+
skipChecksum: opts.skipChecksum === true,
|
|
888
|
+
skipAttestation: opts.skipAttestation === true,
|
|
889
|
+
requireAttestation: opts.requireAttestation,
|
|
890
|
+
ghRunner: opts.ghRunner,
|
|
891
|
+
ghProbe: opts.ghProbe
|
|
892
|
+
});
|
|
711
893
|
}
|
|
712
894
|
|
|
713
895
|
/**
|
|
@@ -730,11 +912,27 @@ function ensureBinarySync(options) {
|
|
|
730
912
|
|
|
731
913
|
const targetVer = (options && options.version) || ANALYZER_MIN_VERSION;
|
|
732
914
|
const skipChecksum = !!(options && options.skipChecksum);
|
|
915
|
+
const skipAttestation = !!(options && options.skipAttestation);
|
|
916
|
+
// Forward requireAttestation when explicitly set (tri-state: undefined
|
|
917
|
+
// lets the child fall back to the AGENT_ANALYZER_REQUIRE_ATTESTATION
|
|
918
|
+
// env var, matching ensureBinary()). Without this forwarding, a sync
|
|
919
|
+
// caller with requireAttestation:true would silently lose the hard-fail
|
|
920
|
+
// intent when gh is missing.
|
|
921
|
+
const requireAttestation = options && typeof options.requireAttestation === 'boolean'
|
|
922
|
+
? options.requireAttestation
|
|
923
|
+
: undefined;
|
|
733
924
|
const selfPath = __filename;
|
|
925
|
+
const ensureOpts = {
|
|
926
|
+
version: targetVer,
|
|
927
|
+
skipChecksum: skipChecksum,
|
|
928
|
+
skipAttestation: skipAttestation
|
|
929
|
+
};
|
|
930
|
+
if (requireAttestation !== undefined) {
|
|
931
|
+
ensureOpts.requireAttestation = requireAttestation;
|
|
932
|
+
}
|
|
734
933
|
const helperLines = [
|
|
735
934
|
'var b = require(' + JSON.stringify(selfPath) + ');',
|
|
736
|
-
'b.ensureBinary(
|
|
737
|
-
', skipChecksum: ' + JSON.stringify(skipChecksum) + ' })',
|
|
935
|
+
'b.ensureBinary(' + JSON.stringify(ensureOpts) + ')',
|
|
738
936
|
' .then(function(p) { process.stdout.write(p); })',
|
|
739
937
|
' .catch(function(e) { process.stderr.write(e.message); process.exit(1); });'
|
|
740
938
|
];
|
|
@@ -798,6 +996,8 @@ module.exports = {
|
|
|
798
996
|
assertSafeArchiveEntry,
|
|
799
997
|
assertInsideRoot,
|
|
800
998
|
downloadBinary,
|
|
999
|
+
verifySlsaAttestation,
|
|
1000
|
+
isGhAvailable,
|
|
801
1001
|
// Exported for tests only
|
|
802
1002
|
extractTarGzToScratch,
|
|
803
1003
|
extractZipToScratch,
|
package/package.json
CHANGED
package/site/content.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"url": "https://agent-sh.github.io/agentsys",
|
|
6
6
|
"repo": "https://github.com/agent-sh/agentsys",
|
|
7
7
|
"npm": "https://www.npmjs.com/package/agentsys",
|
|
8
|
-
"version": "5.
|
|
8
|
+
"version": "5.12.0",
|
|
9
9
|
"author": "Avi Fenesh",
|
|
10
10
|
"author_url": "https://github.com/avifenesh"
|
|
11
11
|
},
|