@kirkelabs/agent-readiness-scan 0.1.0 → 0.2.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/bin/cli.js CHANGED
@@ -1,172 +1,175 @@
1
- #!/usr/bin/env node
2
- /**
3
- * bin/cli.js — command-line entry point.
4
- *
5
- * Usage:
6
- * npx @kirkelabs/agent-readiness-scan https://example.com
7
- * npx @kirkelabs/agent-readiness-scan https://example.com --out ./report
8
- * npx @kirkelabs/agent-readiness-scan https://example.com --json
9
- */
10
-
11
- import { writeFile, mkdir } from 'node:fs/promises';
12
- import { resolve, join, dirname } from 'node:path';
13
- import { scan } from '../src/index.js';
14
- import { renderScorecard } from '../src/scorecard.js';
15
-
16
- const RESET = '\x1b[0m';
17
- const DIM = '\x1b[2m';
18
- const BOLD = '\x1b[1m';
19
- const GREEN = '\x1b[32m';
20
- const YELLOW = '\x1b[33m';
21
- const RED = '\x1b[31m';
22
- const CYAN = '\x1b[36m';
23
-
24
- function parseArgs(argv) {
25
- const args = { url: null, out: './agent-readiness-out', json: false };
26
- for (let i = 2; i < argv.length; i++) {
27
- const a = argv[i];
28
- if (a === '--out') args.out = argv[++i];
29
- else if (a === '--json') args.json = true;
30
- else if (a === '--help' || a === '-h') args.help = true;
31
- else if (!a.startsWith('-')) args.url = a;
32
- }
33
- return args;
34
- }
35
-
36
- function help() {
37
- console.log(`
38
- ${BOLD}agent-readiness-scan${RESET} — is your brand ready for AI agents to act on it?
39
-
40
- ${BOLD}Usage${RESET}
41
- npx @kirkelabs/agent-readiness-scan <url> [options]
42
-
43
- ${BOLD}Options${RESET}
44
- --out <dir> Output directory (default: ./agent-readiness-out)
45
- --json Print machine-readable JSON to stdout (good for CI)
46
- -h, --help Show this help
47
-
48
- ${BOLD}Outputs written to <dir>${RESET}
49
- score.json Machine-readable result (CI-gateable)
50
- report.md Human-readable report
51
- scorecard.html Shareable static scorecard
52
- customs-declaration/ Drop-in policy files
53
- robots.txt
54
- .well-known/security.txt
55
- .well-known/mcp/server-card.json
56
- .well-known/acp/manifest.json
57
-
58
- MIT · Kirke Labs · www.kirkelabs.com
59
- `);
60
- }
61
-
62
- function color(level) {
63
- return level === 'pass'
64
- ? GREEN
65
- : level === 'warn'
66
- ? YELLOW
67
- : level === 'fail'
68
- ? RED
69
- : DIM;
70
- }
71
-
72
- function bar(pct, width = 22) {
73
- const fill = Math.round((pct / 100) * width);
74
- return '█'.repeat(fill) + '░'.repeat(width - fill);
75
- }
76
-
77
- async function writeArtefact(outDir, relPath, content) {
78
- const fullPath = join(outDir, relPath);
79
- await mkdir(dirname(fullPath), { recursive: true });
80
- await writeFile(fullPath, content);
81
- }
82
-
83
- async function main() {
84
- const args = parseArgs(process.argv);
85
- if (args.help || !args.url) {
86
- help();
87
- process.exit(args.url ? 0 : 1);
88
- }
89
-
90
- let url = args.url;
91
- if (!/^https?:\/\//i.test(url)) url = 'https://' + url;
92
-
93
- if (!args.json) {
94
- console.log(`\n${CYAN}⟶ Scanning ${BOLD}${url}${RESET}${CYAN} for agent-readiness…${RESET}\n`);
95
- }
96
-
97
- const result = await scan(url);
98
-
99
- if (args.json) {
100
- process.stdout.write(JSON.stringify(result, null, 2) + '\n');
101
- return;
102
- }
103
-
104
- if (!result.ok) {
105
- console.error(`${RED}✗ Could not scan: ${result.error}${RESET}\n`);
106
- process.exit(2);
107
- }
108
-
109
- const gColor =
110
- result.grade === 'A' || result.grade === 'B'
111
- ? GREEN
112
- : result.grade === 'C'
113
- ? YELLOW
114
- : RED;
115
-
116
- console.log(
117
- `${BOLD} Agent-Readiness Score: ${gColor}${result.score}/100 (${result.grade})${RESET}\n`,
118
- );
119
-
120
- for (const d of result.dimensions) {
121
- const pct = Math.round((d.score / d.max) * 100);
122
- const c = pct >= 70 ? GREEN : pct >= 40 ? YELLOW : RED;
123
- console.log(
124
- ` ${c}${bar(pct)}${RESET} ${d.title} ${DIM}(${d.score}/${d.max}, weight ${d.weight})${RESET}`,
125
- );
126
- for (const f of d.findings) {
127
- console.log(` ${color(f.level)}•${RESET} ${f.msg}`);
128
- }
129
- console.log('');
130
- }
131
-
132
- // Write artefacts.
133
- const outDir = resolve(args.out);
134
- await mkdir(outDir, { recursive: true });
135
- await writeFile(join(outDir, 'score.json'), JSON.stringify(result, null, 2));
136
- await writeFile(join(outDir, 'report.md'), toMarkdown(result));
137
- await writeFile(join(outDir, 'scorecard.html'), renderScorecard(result));
138
-
139
- // Customs declaration files.
140
- for (const [relPath, content] of Object.entries(result.generated)) {
141
- await writeArtefact(join(outDir, 'customs-declaration'), relPath, content);
142
- }
143
-
144
- console.log(`${DIM} Artefacts written to ${outDir}/${RESET}`);
145
- console.log(
146
- `${DIM} score.json · report.md · scorecard.html · customs-declaration/${RESET}\n`,
147
- );
148
- console.log(
149
- `${DIM} Heuristic indicators, not a guarantee of agent action. See docs/METHODOLOGY.md${RESET}\n`,
150
- );
151
-
152
- process.exit(result.score >= 50 ? 0 : 3);
153
- }
154
-
155
- function toMarkdown(r) {
156
- let md = `# Agent-Readiness Report\n\n`;
157
- md += `**URL:** ${r.url} \n**Score:** ${r.score}/100 (${r.grade}) \n`;
158
- md += `**Scanned:** ${r.scannedAt}\n\n`;
159
- md += `> Heuristic indicators of how ready this brand is for AI agents to discover, declare access to, and act on. Not a guarantee of agent uptake.\n\n`;
160
- for (const d of r.dimensions) {
161
- md += `## ${d.title} — ${d.score}/${d.max}\n\n_${d.why}_\n\n`;
162
- for (const f of d.findings) md += `- **${f.level.toUpperCase()}** ${f.msg}\n`;
163
- md += `\n`;
164
- }
165
- md += `---\n\nGenerated by [\`@kirkelabs/agent-readiness-scan\`](https://github.com/KirkeLabs/agent-readiness-scan) MIT. Built by Soleman El Gelawi (CTO, Kirke Labs), with Steve Kirton (www.kirkelabs.com) as a gift to the Algorand ecosystem.\n`;
166
- return md;
167
- }
168
-
169
- main().catch((e) => {
170
- console.error(`${RED}Unexpected error:${RESET}`, e);
171
- process.exit(1);
172
- });
1
+ #!/usr/bin/env node
2
+ /**
3
+ * bin/cli.js — command-line entry point.
4
+ *
5
+ * Usage:
6
+ * npx @kirkelabs/agent-readiness-scan https://example.com
7
+ * npx @kirkelabs/agent-readiness-scan https://example.com --out ./report
8
+ * npx @kirkelabs/agent-readiness-scan https://example.com --json
9
+ */
10
+
11
+ import { writeFile, mkdir } from 'node:fs/promises';
12
+ import { resolve, join, dirname } from 'node:path';
13
+ import { scan } from '../src/index.js';
14
+ import { renderScorecard } from '../src/scorecard.js';
15
+
16
+ const RESET = '\x1b[0m';
17
+ const DIM = '\x1b[2m';
18
+ const BOLD = '\x1b[1m';
19
+ const GREEN = '\x1b[32m';
20
+ const YELLOW = '\x1b[33m';
21
+ const RED = '\x1b[31m';
22
+ const CYAN = '\x1b[36m';
23
+
24
+ function parseArgs(argv) {
25
+ const args = { url: null, out: './agent-readiness-out', json: false };
26
+ for (let i = 2; i < argv.length; i++) {
27
+ const a = argv[i];
28
+ if (a === '--out') args.out = argv[++i];
29
+ else if (a === '--json') args.json = true;
30
+ else if (a === '--help' || a === '-h') args.help = true;
31
+ else if (!a.startsWith('-')) args.url = a;
32
+ }
33
+ return args;
34
+ }
35
+
36
+ function help() {
37
+ console.log(`
38
+ ${BOLD}agent-readiness-scan${RESET} — is your brand ready for AI agents to act on it?
39
+
40
+ ${BOLD}Usage${RESET}
41
+ npx @kirkelabs/agent-readiness-scan <url> [options]
42
+
43
+ ${BOLD}Options${RESET}
44
+ --out <dir> Output directory (default: ./agent-readiness-out)
45
+ --json Print machine-readable JSON to stdout (good for CI)
46
+ -h, --help Show this help
47
+
48
+ ${BOLD}Outputs written to <dir>${RESET}
49
+ score.json Machine-readable result (CI-gateable)
50
+ report.md Human-readable report
51
+ scorecard.html Shareable static scorecard
52
+ customs-declaration/ Drop-in policy files
53
+ robots.txt
54
+ .well-known/security.txt
55
+ .well-known/mcp/server-card.json
56
+ .well-known/acp/manifest.json
57
+ .well-known/agent-access.json
58
+
59
+ MIT · Kirke Labs · www.kirkelabs.com
60
+ `);
61
+ }
62
+
63
+ function color(level) {
64
+ return level === 'pass'
65
+ ? GREEN
66
+ : level === 'warn'
67
+ ? YELLOW
68
+ : level === 'fail'
69
+ ? RED
70
+ : DIM;
71
+ }
72
+
73
+ function bar(pct, width = 22) {
74
+ const fill = Math.round((pct / 100) * width);
75
+ return '█'.repeat(fill) + '░'.repeat(width - fill);
76
+ }
77
+
78
+ async function writeArtefact(outDir, relPath, content) {
79
+ const fullPath = join(outDir, relPath);
80
+ await mkdir(dirname(fullPath), { recursive: true });
81
+ await writeFile(fullPath, content);
82
+ }
83
+
84
+ async function main() {
85
+ const args = parseArgs(process.argv);
86
+ if (args.help || !args.url) {
87
+ help();
88
+ process.exit(args.url ? 0 : 1);
89
+ }
90
+
91
+ let url = args.url;
92
+ if (!/^https?:\/\//i.test(url)) url = 'https://' + url;
93
+
94
+ if (!args.json) {
95
+ console.log(
96
+ `\n${CYAN}⟶ Scanning ${BOLD}${url}${RESET}${CYAN} for agent-readiness…${RESET}\n`,
97
+ );
98
+ }
99
+
100
+ const result = await scan(url);
101
+
102
+ if (args.json) {
103
+ process.stdout.write(JSON.stringify(result, null, 2) + '\n');
104
+ return;
105
+ }
106
+
107
+ if (!result.ok) {
108
+ console.error(`${RED}✗ Could not scan: ${result.error}${RESET}\n`);
109
+ process.exit(2);
110
+ }
111
+
112
+ const gColor =
113
+ result.grade === 'A' || result.grade === 'B'
114
+ ? GREEN
115
+ : result.grade === 'C'
116
+ ? YELLOW
117
+ : RED;
118
+
119
+ console.log(
120
+ `${BOLD} Agent-Readiness Score: ${gColor}${result.score}/100 (${result.grade})${RESET}\n`,
121
+ );
122
+
123
+ for (const d of result.dimensions) {
124
+ const pct = Math.round((d.score / d.max) * 100);
125
+ const c = pct >= 70 ? GREEN : pct >= 40 ? YELLOW : RED;
126
+ console.log(
127
+ ` ${c}${bar(pct)}${RESET} ${d.title} ${DIM}(${d.score}/${d.max}, weight ${d.weight})${RESET}`,
128
+ );
129
+ for (const f of d.findings) {
130
+ console.log(` ${color(f.level)}•${RESET} ${f.msg}`);
131
+ }
132
+ console.log('');
133
+ }
134
+
135
+ // Write artefacts.
136
+ const outDir = resolve(args.out);
137
+ await mkdir(outDir, { recursive: true });
138
+ await writeFile(join(outDir, 'score.json'), JSON.stringify(result, null, 2));
139
+ await writeFile(join(outDir, 'report.md'), toMarkdown(result));
140
+ await writeFile(join(outDir, 'scorecard.html'), renderScorecard(result));
141
+
142
+ // Customs declaration files.
143
+ for (const [relPath, content] of Object.entries(result.generated)) {
144
+ await writeArtefact(join(outDir, 'customs-declaration'), relPath, content);
145
+ }
146
+
147
+ console.log(`${DIM} Artefacts written to ${outDir}/${RESET}`);
148
+ console.log(
149
+ `${DIM} score.json · report.md · scorecard.html · customs-declaration/${RESET}\n`,
150
+ );
151
+ console.log(
152
+ `${DIM} Heuristic indicators, not a guarantee of agent action. See docs/METHODOLOGY.md${RESET}\n`,
153
+ );
154
+
155
+ process.exit(result.score >= 50 ? 0 : 3);
156
+ }
157
+
158
+ function toMarkdown(r) {
159
+ let md = `# Agent-Readiness Report\n\n`;
160
+ md += `**URL:** ${r.url} \n**Score:** ${r.score}/100 (${r.grade}) \n`;
161
+ md += `**Scanned:** ${r.scannedAt}\n\n`;
162
+ md += `> Heuristic indicators of how ready this brand is for AI agents to discover, declare access to, and act on. Not a guarantee of agent uptake.\n\n`;
163
+ for (const d of r.dimensions) {
164
+ md += `## ${d.title} — ${d.score}/${d.max}\n\n_${d.why}_\n\n`;
165
+ for (const f of d.findings) md += `- **${f.level.toUpperCase()}** ${f.msg}\n`;
166
+ md += `\n`;
167
+ }
168
+ md += `---\n\nGenerated by [\`@kirkelabs/agent-readiness-scan\`](https://github.com/KirkeLabs/agent-readiness-scan) — MIT. Built by Soleman El Gelawi (CTO, Kirke Labs), with Steve Kirton (www.kirkelabs.com) as a gift to the Algorand ecosystem.\n`;
169
+ return md;
170
+ }
171
+
172
+ main().catch((e) => {
173
+ console.error(`${RED}Unexpected error:${RESET}`, e);
174
+ process.exit(1);
175
+ });
package/package.json CHANGED
@@ -1,64 +1,69 @@
1
- {
2
- "name": "@kirkelabs/agent-readiness-scan",
3
- "version": "0.1.0",
4
- "description": "Audit a website's customs-house posture for AI agents. Scores 8 dimensions — crawler policy, bot auth, MCP/ACP exposure, agent-actionable Product/Offer, brand identity corroboration, regulatory transparency — and generates a drop-in customs declaration (robots.txt + .well-known/ manifests). A gift to the Algorand ecosystem from Kirke Labs.",
5
- "type": "module",
6
- "bin": {
7
- "agent-readiness-scan": "bin/cli.js"
8
- },
9
- "exports": {
10
- ".": "./src/index.js"
11
- },
12
- "files": [
13
- "bin/",
14
- "src/",
15
- "LICENSE",
16
- "README.md",
17
- "AUTHORS",
18
- "CITATION.cff"
19
- ],
20
- "scripts": {
21
- "scan": "node bin/cli.js",
22
- "test": "node --test \"test/*.test.js\"",
23
- "lint": "eslint . --ext .js",
24
- "format": "prettier --write \"**/*.{js,json,md}\""
25
- },
26
- "keywords": [
27
- "ai-agents",
28
- "mcp",
29
- "acp",
30
- "agentic-commerce",
31
- "crawler-policy",
32
- "web-bot-auth",
33
- "content-signals",
34
- "universal-cart",
35
- "schema-org",
36
- "structured-data",
37
- "algorand",
38
- "cli",
39
- "nodejs"
40
- ],
41
- "author": "Soleman El Gelawi <soleman@kirkelabs.com> (https://www.kirkelabs.com)",
42
- "contributors": [
43
- "Steve Kirton <steve@kirkelabs.com> (https://www.kirkelabs.com)"
44
- ],
45
- "license": "MIT",
46
- "homepage": "https://kirkelabs.github.io/agent-readiness-scan/",
47
- "repository": {
48
- "type": "git",
49
- "url": "git+https://github.com/KirkeLabs/agent-readiness-scan.git"
50
- },
51
- "bugs": {
52
- "url": "https://github.com/KirkeLabs/agent-readiness-scan/issues"
53
- },
54
- "engines": {
55
- "node": ">=20"
56
- },
57
- "dependencies": {
58
- "cheerio": "^1.0.0"
59
- },
60
- "devDependencies": {
61
- "eslint": "^9.0.0",
62
- "prettier": "^3.0.0"
63
- }
64
- }
1
+ {
2
+ "name": "@kirkelabs/agent-readiness-scan",
3
+ "version": "0.2.0",
4
+ "description": "Audit a website's customs-house posture for AI agents. Scores 8 dimensions — crawler policy, bot auth, MCP/ACP exposure, agent-actionable Product/Offer, brand identity corroboration, regulatory transparency — and generates a drop-in customs declaration (robots.txt + .well-known/ manifests). A gift to the Algorand ecosystem from Kirke Labs.",
5
+ "type": "module",
6
+ "bin": {
7
+ "agent-readiness-scan": "bin/cli.js"
8
+ },
9
+ "exports": {
10
+ ".": "./src/index.js"
11
+ },
12
+ "files": [
13
+ "bin/",
14
+ "src/",
15
+ "LICENSE",
16
+ "README.md",
17
+ "CHANGELOG.md",
18
+ "AUTHORS",
19
+ "CITATION.cff"
20
+ ],
21
+ "publishConfig": {
22
+ "access": "public"
23
+ },
24
+ "scripts": {
25
+ "scan": "node bin/cli.js",
26
+ "test": "node --test \"test/*.test.js\"",
27
+ "lint": "eslint . --ext .js",
28
+ "format": "prettier --write \"**/*.{js,json,md}\"",
29
+ "prepublishOnly": "npm run lint && npm test"
30
+ },
31
+ "keywords": [
32
+ "ai-agents",
33
+ "mcp",
34
+ "acp",
35
+ "agentic-commerce",
36
+ "crawler-policy",
37
+ "web-bot-auth",
38
+ "content-signals",
39
+ "universal-cart",
40
+ "schema-org",
41
+ "structured-data",
42
+ "algorand",
43
+ "cli",
44
+ "nodejs"
45
+ ],
46
+ "author": "Soleman El Gelawi <soleman@kirkelabs.com> (https://www.kirkelabs.com)",
47
+ "contributors": [
48
+ "Steve Kirton <steve@kirkelabs.com> (https://www.kirkelabs.com)"
49
+ ],
50
+ "license": "MIT",
51
+ "homepage": "https://kirkelabs.github.io/agent-readiness-scan/",
52
+ "repository": {
53
+ "type": "git",
54
+ "url": "git+https://github.com/KirkeLabs/agent-readiness-scan.git"
55
+ },
56
+ "bugs": {
57
+ "url": "https://github.com/KirkeLabs/agent-readiness-scan/issues"
58
+ },
59
+ "engines": {
60
+ "node": ">=20"
61
+ },
62
+ "dependencies": {
63
+ "cheerio": "^1.0.0"
64
+ },
65
+ "devDependencies": {
66
+ "eslint": "^9.0.0",
67
+ "prettier": "^3.0.0"
68
+ }
69
+ }