repo-agent-brief 0.3.0 → 0.4.1
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/README.md +26 -0
- package/package.json +6 -2
- package/skills/repo-agent-brief/SKILL.md +9 -0
- package/src/cli.js +15 -4
- package/src/index.js +57 -2
package/README.md
CHANGED
|
@@ -45,6 +45,7 @@ Options:
|
|
|
45
45
|
- `--max-file-bytes N` — max bytes to read per context file. Default: `12000`.
|
|
46
46
|
- `--no-snippets` — omit source snippets.
|
|
47
47
|
- `--diff [ref]` — include changed files, insertions/deletions, and high-impact path warnings versus a git ref. Defaults to `HEAD` when no ref is provided.
|
|
48
|
+
- `--bundle [dir]` — write a durable handoff bundle with `brief.md`, `brief.json`, and `verification.md`. Default: `.agent-brief`.
|
|
48
49
|
- `--fail-on-high-risk` — exit `2` if high-severity risk patterns are found.
|
|
49
50
|
|
|
50
51
|
Examples:
|
|
@@ -53,6 +54,7 @@ Examples:
|
|
|
53
54
|
agent-brief . > AGENT_BRIEF.md
|
|
54
55
|
agent-brief ~/dev/my-app --format json
|
|
55
56
|
agent-brief . --diff origin/main
|
|
57
|
+
agent-brief . --diff HEAD --bundle
|
|
56
58
|
agent-brief . --fail-on-high-risk
|
|
57
59
|
```
|
|
58
60
|
|
|
@@ -79,6 +81,26 @@ Every brief now includes a `Suggested verification plan` section. It turns disco
|
|
|
79
81
|
|
|
80
82
|
If you pass `--diff`, the plan gets sharper: docs-only changes downgrade expensive checks, source changes promote tests/typechecks, and CI/deploy/infra/lockfile changes add a manual high-impact-path review. If no test/lint/build commands are found, the plan calls that gap out plainly so the agent does not pretend verification happened.
|
|
81
83
|
|
|
84
|
+
## Handoff bundles
|
|
85
|
+
|
|
86
|
+
For longer-running work, use `--bundle` to leave a stable artifact another agent or human can inspect later:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
agent-brief . --diff HEAD --bundle
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
This writes:
|
|
93
|
+
|
|
94
|
+
- `.agent-brief/brief.md` — the full human-readable project brief.
|
|
95
|
+
- `.agent-brief/brief.json` — the same data for automation.
|
|
96
|
+
- `.agent-brief/verification.md` — a focused checklist of the exact checks the next agent should run or document.
|
|
97
|
+
|
|
98
|
+
Use a custom directory when you want to attach the bundle to a ticket, run log, or CI artifact:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
agent-brief . --diff origin/main --bundle artifacts/agent-brief
|
|
102
|
+
```
|
|
103
|
+
|
|
82
104
|
## Why this exists
|
|
83
105
|
|
|
84
106
|
The current agent tooling boom has plenty of orchestration, MCP servers, and observability dashboards. The missing small thing is a cheap, local preflight that gives any agent the same crisp project orientation before it spends tokens or touches files.
|
|
@@ -105,3 +127,7 @@ MIT
|
|
|
105
127
|
## Agent Skill
|
|
106
128
|
|
|
107
129
|
This package includes an OpenClaw/Claude-style skill at `skills/repo-agent-brief` that teaches agents to run repo preflight and diff-aware handoff briefs before editing or reviewing code.
|
|
130
|
+
|
|
131
|
+
## Release Automation
|
|
132
|
+
|
|
133
|
+
This package is published from GitHub Actions using npm Trusted Publishing with provenance. Releases are built on GitHub-hosted runners and no long-lived npm publish token is required.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "repo-agent-brief",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Generate concise, safety-aware project briefs for coding agents.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -32,7 +32,8 @@
|
|
|
32
32
|
"license": "MIT",
|
|
33
33
|
"repository": {
|
|
34
34
|
"type": "git",
|
|
35
|
-
"url": "git+https://github.com/BuiltByEcho/agent-brief.git"
|
|
35
|
+
"url": "git+https://github.com/BuiltByEcho/agent-brief.git",
|
|
36
|
+
"directory": "packages/repo-agent-brief"
|
|
36
37
|
},
|
|
37
38
|
"bugs": {
|
|
38
39
|
"url": "https://github.com/BuiltByEcho/agent-brief/issues"
|
|
@@ -40,5 +41,8 @@
|
|
|
40
41
|
"homepage": "https://github.com/BuiltByEcho/agent-brief#readme",
|
|
41
42
|
"engines": {
|
|
42
43
|
"node": ">=20"
|
|
44
|
+
},
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public"
|
|
43
47
|
}
|
|
44
48
|
}
|
|
@@ -29,6 +29,14 @@ For machine-readable automation:
|
|
|
29
29
|
npx repo-agent-brief . --format json > agent-brief.json
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
+
For durable handoffs:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npx repo-agent-brief . --diff HEAD --bundle
|
|
36
|
+
sed -n '1,220p' .agent-brief/brief.md
|
|
37
|
+
sed -n '1,160p' .agent-brief/verification.md
|
|
38
|
+
```
|
|
39
|
+
|
|
32
40
|
## When to use
|
|
33
41
|
|
|
34
42
|
- First pass in an unfamiliar repo.
|
|
@@ -48,6 +56,7 @@ npx repo-agent-brief . --format json > agent-brief.json
|
|
|
48
56
|
```bash
|
|
49
57
|
npx repo-agent-brief .
|
|
50
58
|
npx repo-agent-brief . --diff HEAD
|
|
59
|
+
npx repo-agent-brief . --diff HEAD --bundle
|
|
51
60
|
npx repo-agent-brief . --diff origin/main --fail-on-high-risk
|
|
52
61
|
npx repo-agent-brief . --no-snippets
|
|
53
62
|
```
|
package/src/cli.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { resolve } from 'node:path';
|
|
3
|
-
import { generateBrief, formatJson, formatMarkdown } from './index.js';
|
|
3
|
+
import { generateBrief, formatJson, formatMarkdown, writeBundle } from './index.js';
|
|
4
4
|
|
|
5
5
|
function parseArgs(argv) {
|
|
6
|
-
const args = { path: '.', format: 'markdown', maxFileBytes: 12000, noSnippets: false, failOnHighRisk: false, diffRef: null };
|
|
6
|
+
const args = { path: '.', format: 'markdown', maxFileBytes: 12000, noSnippets: false, failOnHighRisk: false, diffRef: null, bundleDir: null };
|
|
7
7
|
for (let i = 0; i < argv.length; i++) {
|
|
8
8
|
const arg = argv[i];
|
|
9
9
|
if (arg === '--format' || arg === '-f') args.format = argv[++i];
|
|
@@ -11,6 +11,7 @@ function parseArgs(argv) {
|
|
|
11
11
|
else if (arg === '--no-snippets') args.noSnippets = true;
|
|
12
12
|
else if (arg === '--fail-on-high-risk') args.failOnHighRisk = true;
|
|
13
13
|
else if (arg === '--diff') args.diffRef = argv[i + 1] && !argv[i + 1].startsWith('-') ? argv[++i] : 'HEAD';
|
|
14
|
+
else if (arg === '--bundle') args.bundleDir = argv[i + 1] && !argv[i + 1].startsWith('-') ? argv[++i] : '.agent-brief';
|
|
14
15
|
else if (arg === '--help' || arg === '-h') args.help = true;
|
|
15
16
|
else if (!arg.startsWith('-')) args.path = arg;
|
|
16
17
|
else throw new Error(`Unknown option: ${arg}`);
|
|
@@ -29,13 +30,15 @@ Options:
|
|
|
29
30
|
--max-file-bytes N Max bytes to read per context file (default: 12000)
|
|
30
31
|
--no-snippets Omit context snippets from output
|
|
31
32
|
--diff [ref] Include changed files vs ref (default: HEAD)
|
|
33
|
+
--bundle [dir] Write brief.md, brief.json, and verification.md (default: .agent-brief)
|
|
32
34
|
--fail-on-high-risk Exit 2 if high-severity risk patterns are found
|
|
33
35
|
-h, --help Show help
|
|
34
36
|
|
|
35
37
|
Examples:
|
|
36
|
-
npx
|
|
38
|
+
npx repo-agent-brief
|
|
37
39
|
agent-brief ~/dev/my-app --format json
|
|
38
40
|
agent-brief . --diff origin/main
|
|
41
|
+
agent-brief . --diff HEAD --bundle
|
|
39
42
|
agent-brief . --fail-on-high-risk > AGENT_BRIEF.md
|
|
40
43
|
`;
|
|
41
44
|
}
|
|
@@ -52,7 +55,15 @@ try {
|
|
|
52
55
|
includeSnippets: !args.noSnippets,
|
|
53
56
|
diffRef: args.diffRef
|
|
54
57
|
});
|
|
55
|
-
|
|
58
|
+
if (args.bundleDir) {
|
|
59
|
+
const files = writeBundle(resolve(args.path), brief, args.bundleDir);
|
|
60
|
+
console.log(`Agent brief bundle written:
|
|
61
|
+
- Markdown: ${files.markdown}
|
|
62
|
+
- JSON: ${files.json}
|
|
63
|
+
- Verification: ${files.verification}`);
|
|
64
|
+
} else {
|
|
65
|
+
console.log(args.format === 'json' ? formatJson(brief) : formatMarkdown(brief));
|
|
66
|
+
}
|
|
56
67
|
if (args.failOnHighRisk && brief.risks.some(r => r.severity === 'high')) process.exit(2);
|
|
57
68
|
} catch (error) {
|
|
58
69
|
console.error(`agent-brief: ${error.message}`);
|
package/src/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
2
|
-
import { basename, join,
|
|
1
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { basename, join, resolve } from 'node:path';
|
|
3
3
|
import { execFileSync } from 'node:child_process';
|
|
4
4
|
|
|
5
5
|
const DEFAULT_IGNORES = new Set([
|
|
@@ -158,6 +158,61 @@ export function formatJson(brief) {
|
|
|
158
158
|
return JSON.stringify(brief, null, 2);
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
+
export function formatVerificationMarkdown(brief) {
|
|
162
|
+
const lines = [];
|
|
163
|
+
lines.push(`# Verification Plan: ${brief.project}`);
|
|
164
|
+
lines.push('');
|
|
165
|
+
lines.push(`Generated: ${brief.generatedAt}`);
|
|
166
|
+
if (brief.git.branch || brief.git.status) lines.push(`Git: ${brief.git.branch || 'unknown'}${brief.git.status ? ` - ${brief.git.status}` : ''}`);
|
|
167
|
+
lines.push('');
|
|
168
|
+
|
|
169
|
+
lines.push('## Checklist');
|
|
170
|
+
if (brief.verificationPlan.length) {
|
|
171
|
+
for (const step of brief.verificationPlan) {
|
|
172
|
+
const command = step.command ? `\n - Command: \`${step.command}\`` : '';
|
|
173
|
+
lines.push(`- [ ] [${step.priority}] ${step.reason}${command}`);
|
|
174
|
+
}
|
|
175
|
+
} else {
|
|
176
|
+
lines.push('- [ ] Do a focused manual smoke check and document what could not be verified.');
|
|
177
|
+
}
|
|
178
|
+
lines.push('');
|
|
179
|
+
|
|
180
|
+
if (brief.diff?.available) {
|
|
181
|
+
lines.push(`## Changed Files vs ${brief.diff.ref}`);
|
|
182
|
+
if (brief.diff.files.length) {
|
|
183
|
+
for (const file of brief.diff.files) {
|
|
184
|
+
lines.push(`- ${file.status} ${file.path}${file.risky ? ' (high-impact)' : ''}`);
|
|
185
|
+
}
|
|
186
|
+
} else {
|
|
187
|
+
lines.push('- No changed files detected.');
|
|
188
|
+
}
|
|
189
|
+
lines.push('');
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
lines.push('## Risk Notes');
|
|
193
|
+
if (brief.risks.length) {
|
|
194
|
+
for (const risk of brief.risks) lines.push(`- [${risk.severity}] ${risk.path}: ${risk.message}`);
|
|
195
|
+
} else {
|
|
196
|
+
lines.push('- No obvious secret/risky-instruction patterns found in scanned context files.');
|
|
197
|
+
}
|
|
198
|
+
lines.push('');
|
|
199
|
+
return lines.join('\n');
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
export function writeBundle(root, brief, bundleDir = '.agent-brief') {
|
|
203
|
+
const outDir = resolve(root, bundleDir);
|
|
204
|
+
mkdirSync(outDir, { recursive: true });
|
|
205
|
+
const files = {
|
|
206
|
+
markdown: join(outDir, 'brief.md'),
|
|
207
|
+
json: join(outDir, 'brief.json'),
|
|
208
|
+
verification: join(outDir, 'verification.md')
|
|
209
|
+
};
|
|
210
|
+
writeFileSync(files.markdown, formatMarkdown(brief));
|
|
211
|
+
writeFileSync(files.json, `${formatJson(brief)}\n`);
|
|
212
|
+
writeFileSync(files.verification, formatVerificationMarkdown(brief));
|
|
213
|
+
return files;
|
|
214
|
+
}
|
|
215
|
+
|
|
161
216
|
function collectContext(root, opts) {
|
|
162
217
|
const files = [];
|
|
163
218
|
for (const name of CONTEXT_FILES) {
|