@drunkcoding/agents-and-skills 0.0.17 → 0.0.19
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 +19 -4
- package/README.md +24 -0
- package/package.json +1 -1
- package/plugins/auto-power/.claude-plugin/plugin.json +17 -0
- package/plugins/auto-power/README.md +80 -0
- package/plugins/auto-power/assets/CHECKPOINT_SCHEMA.md +69 -0
- package/plugins/auto-power/assets/ESCALATION_TEMPLATE.md +67 -0
- package/plugins/auto-power/commands/auto-power-resume.md +32 -0
- package/plugins/auto-power/commands/auto-power.md +46 -0
- package/plugins/auto-power/skills/auto-power-runtime/SKILL.md +220 -0
- package/plugins/html-effectiveness/.claude-plugin/plugin.json +1 -1
- package/plugins/plugin-validator/.claude-plugin/plugin.json +1 -1
- package/plugins/team-superpower/.claude-plugin/plugin.json +1 -1
- package/plugins/team-superpower/agents/backend-developer.md +93 -3
- package/plugins/team-superpower/agents/designer.md +17 -2
- package/plugins/team-superpower/agents/frontend-developer.md +94 -3
- package/plugins/team-superpower/agents/planner.md +62 -6
- package/plugins/team-superpower/agents/qa-engineer.md +73 -17
- package/plugins/team-superpower/agents/reviewer.md +71 -6
- package/plugins/team-superpower/agents/security-engineer.md +16 -1
- package/plugins/team-superpower/agents/software-architect.md +16 -1
- package/plugins/team-superpower/assets/AGENTS.md.template +23 -0
- package/plugins/team-superpower/assets/CLAUDE.md.template +17 -0
- package/plugins/team-superpower/assets/SESSION_README.md +47 -0
- package/plugins/team-superpower/commands/team-feature.md +217 -11
- package/plugins/team-superpower/hooks/task-completed.sh +203 -0
- package/plugins/team-superpower/hooks/task-created.sh +42 -1
- package/plugins/team-superpower/scripts/assess-complexity.sh +194 -0
- package/plugins/team-superpower/scripts/detect-stack.sh +39 -0
- package/plugins/team-superpower/scripts/wave-collision-check.sh +60 -0
- package/plugins/tech-graph/.claude-plugin/plugin.json +1 -1
- package/plugins/html-effectiveness/tests/_tmp.test.js +0 -58
- package/plugins/html-effectiveness/tests/fixtures/01-exploration-code-approaches.data.json +0 -3
- package/plugins/html-effectiveness/tests/fixtures/02-exploration-visual-designs.data.json +0 -3
- package/plugins/html-effectiveness/tests/fixtures/03-code-review-pr.data.json +0 -3
- package/plugins/html-effectiveness/tests/fixtures/04-code-understanding.data.json +0 -3
- package/plugins/html-effectiveness/tests/fixtures/05-design-system.data.json +0 -3
- package/plugins/html-effectiveness/tests/fixtures/06-component-variants.data.json +0 -3
- package/plugins/html-effectiveness/tests/fixtures/07-prototype-animation.data.json +0 -3
- package/plugins/html-effectiveness/tests/fixtures/08-prototype-interaction.data.json +0 -3
- package/plugins/html-effectiveness/tests/fixtures/09-slide-deck.data.json +0 -3
- package/plugins/html-effectiveness/tests/fixtures/10-svg-illustrations.data.json +0 -3
- package/plugins/html-effectiveness/tests/fixtures/11-status-report.data.json +0 -37
- package/plugins/html-effectiveness/tests/fixtures/12-incident-report.data.json +0 -3
- package/plugins/html-effectiveness/tests/fixtures/13-flowchart-diagram.data.json +0 -3
- package/plugins/html-effectiveness/tests/fixtures/14-research-feature-explainer.data.json +0 -3
- package/plugins/html-effectiveness/tests/fixtures/15-research-concept-explainer.data.json +0 -3
- package/plugins/html-effectiveness/tests/fixtures/16-implementation-plan.data.json +0 -3
- package/plugins/html-effectiveness/tests/fixtures/17-pr-writeup.data.json +0 -3
- package/plugins/html-effectiveness/tests/fixtures/18-editor-triage-board.data.json +0 -3
- package/plugins/html-effectiveness/tests/fixtures/19-editor-feature-flags.data.json +0 -3
- package/plugins/html-effectiveness/tests/fixtures/20-editor-prompt-tuner.data.json +0 -3
- package/plugins/html-effectiveness/tests/fixtures/_canned.data.json +0 -7
- package/plugins/html-effectiveness/tests/fixtures/_canned.html.tmpl +0 -7
- package/plugins/html-effectiveness/tests/fixtures/_canned.manifest.json +0 -18
- package/plugins/html-effectiveness/tests/manifest.test.js +0 -61
- package/plugins/html-effectiveness/tests/mustache.test.js +0 -47
- package/plugins/html-effectiveness/tests/render.test.js +0 -118
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"title": "Engineering Status",
|
|
3
|
-
"auto_pill": "Auto-generated",
|
|
4
|
-
"date_range": "Apr 29 — May 13, 2026",
|
|
5
|
-
"repo": "drunkcoding/agents-and-skills",
|
|
6
|
-
"summary": [
|
|
7
|
-
{ "num": "12", "label": "Shipped", "delta": "+3 vs prev", "delta_kind": "up" },
|
|
8
|
-
{ "num": "47", "label": "Open bugs", "delta": "-8", "delta_kind": "down" },
|
|
9
|
-
{ "num": "14", "label": "On-call", "delta": "+2", "delta_kind": "up", "warn": true },
|
|
10
|
-
{ "num": "92%","label": "CI green", "delta": "flat", "delta_kind": "flat" }
|
|
11
|
-
],
|
|
12
|
-
"highlights": {
|
|
13
|
-
"items": [
|
|
14
|
-
{ "strong": "Auth v2 cutover.", "body": "All traffic on new identity stack; p95 latency down <em>30%</em>." },
|
|
15
|
-
{ "strong": "Search reindex.", "body": "Full corpus rebuilt in 11h, down from 26h." },
|
|
16
|
-
{ "strong": "Mobile beta.", "body": "iOS 17 build live to internal testers." }
|
|
17
|
-
]
|
|
18
|
-
},
|
|
19
|
-
"shipped": {
|
|
20
|
-
"rows": [
|
|
21
|
-
{ "pr": "#1042", "title": "feat(auth): rotate session keys", "author": "alice", "risk": "low" },
|
|
22
|
-
{ "pr": "#1048", "title": "fix(search): off-by-one in date filter", "author": "bob", "risk": "low" },
|
|
23
|
-
{ "pr": "#1055", "title": "perf(api): cache permission lookups", "author": "charlie", "risk": "med" },
|
|
24
|
-
{ "pr": "#1061", "title": "feat(mobile): push notif opt-in", "author": "dana", "risk": "high" }
|
|
25
|
-
]
|
|
26
|
-
},
|
|
27
|
-
"velocity_svg": "<svg viewBox=\"0 0 600 160\" xmlns=\"http://www.w3.org/2000/svg\"><polyline fill=\"none\" stroke=\"#D97757\" stroke-width=\"2\" points=\"0,120 75,90 150,100 225,70 300,60 375,80 450,40 525,30 600,50\"/><line x1=\"0\" y1=\"150\" x2=\"600\" y2=\"150\" stroke=\"#D1CFC5\"/></svg>",
|
|
28
|
-
"velocity_caption": "Merged PRs per day, 2-week window. Source: GitHub API.",
|
|
29
|
-
"carryover": {
|
|
30
|
-
"items": [
|
|
31
|
-
{ "tag": "BLOCKED", "body": "App Store review for iOS 17 build.", "who": "dana" },
|
|
32
|
-
{ "tag": "REVIEW", "body": "Permission cache invalidation edge case.", "who": "charlie" },
|
|
33
|
-
{ "tag": "SCOPE", "body": "Q3 platform RFC pending review.", "who": "alice" }
|
|
34
|
-
]
|
|
35
|
-
},
|
|
36
|
-
"footer": "Generated 2026-05-13 · <a href=\"#\">runbook</a>"
|
|
37
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"_meta": { "upstream_repo": "test", "upstream_sha": "test", "extracted_at": "test" },
|
|
3
|
-
"_canned": {
|
|
4
|
-
"title": "Canned",
|
|
5
|
-
"use_cases": ["test"],
|
|
6
|
-
"pattern": "test",
|
|
7
|
-
"tmpl": "fixtures/_canned.html.tmpl",
|
|
8
|
-
"slots": {
|
|
9
|
-
"title": { "type": "string", "required": true },
|
|
10
|
-
"items": {
|
|
11
|
-
"type": "array",
|
|
12
|
-
"of": { "name": "string", "html": "html" }
|
|
13
|
-
}
|
|
14
|
-
},
|
|
15
|
-
"asset_bundles": [],
|
|
16
|
-
"extra_js": null
|
|
17
|
-
}
|
|
18
|
-
}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { test } from 'node:test';
|
|
2
|
-
import assert from 'node:assert/strict';
|
|
3
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
4
|
-
import { dirname, join } from 'node:path';
|
|
5
|
-
import { fileURLToPath } from 'node:url';
|
|
6
|
-
|
|
7
|
-
const HERE = dirname(fileURLToPath(import.meta.url));
|
|
8
|
-
const PLUGIN_ROOT = dirname(HERE);
|
|
9
|
-
const MANIFEST = JSON.parse(readFileSync(join(PLUGIN_ROOT, 'templates/manifest.json'), 'utf8'));
|
|
10
|
-
const VALID_BUNDLES = new Set(['base', 'components', 'charts']);
|
|
11
|
-
|
|
12
|
-
const entries = Object.entries(MANIFEST).filter(([k]) => k !== '_meta');
|
|
13
|
-
|
|
14
|
-
test('manifest declares 20 vendored templates', () => {
|
|
15
|
-
assert.equal(entries.length, 20, `expected 20 entries, got ${entries.length}`);
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
test('_meta records upstream SHA and fetch date', () => {
|
|
19
|
-
const meta = MANIFEST._meta;
|
|
20
|
-
assert.ok(meta, '_meta missing');
|
|
21
|
-
assert.match(meta.upstream_sha, /^[0-9a-f]{40}$/, 'upstream_sha must be 40-char hex');
|
|
22
|
-
assert.match(meta.fetched_at, /^\d{4}-\d{2}-\d{2}$/, 'fetched_at must be YYYY-MM-DD');
|
|
23
|
-
assert.equal(meta.upstream_repo, 'ThariqS/html-effectiveness');
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
for (const [id, entry] of entries) {
|
|
27
|
-
test(`${id}: required fields present`, () => {
|
|
28
|
-
for (const f of ['title', 'use_cases', 'pattern', 'slots', 'asset_bundles']) {
|
|
29
|
-
assert.ok(f in entry, `${id} missing field "${f}"`);
|
|
30
|
-
}
|
|
31
|
-
assert.ok(Array.isArray(entry.use_cases), `${id} use_cases must be array`);
|
|
32
|
-
assert.ok(entry.use_cases.length > 0, `${id} use_cases must be non-empty`);
|
|
33
|
-
assert.equal(typeof entry.pattern, 'string', `${id} pattern must be string`);
|
|
34
|
-
assert.equal(typeof entry.slots, 'object', `${id} slots must be object`);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
test(`${id}: asset_bundles valid`, () => {
|
|
38
|
-
assert.ok(Array.isArray(entry.asset_bundles), `${id} asset_bundles not array`);
|
|
39
|
-
for (const b of entry.asset_bundles) {
|
|
40
|
-
assert.ok(VALID_BUNDLES.has(b), `${id} asset_bundles contains invalid "${b}"`);
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
test(`${id}: template file exists`, () => {
|
|
45
|
-
const tmplRel = entry.tmpl || `templates/${id}.html.tmpl`;
|
|
46
|
-
const tmplAbs = join(PLUGIN_ROOT, tmplRel);
|
|
47
|
-
assert.ok(existsSync(tmplAbs), `${id} template file missing: ${tmplRel}`);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
test(`${id}: fixture file exists`, () => {
|
|
51
|
-
const fix = join(PLUGIN_ROOT, `tests/fixtures/${id}.data.json`);
|
|
52
|
-
assert.ok(existsSync(fix), `${id} fixture missing: tests/fixtures/${id}.data.json`);
|
|
53
|
-
const data = JSON.parse(readFileSync(fix, 'utf8'));
|
|
54
|
-
for (const [slot, schemaRaw] of Object.entries(entry.slots)) {
|
|
55
|
-
const schema = typeof schemaRaw === 'string' ? { type: schemaRaw } : schemaRaw;
|
|
56
|
-
if (schema.required) {
|
|
57
|
-
assert.ok(slot in data, `${id} fixture missing required slot "${slot}"`);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { test } from 'node:test';
|
|
2
|
-
import assert from 'node:assert/strict';
|
|
3
|
-
import { render } from '../scripts/mustache.js';
|
|
4
|
-
|
|
5
|
-
test('renders bare variable, escaped by default', () => {
|
|
6
|
-
assert.equal(render('Hello {{name}}', { name: 'World' }), 'Hello World');
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
test('escapes HTML special chars in {{var}}', () => {
|
|
10
|
-
assert.equal(
|
|
11
|
-
render('{{x}}', { x: '<script>alert(1)</script>' }),
|
|
12
|
-
'<script>alert(1)</script>'
|
|
13
|
-
);
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
test('triple-stash {{{raw}}} bypasses escaping', () => {
|
|
17
|
-
assert.equal(render('{{{html}}}', { html: '<b>x</b>' }), '<b>x</b>');
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
test('section iterates array with sub-context', () => {
|
|
21
|
-
const tmpl = '{{#items}}[{{name}}]{{/items}}';
|
|
22
|
-
assert.equal(render(tmpl, { items: [{ name: 'a' }, { name: 'b' }] }), '[a][b]');
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
test('inverted section renders only when falsy/empty', () => {
|
|
26
|
-
assert.equal(render('{{^items}}empty{{/items}}', { items: [] }), 'empty');
|
|
27
|
-
assert.equal(render('{{^items}}empty{{/items}}', { items: [{}] }), '');
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
test('missing key renders as empty string, not "undefined"', () => {
|
|
31
|
-
assert.equal(render('x={{missing}}', {}), 'x=');
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
test('nested sections respect inherited context', () => {
|
|
35
|
-
const tmpl = '{{#a}}{{#b}}{{x}}{{/b}}{{/a}}';
|
|
36
|
-
assert.equal(render(tmpl, { a: { b: [{ x: 'ok' }] } }), 'ok');
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
test('falsy section (false, null, undefined, empty array) renders nothing', () => {
|
|
40
|
-
for (const val of [false, null, undefined, []]) {
|
|
41
|
-
assert.equal(render('{{#x}}body{{/x}}', { x: val }), '');
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
test('preserves literal text around tags', () => {
|
|
46
|
-
assert.equal(render('a {{x}} b', { x: '1' }), 'a 1 b');
|
|
47
|
-
});
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
import { test } from 'node:test';
|
|
2
|
-
import assert from 'node:assert/strict';
|
|
3
|
-
import { mkdtempSync, readFileSync, rmSync } from 'node:fs';
|
|
4
|
-
import { tmpdir } from 'node:os';
|
|
5
|
-
import { join, dirname } from 'node:path';
|
|
6
|
-
import { fileURLToPath } from 'node:url';
|
|
7
|
-
import { renderReport } from '../scripts/render.js';
|
|
8
|
-
|
|
9
|
-
const here = dirname(fileURLToPath(import.meta.url));
|
|
10
|
-
const fixtures = join(here, 'fixtures');
|
|
11
|
-
|
|
12
|
-
function setup() {
|
|
13
|
-
const out = mkdtempSync(join(tmpdir(), 'htmleff-'));
|
|
14
|
-
return {
|
|
15
|
-
out,
|
|
16
|
-
cleanup: () => rmSync(out, { recursive: true, force: true }),
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
test('renders canned template into self-contained HTML', () => {
|
|
21
|
-
const { out, cleanup } = setup();
|
|
22
|
-
try {
|
|
23
|
-
const outPath = join(out, 'demo.html');
|
|
24
|
-
renderReport({
|
|
25
|
-
templateId: '_canned',
|
|
26
|
-
data: JSON.parse(readFileSync(join(fixtures, '_canned.data.json'), 'utf8')),
|
|
27
|
-
outPath,
|
|
28
|
-
manifestPath: join(fixtures, '_canned.manifest.json'),
|
|
29
|
-
pluginRoot: dirname(fixtures),
|
|
30
|
-
});
|
|
31
|
-
const html = readFileSync(outPath, 'utf8');
|
|
32
|
-
assert.ok(html.startsWith('<!doctype html>'), 'starts with doctype');
|
|
33
|
-
assert.ok(html.includes('<title>Demo <Report></title>'), 'title escaped in head');
|
|
34
|
-
assert.ok(html.includes('Demo <Report></h1>'), 'title escaped in body');
|
|
35
|
-
assert.ok(html.includes('<b>bold</b>'), 'html slot rendered raw');
|
|
36
|
-
assert.ok(!html.match(/\{\{[^}]+\}\}/), 'no leftover mustache markers');
|
|
37
|
-
assert.ok(!html.includes('<link'), 'no external link');
|
|
38
|
-
assert.ok(!html.match(/<script\s+src=/i), 'no external script src');
|
|
39
|
-
} finally {
|
|
40
|
-
cleanup();
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
test('writes sidecar .data.json next to output', () => {
|
|
45
|
-
const { out, cleanup } = setup();
|
|
46
|
-
try {
|
|
47
|
-
const outPath = join(out, 'demo.html');
|
|
48
|
-
const data = JSON.parse(readFileSync(join(fixtures, '_canned.data.json'), 'utf8'));
|
|
49
|
-
renderReport({
|
|
50
|
-
templateId: '_canned',
|
|
51
|
-
data,
|
|
52
|
-
outPath,
|
|
53
|
-
manifestPath: join(fixtures, '_canned.manifest.json'),
|
|
54
|
-
pluginRoot: dirname(fixtures),
|
|
55
|
-
});
|
|
56
|
-
const sidecarPath = outPath + '.data.json';
|
|
57
|
-
const sidecar = JSON.parse(readFileSync(sidecarPath, 'utf8'));
|
|
58
|
-
assert.equal(sidecar.template, '_canned');
|
|
59
|
-
assert.deepEqual(sidecar.data, data);
|
|
60
|
-
assert.ok(sidecar.rendered_at);
|
|
61
|
-
} finally {
|
|
62
|
-
cleanup();
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
test('throws on missing required slot with template:slot context', () => {
|
|
67
|
-
const { out, cleanup } = setup();
|
|
68
|
-
try {
|
|
69
|
-
assert.throws(
|
|
70
|
-
() => renderReport({
|
|
71
|
-
templateId: '_canned',
|
|
72
|
-
data: { items: [] },
|
|
73
|
-
outPath: join(out, 'x.html'),
|
|
74
|
-
manifestPath: join(fixtures, '_canned.manifest.json'),
|
|
75
|
-
pluginRoot: dirname(fixtures),
|
|
76
|
-
}),
|
|
77
|
-
/_canned:title.*required/,
|
|
78
|
-
);
|
|
79
|
-
} finally {
|
|
80
|
-
cleanup();
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
test('throws on unknown template id with valid-ids list', () => {
|
|
85
|
-
const { out, cleanup } = setup();
|
|
86
|
-
try {
|
|
87
|
-
assert.throws(
|
|
88
|
-
() => renderReport({
|
|
89
|
-
templateId: 'does-not-exist',
|
|
90
|
-
data: {},
|
|
91
|
-
outPath: join(out, 'x.html'),
|
|
92
|
-
manifestPath: join(fixtures, '_canned.manifest.json'),
|
|
93
|
-
pluginRoot: dirname(fixtures),
|
|
94
|
-
}),
|
|
95
|
-
/template not found.*_canned/i,
|
|
96
|
-
);
|
|
97
|
-
} finally {
|
|
98
|
-
cleanup();
|
|
99
|
-
}
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
test('inverted section renders fallback when array empty', () => {
|
|
103
|
-
const { out, cleanup } = setup();
|
|
104
|
-
try {
|
|
105
|
-
const outPath = join(out, 'empty.html');
|
|
106
|
-
renderReport({
|
|
107
|
-
templateId: '_canned',
|
|
108
|
-
data: { title: 'Empty', items: [] },
|
|
109
|
-
outPath,
|
|
110
|
-
manifestPath: join(fixtures, '_canned.manifest.json'),
|
|
111
|
-
pluginRoot: dirname(fixtures),
|
|
112
|
-
});
|
|
113
|
-
const html = readFileSync(outPath, 'utf8');
|
|
114
|
-
assert.ok(html.includes('No items.'));
|
|
115
|
-
} finally {
|
|
116
|
-
cleanup();
|
|
117
|
-
}
|
|
118
|
-
});
|