@event4u/agent-config 14.16.0 → 14.17.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/.augment-plugin/marketplace.json +3 -3
- package/.augment-plugin/plugin.json +1 -1
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +83 -210
- package/README.md +1 -1
- package/dist/agent-src/commands/analyze/inbox.md +172 -6
- package/dist/agent-src/commands/fix/commit-messages.md +336 -0
- package/dist/agent-src/commands/fix.md +5 -3
- package/dist/agent-src/rules/commit-conventions.md +1 -1
- package/dist/agent-src/skills/aws-infrastructure/SKILL.md +41 -0
- package/dist/agent-src/skills/conventional-commits-writing/SKILL.md +234 -4
- package/dist/agent-src/skills/terraform/SKILL.md +29 -0
- package/dist/agent-src/skills/threat-modeling/data/reasoning.csv +1 -0
- package/dist/agent-src/skills/threat-modeling/data/surfaces.csv +1 -0
- package/dist/agent-src/skills/threat-modeling/data/threats.csv +5 -0
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/cli-delegate/cmd_explain.js +24 -112
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +42 -16
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +3 -3
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +6 -5
- package/dist/discovery/trust-report.md +2 -2
- package/dist/discovery/workspaces.json +5 -4
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/package.json +1 -1
- package/src/config/web-launch-readiness.json +1 -1
- package/src/scripts/_cli/explain_last/index.ts +1 -1
- package/src/scripts/_cli/explain_last/memory.ts +8 -104
- package/src/scripts/check_artefact_count_messaging.ts +9 -0
- package/src/scripts/check_release_highlights.ts +77 -4
- package/src/scripts/check_web_launch_readiness.ts +295 -15
- package/src/scripts/measure_release_mix.ts +384 -0
- package/src/scripts/release_mix_taxonomy.json +172 -0
- package/src/scripts/attest_artifact.ts +0 -193
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env tsx
|
|
2
|
-
/**
|
|
3
|
-
* Content attestation for any artifact a hook would INJECT.
|
|
4
|
-
*
|
|
5
|
-
* `road-to-skill-ecosystem-runtime-enforcement` Phase 5, Steps 6-7, and the
|
|
6
|
-
* ordering in that step is the argument: attestation is the **precondition** for
|
|
7
|
-
* auto-injection, not a follow-up to it.
|
|
8
|
-
*
|
|
9
|
-
* ── The threat, concretely ──────────────────────────────────────────────────
|
|
10
|
-
* A hook that reads a tracked file and injects its contents into the model's
|
|
11
|
-
* context turns that file into a **standing injection amplifier**. Whoever can
|
|
12
|
-
* write the file can write the agent's instructions, on every session, without
|
|
13
|
-
* a review — which is `untrusted-input-defense`'s found-instructions case
|
|
14
|
-
* arriving through a file the repository itself vouches for. The file being
|
|
15
|
-
* tracked is not the control: a tracked file changes in a pull request, and a
|
|
16
|
-
* pull request that changes an injected file is indistinguishable in the diff
|
|
17
|
-
* from one that changes documentation.
|
|
18
|
-
*
|
|
19
|
-
* ── The contract ────────────────────────────────────────────────────────────
|
|
20
|
-
* An injectable artifact carries a sidecar `<file>.attest.json` holding the
|
|
21
|
-
* sha256 of its bytes and the date the attestation was recorded. Before
|
|
22
|
-
* injecting, a caller asks {@link verifyArtifact}:
|
|
23
|
-
*
|
|
24
|
-
* - hash matches → `ok`, inject.
|
|
25
|
-
* - hash differs → `mismatch`, REFUSE. The content changed since a human
|
|
26
|
-
* vouched for it; re-attesting is a deliberate act with a diff.
|
|
27
|
-
* - no sidecar → `unattested`, REFUSE. **Not "allow because nothing said
|
|
28
|
-
* no"** — that default makes the whole mechanism opt-out, and the file an
|
|
29
|
-
* attacker adds is exactly the one with no sidecar.
|
|
30
|
-
* - file missing → `absent`, REFUSE.
|
|
31
|
-
*
|
|
32
|
-
* ── What this does NOT claim ────────────────────────────────────────────────
|
|
33
|
-
* The sidecar is committed beside the artifact, so an attacker who can write
|
|
34
|
-
* both can write a consistent pair. This is NOT a cryptographic signature and
|
|
35
|
-
* does not pretend to be one. What it buys is that the change becomes VISIBLE:
|
|
36
|
-
* a diff that touches an injected file must also touch its attestation, and a
|
|
37
|
-
* hash line changing in a review is a question, where a prose change in the same
|
|
38
|
-
* file is not. Making a change reviewable is the honest claim; making it
|
|
39
|
-
* impossible would need a key this repository does not have.
|
|
40
|
-
*
|
|
41
|
-
* Exit codes: 0 verified · 1 refused (mismatch / unattested / absent) · 2 usage.
|
|
42
|
-
*
|
|
43
|
-
* Usage:
|
|
44
|
-
* ./scripts-run src/scripts/attest_artifact --record <file>
|
|
45
|
-
* ./scripts-run src/scripts/attest_artifact --verify <file>
|
|
46
|
-
* ./scripts-run src/scripts/attest_artifact --verify <file> --json
|
|
47
|
-
*/
|
|
48
|
-
import * as crypto from 'node:crypto';
|
|
49
|
-
import * as fs from 'node:fs';
|
|
50
|
-
import * as path from 'node:path';
|
|
51
|
-
import process from 'node:process';
|
|
52
|
-
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
53
|
-
|
|
54
|
-
const _HERE = fileURLToPath(import.meta.url);
|
|
55
|
-
|
|
56
|
-
/** Sidecar suffix. Beside the artifact, so a move takes the attestation with it. */
|
|
57
|
-
export const ATTEST_SUFFIX = '.attest.json';
|
|
58
|
-
|
|
59
|
-
export type AttestStatus = 'ok' | 'mismatch' | 'unattested' | 'absent';
|
|
60
|
-
|
|
61
|
-
export interface Attestation {
|
|
62
|
-
schema_version: 1;
|
|
63
|
-
/** sha256 of the artifact's bytes, hex. */
|
|
64
|
-
sha256: string;
|
|
65
|
-
/** `YYYY-MM-DD` the attestation was recorded. */
|
|
66
|
-
recorded_at: string;
|
|
67
|
-
/** Bytes at record time — a cheap second signal that costs nothing to store. */
|
|
68
|
-
bytes: number;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export interface Verdict {
|
|
72
|
-
status: AttestStatus;
|
|
73
|
-
/** True only for `ok`. Every other status refuses. */
|
|
74
|
-
inject: boolean;
|
|
75
|
-
detail: string;
|
|
76
|
-
expected?: string;
|
|
77
|
-
actual?: string;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export function sidecarPath(artifact: string): string {
|
|
81
|
-
return `${artifact}${ATTEST_SUFFIX}`;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export function hashFile(artifact: string): string {
|
|
85
|
-
return crypto.createHash('sha256').update(fs.readFileSync(artifact)).digest('hex');
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Verify an artifact against its sidecar.
|
|
90
|
-
*
|
|
91
|
-
* Every non-`ok` status sets `inject: false`. That is the whole safety property
|
|
92
|
-
* and it is expressed as data rather than left to each caller's `if`: a caller
|
|
93
|
-
* that reads `verdict.inject` cannot accidentally treat `unattested` as
|
|
94
|
-
* permissive, which is the mistake an `status === 'mismatch'` check invites.
|
|
95
|
-
*/
|
|
96
|
-
export function verifyArtifact(artifact: string, today?: string): Verdict {
|
|
97
|
-
void today;
|
|
98
|
-
if (!fs.existsSync(artifact)) {
|
|
99
|
-
return { status: 'absent', inject: false, detail: `${artifact} does not exist` };
|
|
100
|
-
}
|
|
101
|
-
const side = sidecarPath(artifact);
|
|
102
|
-
if (!fs.existsSync(side)) {
|
|
103
|
-
return {
|
|
104
|
-
status: 'unattested',
|
|
105
|
-
inject: false,
|
|
106
|
-
detail:
|
|
107
|
-
`${artifact} has no ${ATTEST_SUFFIX} sidecar — REFUSED. An unattested artifact is ` +
|
|
108
|
-
'not "allowed because nothing said no": that default makes attestation opt-out, and ' +
|
|
109
|
-
'the file an attacker adds is precisely the one with no sidecar.',
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
let att: Partial<Attestation>;
|
|
113
|
-
try {
|
|
114
|
-
att = JSON.parse(fs.readFileSync(side, 'utf8')) as Partial<Attestation>;
|
|
115
|
-
} catch (e) {
|
|
116
|
-
return {
|
|
117
|
-
status: 'unattested',
|
|
118
|
-
inject: false,
|
|
119
|
-
detail: `${side} does not parse (${e instanceof Error ? e.message : String(e)}) — treated as absent`,
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
const actual = hashFile(artifact);
|
|
123
|
-
if (typeof att.sha256 !== 'string' || att.sha256 === '') {
|
|
124
|
-
return { status: 'unattested', inject: false, detail: `${side} carries no sha256`, actual };
|
|
125
|
-
}
|
|
126
|
-
if (att.sha256 !== actual) {
|
|
127
|
-
return {
|
|
128
|
-
status: 'mismatch',
|
|
129
|
-
inject: false,
|
|
130
|
-
detail:
|
|
131
|
-
`${artifact} changed since it was attested — REFUSED. Re-attest deliberately ` +
|
|
132
|
-
`(--record) so the new hash lands in a diff a reviewer sees.`,
|
|
133
|
-
expected: att.sha256,
|
|
134
|
-
actual,
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
return { status: 'ok', inject: true, detail: `${artifact} matches its attestation`, expected: att.sha256, actual };
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/** Record (or re-record) an attestation. Deliberate, and it lands in a diff. */
|
|
141
|
-
export function recordAttestation(artifact: string, today = new Date().toISOString().slice(0, 10)): Attestation {
|
|
142
|
-
const att: Attestation = {
|
|
143
|
-
schema_version: 1,
|
|
144
|
-
sha256: hashFile(artifact),
|
|
145
|
-
recorded_at: today,
|
|
146
|
-
bytes: fs.statSync(artifact).size,
|
|
147
|
-
};
|
|
148
|
-
fs.writeFileSync(sidecarPath(artifact), `${JSON.stringify(att, null, 2)}\n`, 'utf8');
|
|
149
|
-
return att;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
export function main(argv: string[] = process.argv.slice(2)): number {
|
|
153
|
-
const usage =
|
|
154
|
-
'usage: attest_artifact (--record | --verify) <file> [--json]\n' +
|
|
155
|
-
' --verify exits 1 on mismatch, unattested or absent. Refusal is the default.\n';
|
|
156
|
-
if (argv.includes('-h') || argv.includes('--help')) {
|
|
157
|
-
process.stdout.write(usage);
|
|
158
|
-
return 0;
|
|
159
|
-
}
|
|
160
|
-
const asJson = argv.includes('--json');
|
|
161
|
-
const record = argv.includes('--record');
|
|
162
|
-
const verify = argv.includes('--verify');
|
|
163
|
-
const file = argv.find((a) => !a.startsWith('--'));
|
|
164
|
-
if (record === verify || file === undefined) {
|
|
165
|
-
process.stderr.write(`attest_artifact: error: exactly one of --record / --verify plus a file\n${usage}`);
|
|
166
|
-
return 2;
|
|
167
|
-
}
|
|
168
|
-
const target = path.resolve(file);
|
|
169
|
-
if (record) {
|
|
170
|
-
if (!fs.existsSync(target)) {
|
|
171
|
-
process.stderr.write(`attest_artifact: ${file} does not exist\n`);
|
|
172
|
-
return 2;
|
|
173
|
-
}
|
|
174
|
-
const att = recordAttestation(target);
|
|
175
|
-
process.stdout.write(`✅ attested ${file} — sha256 ${att.sha256.slice(0, 16)}… (${String(att.bytes)} bytes)\n`);
|
|
176
|
-
return 0;
|
|
177
|
-
}
|
|
178
|
-
const v = verifyArtifact(target);
|
|
179
|
-
if (asJson) {
|
|
180
|
-
process.stdout.write(`${JSON.stringify(v, null, 2)}\n`);
|
|
181
|
-
} else if (v.inject) {
|
|
182
|
-
process.stdout.write(`✅ ${v.detail}\n`);
|
|
183
|
-
} else {
|
|
184
|
-
process.stderr.write(`❌ [${v.status}] ${v.detail}\n`);
|
|
185
|
-
}
|
|
186
|
-
return v.inject ? 0 : 1;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
/* c8 ignore start */
|
|
190
|
-
if (process.argv[1] !== undefined && pathToFileURL(path.resolve(process.argv[1])).href === pathToFileURL(_HERE).href) {
|
|
191
|
-
process.exit(main());
|
|
192
|
-
}
|
|
193
|
-
/* c8 ignore stop */
|