@codemcp/ade 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/.ade/skills/adr-nygard/SKILL.md +45 -0
- package/.ade/skills/conventional-commits/SKILL.md +36 -0
- package/.ade/skills/tanstack-architecture/SKILL.md +25 -0
- package/.ade/skills/tanstack-code/SKILL.md +25 -0
- package/.ade/skills/tanstack-design/SKILL.md +24 -0
- package/.ade/skills/tanstack-testing/SKILL.md +24 -0
- package/.agentskills/skills/adr-nygard/SKILL.md +45 -0
- package/.agentskills/skills/commit/SKILL.md +20 -0
- package/.agentskills/skills/tdd/SKILL.md +10 -0
- package/.beads/README.md +85 -0
- package/.beads/config.yaml +63 -0
- package/.beads/interactions.jsonl +0 -0
- package/.beads/issues.jsonl +46 -0
- package/.beads/last-touched +1 -0
- package/.beads/metadata.json +4 -0
- package/.claude/settings.json +16 -0
- package/.claude/skills/extending-catalog/SKILL.md +41 -0
- package/.cursor/mcp.json +16 -0
- package/.cursor/rules/ade.mdc +10 -0
- package/.github/agents/ade.agent.md +28 -0
- package/.github/copilot-instructions.md +11 -0
- package/.github/workflows/pr.yml +38 -0
- package/.github/workflows/release.yml +124 -0
- package/.husky/post-checkout +2 -0
- package/.husky/post-merge +2 -0
- package/.husky/pre-commit +2 -0
- package/.husky/pre-push +8 -0
- package/.kiro/agents/ade.json +20 -0
- package/.kiro/settings/mcp.json +14 -0
- package/.knowledge/.prettierignore +1 -0
- package/.knowledge/config.yaml +9 -0
- package/.lintstagedrc.js +4 -0
- package/.mcp.json +20 -0
- package/.opencode/agents/ade.md +118 -0
- package/.prettierignore +2 -0
- package/.prettierrc.yaml +3 -0
- package/.vibe/beads-state-ade-autonomy-facet-46zodk.json +29 -0
- package/.vibe/beads-state-ade-fix-no-arch-selected-hvfiio.json +34 -0
- package/.vibe/development-plan-autonomy-facet.md +214 -0
- package/.vibe/development-plan-fix-no-arch-selected.md +103 -0
- package/.vscode/mcp.json +24 -0
- package/LICENSE +21 -0
- package/README.md +293 -0
- package/config.lock.yaml +118 -0
- package/config.yaml +10 -0
- package/docs/CLI-PRD.md +251 -0
- package/docs/CLI-design.md +646 -0
- package/docs/adrs/0001-tui-framework-selection.md +77 -0
- package/eslint.config.mjs +38 -0
- package/opencode.json +17 -0
- package/package.json +79 -0
- package/packages/cli/.prettierignore +1 -0
- package/packages/cli/dist/commands/install.js +39 -0
- package/packages/cli/dist/commands/setup.js +177 -0
- package/packages/cli/dist/index.js +43 -0
- package/packages/cli/dist/knowledge-installer.js +38 -0
- package/packages/cli/dist/version.js +1 -0
- package/packages/cli/eslint.config.mjs +40 -0
- package/packages/cli/nodemon.json +7 -0
- package/packages/cli/package.json +40 -0
- package/packages/cli/src/commands/conventions.integration.spec.ts +267 -0
- package/packages/cli/src/commands/install.integration.spec.ts +123 -0
- package/packages/cli/src/commands/install.spec.ts +169 -0
- package/packages/cli/src/commands/install.ts +63 -0
- package/packages/cli/src/commands/knowledge.integration.spec.ts +129 -0
- package/packages/cli/src/commands/setup.integration.spec.ts +148 -0
- package/packages/cli/src/commands/setup.spec.ts +442 -0
- package/packages/cli/src/commands/setup.ts +252 -0
- package/packages/cli/src/index.ts +52 -0
- package/packages/cli/src/knowledge-installer.spec.ts +111 -0
- package/packages/cli/src/knowledge-installer.ts +54 -0
- package/packages/cli/src/version.ts +1 -0
- package/packages/cli/tsconfig.build.json +8 -0
- package/packages/cli/tsconfig.json +10 -0
- package/packages/cli/tsconfig.vitest.json +7 -0
- package/packages/cli/vitest.config.ts +5 -0
- package/packages/core/.prettierignore +1 -0
- package/packages/core/eslint.config.mjs +40 -0
- package/packages/core/nodemon.json +7 -0
- package/packages/core/package.json +34 -0
- package/packages/core/src/catalog/catalog.spec.ts +570 -0
- package/packages/core/src/catalog/facets/architecture.ts +438 -0
- package/packages/core/src/catalog/facets/autonomy.ts +106 -0
- package/packages/core/src/catalog/facets/backpressure.ts +143 -0
- package/packages/core/src/catalog/facets/practices.ts +173 -0
- package/packages/core/src/catalog/facets/process.ts +50 -0
- package/packages/core/src/catalog/index.ts +93 -0
- package/packages/core/src/config.spec.ts +165 -0
- package/packages/core/src/config.ts +39 -0
- package/packages/core/src/index.ts +55 -0
- package/packages/core/src/registry.spec.ts +145 -0
- package/packages/core/src/registry.ts +70 -0
- package/packages/core/src/resolver.spec.ts +626 -0
- package/packages/core/src/resolver.ts +214 -0
- package/packages/core/src/types.ts +179 -0
- package/packages/core/src/writers/git-hooks.ts +9 -0
- package/packages/core/src/writers/instruction.spec.ts +42 -0
- package/packages/core/src/writers/instruction.ts +8 -0
- package/packages/core/src/writers/knowledge.spec.ts +26 -0
- package/packages/core/src/writers/knowledge.ts +15 -0
- package/packages/core/src/writers/permission-policy.ts +8 -0
- package/packages/core/src/writers/setup-note.ts +9 -0
- package/packages/core/src/writers/skills.spec.ts +109 -0
- package/packages/core/src/writers/skills.ts +9 -0
- package/packages/core/src/writers/workflows.spec.ts +72 -0
- package/packages/core/src/writers/workflows.ts +26 -0
- package/packages/core/tsconfig.build.json +8 -0
- package/packages/core/tsconfig.json +7 -0
- package/packages/core/tsconfig.vitest.json +7 -0
- package/packages/core/vitest.config.ts +5 -0
- package/packages/harnesses/.prettierignore +1 -0
- package/packages/harnesses/eslint.config.mjs +40 -0
- package/packages/harnesses/package.json +35 -0
- package/packages/harnesses/src/index.spec.ts +45 -0
- package/packages/harnesses/src/index.ts +47 -0
- package/packages/harnesses/src/permission-policy.ts +173 -0
- package/packages/harnesses/src/skills-installer.ts +54 -0
- package/packages/harnesses/src/types.ts +12 -0
- package/packages/harnesses/src/util.ts +221 -0
- package/packages/harnesses/src/writers/claude-code.spec.ts +320 -0
- package/packages/harnesses/src/writers/claude-code.ts +107 -0
- package/packages/harnesses/src/writers/cline.spec.ts +212 -0
- package/packages/harnesses/src/writers/cline.ts +24 -0
- package/packages/harnesses/src/writers/copilot.spec.ts +258 -0
- package/packages/harnesses/src/writers/copilot.ts +105 -0
- package/packages/harnesses/src/writers/cursor.spec.ts +219 -0
- package/packages/harnesses/src/writers/cursor.ts +95 -0
- package/packages/harnesses/src/writers/kiro.spec.ts +228 -0
- package/packages/harnesses/src/writers/kiro.ts +89 -0
- package/packages/harnesses/src/writers/opencode.spec.ts +258 -0
- package/packages/harnesses/src/writers/opencode.ts +67 -0
- package/packages/harnesses/src/writers/roo-code.spec.ts +197 -0
- package/packages/harnesses/src/writers/roo-code.ts +71 -0
- package/packages/harnesses/src/writers/universal.spec.ts +134 -0
- package/packages/harnesses/src/writers/universal.ts +84 -0
- package/packages/harnesses/src/writers/windsurf.spec.ts +178 -0
- package/packages/harnesses/src/writers/windsurf.ts +89 -0
- package/packages/harnesses/tsconfig.build.json +8 -0
- package/packages/harnesses/tsconfig.json +7 -0
- package/packages/harnesses/tsconfig.vitest.json +7 -0
- package/packages/harnesses/vitest.config.ts +5 -0
- package/pnpm-workspace.yaml +2 -0
- package/scripts/rename-packages.sh +23 -0
- package/skills-lock.json +20 -0
- package/tsconfig.base.json +25 -0
- package/tsconfig.build.json +7 -0
- package/tsconfig.json +13 -0
- package/turbo.json +47 -0
- package/vitest.config.ts +22 -0
- package/vitest.setup.ts +0 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { workflowsWriter } from "./workflows.js";
|
|
3
|
+
import type { ResolutionContext } from "../types.js";
|
|
4
|
+
|
|
5
|
+
describe("workflowsWriter", () => {
|
|
6
|
+
const context: ResolutionContext = { resolved: {} };
|
|
7
|
+
|
|
8
|
+
it("has id 'workflows'", () => {
|
|
9
|
+
expect(workflowsWriter.id).toBe("workflows");
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it("returns mcp_servers with correct ref, command, and args for a given package", async () => {
|
|
13
|
+
const result = await workflowsWriter.write(
|
|
14
|
+
{ package: "@codemcp/workflows-server" },
|
|
15
|
+
context
|
|
16
|
+
);
|
|
17
|
+
expect(result).toEqual({
|
|
18
|
+
mcp_servers: [
|
|
19
|
+
{
|
|
20
|
+
ref: "@codemcp/workflows-server",
|
|
21
|
+
command: "npx",
|
|
22
|
+
args: ["@codemcp/workflows-server"],
|
|
23
|
+
env: {}
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("uses ref override when provided", async () => {
|
|
30
|
+
const result = await workflowsWriter.write(
|
|
31
|
+
{ package: "@codemcp/workflows-server@latest", ref: "workflows" },
|
|
32
|
+
context
|
|
33
|
+
);
|
|
34
|
+
expect(result.mcp_servers![0].ref).toBe("workflows");
|
|
35
|
+
expect(result.mcp_servers![0].args).toEqual([
|
|
36
|
+
"@codemcp/workflows-server@latest"
|
|
37
|
+
]);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("includes env in the entry when env is specified", async () => {
|
|
41
|
+
const result = await workflowsWriter.write(
|
|
42
|
+
{
|
|
43
|
+
package: "@codemcp/workflows-server",
|
|
44
|
+
env: { API_KEY: "secret", NODE_ENV: "production" }
|
|
45
|
+
},
|
|
46
|
+
context
|
|
47
|
+
);
|
|
48
|
+
expect(result.mcp_servers![0].env).toEqual({
|
|
49
|
+
API_KEY: "secret",
|
|
50
|
+
NODE_ENV: "production"
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("defaults env to an empty object when not specified", async () => {
|
|
55
|
+
const result = await workflowsWriter.write(
|
|
56
|
+
{ package: "@codemcp/workflows-server" },
|
|
57
|
+
context
|
|
58
|
+
);
|
|
59
|
+
expect(result.mcp_servers![0].env).toEqual({});
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("only returns mcp_servers, not other LogicalConfig keys", async () => {
|
|
63
|
+
const result = await workflowsWriter.write(
|
|
64
|
+
{ package: "@codemcp/workflows-server" },
|
|
65
|
+
context
|
|
66
|
+
);
|
|
67
|
+
expect(Object.keys(result)).toEqual(["mcp_servers"]);
|
|
68
|
+
expect(result).not.toHaveProperty("instructions");
|
|
69
|
+
expect(result).not.toHaveProperty("cli_actions");
|
|
70
|
+
expect(result).not.toHaveProperty("knowledge_sources");
|
|
71
|
+
});
|
|
72
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ProvisionWriterDef } from "../types.js";
|
|
2
|
+
|
|
3
|
+
export const workflowsWriter: ProvisionWriterDef = {
|
|
4
|
+
id: "workflows",
|
|
5
|
+
async write(config) {
|
|
6
|
+
const {
|
|
7
|
+
package: pkg,
|
|
8
|
+
ref,
|
|
9
|
+
env
|
|
10
|
+
} = config as {
|
|
11
|
+
package: string;
|
|
12
|
+
ref?: string;
|
|
13
|
+
env?: Record<string, string>;
|
|
14
|
+
};
|
|
15
|
+
return {
|
|
16
|
+
mcp_servers: [
|
|
17
|
+
{
|
|
18
|
+
ref: ref ?? pkg,
|
|
19
|
+
command: "npx",
|
|
20
|
+
args: [pkg],
|
|
21
|
+
env: env ?? {}
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
dist
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import js from "@eslint/js";
|
|
2
|
+
import { parser, configs } from "typescript-eslint";
|
|
3
|
+
import prettier from "eslint-config-prettier";
|
|
4
|
+
|
|
5
|
+
export default [
|
|
6
|
+
js.configs.recommended,
|
|
7
|
+
...configs.recommended,
|
|
8
|
+
prettier,
|
|
9
|
+
{
|
|
10
|
+
// Config for TypeScript files
|
|
11
|
+
files: ["**/*.{ts,tsx}"],
|
|
12
|
+
languageOptions: {
|
|
13
|
+
parser,
|
|
14
|
+
parserOptions: {
|
|
15
|
+
project: ["./tsconfig.json", "./tsconfig.vitest.json"]
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
// Config for JavaScript files - no TypeScript parsing
|
|
21
|
+
files: ["**/*.{js,jsx}"],
|
|
22
|
+
...js.configs.recommended
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
// Relaxed rules for test files
|
|
26
|
+
files: ["**/*.test.ts", "**/*.spec.ts"],
|
|
27
|
+
rules: {
|
|
28
|
+
"@typescript-eslint/no-explicit-any": "off",
|
|
29
|
+
"@typescript-eslint/no-unused-vars": "off"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
ignores: [
|
|
34
|
+
"**/node_modules/**",
|
|
35
|
+
"**/dist/**",
|
|
36
|
+
".pnpm-store/**",
|
|
37
|
+
"pnpm-lock.yaml"
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
];
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@codemcp/ade-harnesses",
|
|
3
|
+
"main": "dist/index.js",
|
|
4
|
+
"types": "dist/index.d.ts",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"publishConfig": {
|
|
7
|
+
"access": "public"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc -p tsconfig.build.json",
|
|
11
|
+
"clean:build": "rimraf ./dist",
|
|
12
|
+
"dev": "nodemon",
|
|
13
|
+
"lint": "eslint .",
|
|
14
|
+
"lint:fix": "eslint --fix .",
|
|
15
|
+
"format": "prettier --check .",
|
|
16
|
+
"format:fix": "prettier --write .",
|
|
17
|
+
"test": "vitest --run",
|
|
18
|
+
"test:watch": "vitest",
|
|
19
|
+
"typecheck": "tsc"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"@codemcp/ade-core": "workspace:*",
|
|
23
|
+
"@codemcp/skills": "^2.3.0"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@typescript-eslint/eslint-plugin": "^8.21.0",
|
|
27
|
+
"@typescript-eslint/parser": "^8.21.0",
|
|
28
|
+
"eslint": "^9.18.0",
|
|
29
|
+
"eslint-config-prettier": "^10.0.1",
|
|
30
|
+
"prettier": "^3.4.2",
|
|
31
|
+
"rimraf": "^6.0.1",
|
|
32
|
+
"typescript": "^5.7.3"
|
|
33
|
+
},
|
|
34
|
+
"version": "0.2.0"
|
|
35
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { allHarnessWriters, getHarnessWriter, getHarnessIds } from "./index.js";
|
|
3
|
+
|
|
4
|
+
describe("harness registry", () => {
|
|
5
|
+
it("exports all harness writers", () => {
|
|
6
|
+
expect(allHarnessWriters).toHaveLength(9);
|
|
7
|
+
const ids = allHarnessWriters.map((w) => w.id);
|
|
8
|
+
expect(ids).toContain("universal");
|
|
9
|
+
expect(ids).toContain("claude-code");
|
|
10
|
+
expect(ids).toContain("cursor");
|
|
11
|
+
expect(ids).toContain("copilot");
|
|
12
|
+
expect(ids).toContain("windsurf");
|
|
13
|
+
expect(ids).toContain("cline");
|
|
14
|
+
expect(ids).toContain("roo-code");
|
|
15
|
+
expect(ids).toContain("kiro");
|
|
16
|
+
expect(ids).toContain("opencode");
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("looks up harness by id", () => {
|
|
20
|
+
expect(getHarnessWriter("cursor")?.label).toBe("Cursor");
|
|
21
|
+
expect(getHarnessWriter("nonexistent")).toBeUndefined();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("returns all harness ids", () => {
|
|
25
|
+
const ids = getHarnessIds();
|
|
26
|
+
expect(ids).toEqual([
|
|
27
|
+
"universal",
|
|
28
|
+
"claude-code",
|
|
29
|
+
"cursor",
|
|
30
|
+
"copilot",
|
|
31
|
+
"windsurf",
|
|
32
|
+
"cline",
|
|
33
|
+
"roo-code",
|
|
34
|
+
"kiro",
|
|
35
|
+
"opencode"
|
|
36
|
+
]);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("all writers have label and description", () => {
|
|
40
|
+
for (const w of allHarnessWriters) {
|
|
41
|
+
expect(w.label).toBeTruthy();
|
|
42
|
+
expect(w.description).toBeTruthy();
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
});
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export type { HarnessWriter } from "./types.js";
|
|
2
|
+
export { installSkills } from "./skills-installer.js";
|
|
3
|
+
export { writeInlineSkills } from "./util.js";
|
|
4
|
+
|
|
5
|
+
export { universalWriter } from "./writers/universal.js";
|
|
6
|
+
export { claudeCodeWriter } from "./writers/claude-code.js";
|
|
7
|
+
export { cursorWriter } from "./writers/cursor.js";
|
|
8
|
+
export { copilotWriter } from "./writers/copilot.js";
|
|
9
|
+
export { windsurfWriter } from "./writers/windsurf.js";
|
|
10
|
+
export { clineWriter } from "./writers/cline.js";
|
|
11
|
+
export { rooCodeWriter } from "./writers/roo-code.js";
|
|
12
|
+
export { kiroWriter } from "./writers/kiro.js";
|
|
13
|
+
export { opencodeWriter } from "./writers/opencode.js";
|
|
14
|
+
|
|
15
|
+
import type { HarnessWriter } from "./types.js";
|
|
16
|
+
import { universalWriter } from "./writers/universal.js";
|
|
17
|
+
import { claudeCodeWriter } from "./writers/claude-code.js";
|
|
18
|
+
import { cursorWriter } from "./writers/cursor.js";
|
|
19
|
+
import { copilotWriter } from "./writers/copilot.js";
|
|
20
|
+
import { windsurfWriter } from "./writers/windsurf.js";
|
|
21
|
+
import { clineWriter } from "./writers/cline.js";
|
|
22
|
+
import { rooCodeWriter } from "./writers/roo-code.js";
|
|
23
|
+
import { kiroWriter } from "./writers/kiro.js";
|
|
24
|
+
import { opencodeWriter } from "./writers/opencode.js";
|
|
25
|
+
|
|
26
|
+
/** All built-in harness writers, ordered for wizard display. */
|
|
27
|
+
export const allHarnessWriters: HarnessWriter[] = [
|
|
28
|
+
universalWriter,
|
|
29
|
+
claudeCodeWriter,
|
|
30
|
+
cursorWriter,
|
|
31
|
+
copilotWriter,
|
|
32
|
+
windsurfWriter,
|
|
33
|
+
clineWriter,
|
|
34
|
+
rooCodeWriter,
|
|
35
|
+
kiroWriter,
|
|
36
|
+
opencodeWriter
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
/** Look up a harness writer by id. */
|
|
40
|
+
export function getHarnessWriter(id: string): HarnessWriter | undefined {
|
|
41
|
+
return allHarnessWriters.find((w) => w.id === id);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** All valid harness IDs. */
|
|
45
|
+
export function getHarnessIds(): string[] {
|
|
46
|
+
return allHarnessWriters.map((w) => w.id);
|
|
47
|
+
}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AutonomyCapability,
|
|
3
|
+
LogicalConfig,
|
|
4
|
+
PermissionDecision,
|
|
5
|
+
PermissionRule
|
|
6
|
+
} from "@codemcp/ade-core";
|
|
7
|
+
|
|
8
|
+
const SENSIBLE_DEFAULTS_RULES: Record<string, PermissionRule> = {
|
|
9
|
+
read: {
|
|
10
|
+
"*": "allow",
|
|
11
|
+
"*.env": "deny",
|
|
12
|
+
"*.env.*": "deny",
|
|
13
|
+
"*.env.example": "allow"
|
|
14
|
+
},
|
|
15
|
+
edit: "allow",
|
|
16
|
+
glob: "allow",
|
|
17
|
+
grep: "allow",
|
|
18
|
+
list: "allow",
|
|
19
|
+
lsp: "allow",
|
|
20
|
+
task: "allow",
|
|
21
|
+
todoread: "deny",
|
|
22
|
+
todowrite: "deny",
|
|
23
|
+
skill: "deny",
|
|
24
|
+
webfetch: "ask",
|
|
25
|
+
websearch: "ask",
|
|
26
|
+
codesearch: "ask",
|
|
27
|
+
bash: {
|
|
28
|
+
"*": "deny",
|
|
29
|
+
"grep *": "allow",
|
|
30
|
+
"rg *": "allow",
|
|
31
|
+
"find *": "allow",
|
|
32
|
+
"fd *": "allow",
|
|
33
|
+
ls: "allow",
|
|
34
|
+
"ls *": "allow",
|
|
35
|
+
"cat *": "allow",
|
|
36
|
+
"head *": "allow",
|
|
37
|
+
"tail *": "allow",
|
|
38
|
+
"wc *": "allow",
|
|
39
|
+
"sort *": "allow",
|
|
40
|
+
"uniq *": "allow",
|
|
41
|
+
"diff *": "allow",
|
|
42
|
+
"echo *": "allow",
|
|
43
|
+
"printf *": "allow",
|
|
44
|
+
pwd: "allow",
|
|
45
|
+
"which *": "allow",
|
|
46
|
+
"type *": "allow",
|
|
47
|
+
whoami: "allow",
|
|
48
|
+
date: "allow",
|
|
49
|
+
"date *": "allow",
|
|
50
|
+
env: "allow",
|
|
51
|
+
"tree *": "allow",
|
|
52
|
+
"file *": "allow",
|
|
53
|
+
"stat *": "allow",
|
|
54
|
+
"readlink *": "allow",
|
|
55
|
+
"realpath *": "allow",
|
|
56
|
+
"dirname *": "allow",
|
|
57
|
+
"basename *": "allow",
|
|
58
|
+
"sed *": "allow",
|
|
59
|
+
"awk *": "allow",
|
|
60
|
+
"cut *": "allow",
|
|
61
|
+
"tr *": "allow",
|
|
62
|
+
"tee *": "allow",
|
|
63
|
+
"xargs *": "allow",
|
|
64
|
+
"jq *": "allow",
|
|
65
|
+
"yq *": "allow",
|
|
66
|
+
"mkdir *": "allow",
|
|
67
|
+
"touch *": "allow",
|
|
68
|
+
"cp *": "ask",
|
|
69
|
+
"mv *": "ask",
|
|
70
|
+
"ln *": "ask",
|
|
71
|
+
"npm *": "ask",
|
|
72
|
+
"node *": "ask",
|
|
73
|
+
"pip *": "ask",
|
|
74
|
+
"python *": "ask",
|
|
75
|
+
"python3 *": "ask",
|
|
76
|
+
"rm *": "deny",
|
|
77
|
+
"rmdir *": "deny",
|
|
78
|
+
"curl *": "deny",
|
|
79
|
+
"wget *": "deny",
|
|
80
|
+
"chmod *": "deny",
|
|
81
|
+
"chown *": "deny",
|
|
82
|
+
"sudo *": "deny",
|
|
83
|
+
"su *": "deny",
|
|
84
|
+
"sh *": "deny",
|
|
85
|
+
"bash *": "deny",
|
|
86
|
+
"zsh *": "deny",
|
|
87
|
+
"eval *": "deny",
|
|
88
|
+
"exec *": "deny",
|
|
89
|
+
"source *": "deny",
|
|
90
|
+
". *": "deny",
|
|
91
|
+
"nohup *": "deny",
|
|
92
|
+
"dd *": "deny",
|
|
93
|
+
"mkfs *": "deny",
|
|
94
|
+
"mount *": "deny",
|
|
95
|
+
"umount *": "deny",
|
|
96
|
+
"kill *": "deny",
|
|
97
|
+
"killall *": "deny",
|
|
98
|
+
"pkill *": "deny",
|
|
99
|
+
"nc *": "deny",
|
|
100
|
+
"ncat *": "deny",
|
|
101
|
+
"ssh *": "deny",
|
|
102
|
+
"scp *": "deny",
|
|
103
|
+
"rsync *": "deny",
|
|
104
|
+
"docker *": "deny",
|
|
105
|
+
"kubectl *": "deny",
|
|
106
|
+
"systemctl *": "deny",
|
|
107
|
+
"service *": "deny",
|
|
108
|
+
"crontab *": "deny",
|
|
109
|
+
reboot: "deny",
|
|
110
|
+
"shutdown *": "deny",
|
|
111
|
+
"passwd *": "deny",
|
|
112
|
+
"useradd *": "deny",
|
|
113
|
+
"userdel *": "deny",
|
|
114
|
+
"iptables *": "deny"
|
|
115
|
+
},
|
|
116
|
+
external_directory: "deny",
|
|
117
|
+
doom_loop: "deny"
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
export function getAutonomyProfile(config: LogicalConfig) {
|
|
121
|
+
return config.permission_policy?.profile;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export function hasPermissionPolicy(config: LogicalConfig): boolean {
|
|
125
|
+
return config.permission_policy !== undefined;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export function getCapabilityDecision(
|
|
129
|
+
config: LogicalConfig,
|
|
130
|
+
capability: AutonomyCapability
|
|
131
|
+
): PermissionDecision | undefined {
|
|
132
|
+
return config.permission_policy?.capabilities?.[capability];
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export function allowsCapability(
|
|
136
|
+
config: LogicalConfig,
|
|
137
|
+
capability: AutonomyCapability
|
|
138
|
+
): boolean {
|
|
139
|
+
return getCapabilityDecision(config, capability) === "allow";
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export function keepsWebOnAsk(config: LogicalConfig): boolean {
|
|
143
|
+
return getCapabilityDecision(config, "web") === "ask";
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export function getHarnessPermissionRules(
|
|
147
|
+
config: LogicalConfig
|
|
148
|
+
): Record<string, PermissionRule> | undefined {
|
|
149
|
+
switch (config.permission_policy?.profile) {
|
|
150
|
+
case "rigid":
|
|
151
|
+
return {
|
|
152
|
+
"*": "ask",
|
|
153
|
+
webfetch: "ask",
|
|
154
|
+
websearch: "ask",
|
|
155
|
+
codesearch: "ask",
|
|
156
|
+
external_directory: "deny",
|
|
157
|
+
doom_loop: "deny"
|
|
158
|
+
};
|
|
159
|
+
case "sensible-defaults":
|
|
160
|
+
return SENSIBLE_DEFAULTS_RULES;
|
|
161
|
+
case "max-autonomy":
|
|
162
|
+
return {
|
|
163
|
+
"*": "allow",
|
|
164
|
+
webfetch: "ask",
|
|
165
|
+
websearch: "ask",
|
|
166
|
+
codesearch: "ask",
|
|
167
|
+
external_directory: "deny",
|
|
168
|
+
doom_loop: "deny"
|
|
169
|
+
};
|
|
170
|
+
default:
|
|
171
|
+
return undefined;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import type { SkillDefinition, InlineSkill } from "@codemcp/ade-core";
|
|
3
|
+
import { runAdd } from "@codemcp/skills/api";
|
|
4
|
+
|
|
5
|
+
function isInlineSkill(skill: SkillDefinition): skill is InlineSkill {
|
|
6
|
+
return "body" in skill;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Install skills using the @codemcp/skills programmatic API.
|
|
11
|
+
*
|
|
12
|
+
* Inline skills are expected to already exist as SKILL.md files under
|
|
13
|
+
* `<projectRoot>/.ade/skills/<name>/` (written by the agent writer).
|
|
14
|
+
* This function calls `runAdd` with the local path for inline skills
|
|
15
|
+
* and the remote source for external skills.
|
|
16
|
+
*
|
|
17
|
+
* Note: `runAdd` uses `process.cwd()` to determine the install destination.
|
|
18
|
+
* This function changes cwd to `projectRoot` before calling `runAdd`.
|
|
19
|
+
*/
|
|
20
|
+
export async function installSkills(
|
|
21
|
+
skills: SkillDefinition[],
|
|
22
|
+
projectRoot: string
|
|
23
|
+
): Promise<void> {
|
|
24
|
+
if (skills.length === 0) return;
|
|
25
|
+
|
|
26
|
+
const originalCwd = process.cwd();
|
|
27
|
+
process.chdir(projectRoot);
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
for (const skill of skills) {
|
|
31
|
+
const source = isInlineSkill(skill)
|
|
32
|
+
? join(projectRoot, ".ade", "skills", skill.name)
|
|
33
|
+
: skill.source;
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
await runAdd([source], { yes: true, all: true });
|
|
37
|
+
} catch (err) {
|
|
38
|
+
// runAdd may throw on network errors for external skills.
|
|
39
|
+
// Log and continue — inline skills should always succeed.
|
|
40
|
+
console.warn(
|
|
41
|
+
`Warning: failed to install skill "${skill.name}" from ${source}:`,
|
|
42
|
+
err instanceof Error ? err.message : err
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
} finally {
|
|
47
|
+
// Restore cwd only if the original directory still exists
|
|
48
|
+
try {
|
|
49
|
+
process.chdir(originalCwd);
|
|
50
|
+
} catch {
|
|
51
|
+
// Original cwd may have been removed (e.g. in tests)
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { AgentWriterDef } from "@codemcp/ade-core";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A harness writer extends AgentWriterDef with metadata for display in the
|
|
5
|
+
* setup wizard and CLI help.
|
|
6
|
+
*/
|
|
7
|
+
export interface HarnessWriter extends AgentWriterDef {
|
|
8
|
+
/** Human-readable label for the wizard (e.g. "Claude Code") */
|
|
9
|
+
label: string;
|
|
10
|
+
/** Short description shown as hint in the wizard */
|
|
11
|
+
description: string;
|
|
12
|
+
}
|