@kodrunhq/opencode-autopilot 1.4.0 → 1.5.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/assets/commands/brainstorm.md +7 -0
- package/assets/commands/stocktake.md +7 -0
- package/assets/commands/tdd.md +7 -0
- package/assets/commands/update-docs.md +7 -0
- package/assets/commands/write-plan.md +7 -0
- package/assets/skills/brainstorming/SKILL.md +295 -0
- package/assets/skills/code-review/SKILL.md +241 -0
- package/assets/skills/e2e-testing/SKILL.md +266 -0
- package/assets/skills/git-worktrees/SKILL.md +296 -0
- package/assets/skills/go-patterns/SKILL.md +240 -0
- package/assets/skills/plan-executing/SKILL.md +258 -0
- package/assets/skills/plan-writing/SKILL.md +278 -0
- package/assets/skills/python-patterns/SKILL.md +255 -0
- package/assets/skills/rust-patterns/SKILL.md +293 -0
- package/assets/skills/strategic-compaction/SKILL.md +217 -0
- package/assets/skills/systematic-debugging/SKILL.md +299 -0
- package/assets/skills/tdd-workflow/SKILL.md +311 -0
- package/assets/skills/typescript-patterns/SKILL.md +278 -0
- package/assets/skills/verification/SKILL.md +240 -0
- package/package.json +1 -1
- package/src/index.ts +4 -0
- package/src/orchestrator/skill-injection.ts +38 -0
- package/src/review/sanitize.ts +1 -1
- package/src/skills/adaptive-injector.ts +122 -0
- package/src/skills/dependency-resolver.ts +88 -0
- package/src/skills/linter.ts +113 -0
- package/src/skills/loader.ts +88 -0
- package/src/templates/skill-template.ts +4 -0
- package/src/tools/create-skill.ts +12 -0
- package/src/tools/stocktake.ts +170 -0
- package/src/tools/update-docs.ts +116 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { execFile as execFileCb } from "node:child_process";
|
|
2
|
+
import { basename } from "node:path";
|
|
3
|
+
import { promisify } from "node:util";
|
|
4
|
+
import { tool } from "@opencode-ai/plugin";
|
|
5
|
+
|
|
6
|
+
const execFile = promisify(execFileCb);
|
|
7
|
+
|
|
8
|
+
interface UpdateDocsArgs {
|
|
9
|
+
readonly scope?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface AffectedDoc {
|
|
13
|
+
readonly doc: string;
|
|
14
|
+
readonly reason: string;
|
|
15
|
+
readonly suggestion: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** Run a git command and return stdout lines (empty array on error). */
|
|
19
|
+
async function gitLines(args: readonly string[], cwd: string): Promise<readonly string[]> {
|
|
20
|
+
try {
|
|
21
|
+
const { stdout } = await execFile("git", [...args], { cwd });
|
|
22
|
+
return stdout
|
|
23
|
+
.trim()
|
|
24
|
+
.split("\n")
|
|
25
|
+
.filter((line) => line.length > 0);
|
|
26
|
+
} catch {
|
|
27
|
+
return [];
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export async function updateDocsCore(args: UpdateDocsArgs, projectDir: string): Promise<string> {
|
|
32
|
+
const scope = args.scope ?? "changed";
|
|
33
|
+
|
|
34
|
+
// Get changed source files
|
|
35
|
+
const changedFiles: readonly string[] =
|
|
36
|
+
scope === "all"
|
|
37
|
+
? await gitLines(["ls-files"], projectDir)
|
|
38
|
+
: await gitLines(["diff", "--name-only", "HEAD"], projectDir);
|
|
39
|
+
|
|
40
|
+
// Get all markdown files in the project
|
|
41
|
+
const mdFiles = await gitLines(["ls-files", "*.md"], projectDir);
|
|
42
|
+
|
|
43
|
+
// For each changed source file, check if any markdown file references it
|
|
44
|
+
const affectedDocs: AffectedDoc[] = [];
|
|
45
|
+
const seenDocs = new Set<string>();
|
|
46
|
+
|
|
47
|
+
for (const changedFile of changedFiles) {
|
|
48
|
+
// Skip markdown files themselves
|
|
49
|
+
if (changedFile.endsWith(".md")) continue;
|
|
50
|
+
|
|
51
|
+
const fileBaseName = basename(changedFile);
|
|
52
|
+
// Strip extension for module-style references
|
|
53
|
+
const moduleName = fileBaseName.replace(/\.[^.]+$/, "");
|
|
54
|
+
|
|
55
|
+
for (const mdFile of mdFiles) {
|
|
56
|
+
if (seenDocs.has(`${mdFile}:${changedFile}`)) continue;
|
|
57
|
+
|
|
58
|
+
// Simple heuristic: check if the markdown file path suggests it documents this area
|
|
59
|
+
// or if the changed file's name/module appears in common documentation patterns
|
|
60
|
+
const mdBaseName = basename(mdFile).replace(/\.md$/, "").toLowerCase();
|
|
61
|
+
const changedDir = changedFile.split("/").slice(0, -1).join("/");
|
|
62
|
+
|
|
63
|
+
const isRelated =
|
|
64
|
+
mdBaseName === "readme" ||
|
|
65
|
+
mdBaseName === moduleName.toLowerCase() ||
|
|
66
|
+
(changedDir.length > 0 && mdFile.toLowerCase().includes(changedDir.toLowerCase()));
|
|
67
|
+
|
|
68
|
+
if (isRelated) {
|
|
69
|
+
seenDocs.add(`${mdFile}:${changedFile}`);
|
|
70
|
+
affectedDocs.push({
|
|
71
|
+
doc: mdFile,
|
|
72
|
+
reason: `may be related to ${changedFile} (heuristic: path/name match)`,
|
|
73
|
+
suggestion: `Review ${mdFile} — it may need updates to reflect changes to ${changedFile}`,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Deduplicate by doc path
|
|
80
|
+
const uniqueDocs = Array.from(
|
|
81
|
+
affectedDocs
|
|
82
|
+
.reduce((map, item) => {
|
|
83
|
+
if (!map.has(item.doc)) {
|
|
84
|
+
map.set(item.doc, item);
|
|
85
|
+
}
|
|
86
|
+
return map;
|
|
87
|
+
}, new Map<string, AffectedDoc>())
|
|
88
|
+
.values(),
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
const nonMdChanged = changedFiles.filter((f) => !f.endsWith(".md"));
|
|
92
|
+
|
|
93
|
+
return JSON.stringify(
|
|
94
|
+
{
|
|
95
|
+
changedFiles: nonMdChanged,
|
|
96
|
+
affectedDocs: uniqueDocs,
|
|
97
|
+
summary: `${nonMdChanged.length} source files changed, ${uniqueDocs.length} docs may need updates`,
|
|
98
|
+
},
|
|
99
|
+
null,
|
|
100
|
+
2,
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export const ocUpdateDocs = tool({
|
|
105
|
+
description: "Detect documentation affected by recent code changes and suggest updates.",
|
|
106
|
+
args: {
|
|
107
|
+
scope: tool.schema
|
|
108
|
+
.enum(["changed", "all"])
|
|
109
|
+
.optional()
|
|
110
|
+
.default("changed")
|
|
111
|
+
.describe("Scope: 'changed' for git diff, 'all' for full scan"),
|
|
112
|
+
},
|
|
113
|
+
async execute(args) {
|
|
114
|
+
return updateDocsCore(args, process.cwd());
|
|
115
|
+
},
|
|
116
|
+
});
|