@martinffx/atelier 1.4.0 → 2.0.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/CHANGELOG.md +24 -0
- package/README.md +150 -116
- package/agents/architect.md +6 -6
- package/agents/oracle.md +1 -1
- package/agents/{recon.md → sentinel.md} +3 -3
- package/dist/atelier.js +167 -26
- package/package.json +2 -1
- package/skills/code-review/SKILL.md +2 -2
- package/skills/code-review/references/rq.md +3 -3
- package/skills/code-subagents/SKILL.md +44 -75
- package/skills/code-subagents/references/batch-reviewer-prompt.md +44 -0
- package/skills/code-subagents/references/implementor-prompt.md +10 -11
- package/skills/spec-brainstorm/SKILL.md +19 -14
- package/skills/spec-finish/SKILL.md +14 -14
- package/skills/spec-implement/SKILL.md +40 -39
- package/skills/spec-orchestrator/SKILL.md +71 -36
- package/skills/spec-plan/SKILL.md +79 -25
- package/skills/code-subagents/references/code-quality-reviewer-prompt.md +0 -48
- package/skills/code-subagents/references/spec-reviewer-prompt.md +0 -62
package/dist/atelier.js
CHANGED
|
@@ -31996,10 +31996,13 @@ var coerce = {
|
|
|
31996
31996
|
};
|
|
31997
31997
|
var NEVER = INVALID;
|
|
31998
31998
|
// src/constants.ts
|
|
31999
|
-
var
|
|
32000
|
-
var AGENT_NAMES = ["
|
|
31999
|
+
var Harness = ["claude", "opencode", "codex", "cursor"];
|
|
32000
|
+
var AGENT_NAMES = ["sentinel", "oracle", "architect"];
|
|
32001
|
+
var LEGACY_AGENT_NAME = "recon";
|
|
32001
32002
|
|
|
32002
32003
|
// src/utils/errors.ts
|
|
32004
|
+
var harnessChoices = `${Harness.slice(0, -1).join(", ")}, or ${Harness.at(-1)}`;
|
|
32005
|
+
|
|
32003
32006
|
class AtelierError extends Error {
|
|
32004
32007
|
code;
|
|
32005
32008
|
exitCode;
|
|
@@ -32013,19 +32016,19 @@ class AtelierError extends Error {
|
|
|
32013
32016
|
|
|
32014
32017
|
class ConfigNotFoundError extends AtelierError {
|
|
32015
32018
|
constructor(command) {
|
|
32016
|
-
super(`.atelier/config.json not found. Run \`atelier ${command} --harness
|
|
32019
|
+
super(`.atelier/config.json not found. Run \`atelier ${command} --harness <${Harness.join("|")}>\` first.`, "CONFIG_NOT_FOUND", 1);
|
|
32017
32020
|
}
|
|
32018
32021
|
}
|
|
32019
32022
|
|
|
32020
32023
|
class HarnessRequiredError extends AtelierError {
|
|
32021
32024
|
constructor() {
|
|
32022
|
-
super(
|
|
32025
|
+
super(`\`--yes\` requires \`--harness\` (${harnessChoices}).`, "HARNESS_REQUIRED", 1);
|
|
32023
32026
|
}
|
|
32024
32027
|
}
|
|
32025
32028
|
|
|
32026
32029
|
class InvalidHarnessError extends AtelierError {
|
|
32027
32030
|
constructor(value) {
|
|
32028
|
-
super(`Invalid harness "${value}". Must be
|
|
32031
|
+
super(`Invalid harness "${value}". Must be ${harnessChoices}.`, "INVALID_HARNESS", 1);
|
|
32029
32032
|
}
|
|
32030
32033
|
}
|
|
32031
32034
|
class FileWriteError extends AtelierError {
|
|
@@ -32041,7 +32044,7 @@ class HarnessConfigError extends AtelierError {
|
|
|
32041
32044
|
}
|
|
32042
32045
|
class InvalidConfigError extends AtelierError {
|
|
32043
32046
|
constructor(cause, { suggestReinit = false } = {}) {
|
|
32044
|
-
const suffix = suggestReinit ?
|
|
32047
|
+
const suffix = suggestReinit ? ` Run \`atelier init --harness <${Harness.join("|")}>\` to reconfigure.` : "";
|
|
32045
32048
|
super(`Invalid configuration: ${cause}.${suffix}`, "INVALID_CONFIG", 1);
|
|
32046
32049
|
}
|
|
32047
32050
|
}
|
|
@@ -32131,18 +32134,46 @@ function readConfig(path2 = CONFIG_PATH) {
|
|
|
32131
32134
|
});
|
|
32132
32135
|
}
|
|
32133
32136
|
try {
|
|
32134
|
-
return ok(validateConfig(parsed));
|
|
32137
|
+
return ok(validateConfig(migrateLegacyAgentName(parsed)));
|
|
32135
32138
|
} catch (validationErr) {
|
|
32136
32139
|
const message = validationErr instanceof Error ? validationErr.message : String(validationErr);
|
|
32137
32140
|
return err({ type: "invalid", message });
|
|
32138
32141
|
}
|
|
32139
32142
|
}
|
|
32143
|
+
function migrateLegacyAgentName(config) {
|
|
32144
|
+
if (typeof config !== "object" || config === null) {
|
|
32145
|
+
return config;
|
|
32146
|
+
}
|
|
32147
|
+
const migrated = { ...config };
|
|
32148
|
+
for (const harness of Harness) {
|
|
32149
|
+
const section = migrated[harness];
|
|
32150
|
+
if (typeof section !== "object" || section === null || !Array.isArray(section.agents)) {
|
|
32151
|
+
continue;
|
|
32152
|
+
}
|
|
32153
|
+
const agents = section.agents;
|
|
32154
|
+
migrated[harness] = {
|
|
32155
|
+
...section,
|
|
32156
|
+
agents: agents.map((agent) => {
|
|
32157
|
+
if (typeof agent !== "object" || agent === null) {
|
|
32158
|
+
return agent;
|
|
32159
|
+
}
|
|
32160
|
+
const entry = agent;
|
|
32161
|
+
return {
|
|
32162
|
+
...entry,
|
|
32163
|
+
template: entry.template === LEGACY_AGENT_NAME ? "sentinel" : entry.template,
|
|
32164
|
+
name: entry.name === LEGACY_AGENT_NAME ? "sentinel" : entry.name
|
|
32165
|
+
};
|
|
32166
|
+
})
|
|
32167
|
+
};
|
|
32168
|
+
}
|
|
32169
|
+
return migrated;
|
|
32170
|
+
}
|
|
32140
32171
|
function isOldFlatConfig(config) {
|
|
32141
32172
|
if (typeof config !== "object" || config === null) {
|
|
32142
32173
|
return false;
|
|
32143
32174
|
}
|
|
32144
32175
|
const record = config;
|
|
32145
|
-
return typeof record.harness === "string" &&
|
|
32176
|
+
return typeof record.harness === "string" && Harness.every((harness) => record[harness] == null);
|
|
32146
32177
|
}
|
|
32147
32178
|
function writeConfig(config, path2 = CONFIG_PATH) {
|
|
32148
32179
|
const dir = dirname(path2);
|
|
@@ -32153,7 +32184,7 @@ function writeConfig(config, path2 = CONFIG_PATH) {
|
|
|
32153
32184
|
`);
|
|
32154
32185
|
}
|
|
32155
32186
|
function getConfiguredHarnesses(config) {
|
|
32156
|
-
return
|
|
32187
|
+
return Harness.filter((harness) => config[harness] !== undefined);
|
|
32157
32188
|
}
|
|
32158
32189
|
function removeConfigDir(path2 = CONFIG_PATH) {
|
|
32159
32190
|
const dir = dirname(path2);
|
|
@@ -32292,7 +32323,7 @@ async function init(options2) {
|
|
|
32292
32323
|
}
|
|
32293
32324
|
let harness;
|
|
32294
32325
|
if (harnessOption) {
|
|
32295
|
-
if (!
|
|
32326
|
+
if (!Harness.includes(harnessOption)) {
|
|
32296
32327
|
throw new InvalidHarnessError(harnessOption);
|
|
32297
32328
|
}
|
|
32298
32329
|
harness = harnessOption;
|
|
@@ -32302,7 +32333,7 @@ async function init(options2) {
|
|
|
32302
32333
|
type: "list",
|
|
32303
32334
|
name: "harness",
|
|
32304
32335
|
message: "Which harness are you using?",
|
|
32305
|
-
choices:
|
|
32336
|
+
choices: Harness
|
|
32306
32337
|
}
|
|
32307
32338
|
]);
|
|
32308
32339
|
harness = answer.harness;
|
|
@@ -32348,7 +32379,7 @@ Files to write:`);
|
|
|
32348
32379
|
Atelier initialized for ${harness}.`);
|
|
32349
32380
|
console.log(`
|
|
32350
32381
|
Next step:`);
|
|
32351
|
-
if (harness === "opencode" && section.provider === "openai") {
|
|
32382
|
+
if (harness === "opencode" && "provider" in section && section.provider === "openai") {
|
|
32352
32383
|
console.log(" opencode auth login --provider openai # connect your OpenAI account");
|
|
32353
32384
|
}
|
|
32354
32385
|
console.log(" npx skills add martinffx/atelier # install skills");
|
|
@@ -32361,7 +32392,7 @@ import { homedir as homedir4 } from "os";
|
|
|
32361
32392
|
// src/commands/utils.ts
|
|
32362
32393
|
async function resolveHarness(config, harnessOption, command) {
|
|
32363
32394
|
if (harnessOption) {
|
|
32364
|
-
if (!
|
|
32395
|
+
if (!Harness.includes(harnessOption)) {
|
|
32365
32396
|
throw new InvalidHarnessError(harnessOption);
|
|
32366
32397
|
}
|
|
32367
32398
|
const configured2 = getConfiguredHarnesses(config);
|
|
@@ -32493,6 +32524,9 @@ var SimpleConfigSchema = exports_external.object({
|
|
|
32493
32524
|
default_model: exports_external.string().min(1),
|
|
32494
32525
|
agents: exports_external.array(AgentSchema).min(1)
|
|
32495
32526
|
});
|
|
32527
|
+
var CursorConfigSchema = exports_external.object({
|
|
32528
|
+
agents: exports_external.array(AgentSchema).min(1)
|
|
32529
|
+
}).strict();
|
|
32496
32530
|
var OPENCODE_PROVIDERS = ["opencode-zen", "opencode-go", "amazon-bedrock", "openai"];
|
|
32497
32531
|
var OpenCodeConfigSchema = exports_external.object({
|
|
32498
32532
|
provider: exports_external.enum(OPENCODE_PROVIDERS),
|
|
@@ -32505,7 +32539,7 @@ var OpenCodeConfigSchema = exports_external.object({
|
|
|
32505
32539
|
var ANTHROPIC_MODELS = ["haiku", "sonnet", "opus", "opusplan"];
|
|
32506
32540
|
var DEFAULT_MODELS = {
|
|
32507
32541
|
default_model: "opusplan",
|
|
32508
|
-
|
|
32542
|
+
sentinel: "haiku",
|
|
32509
32543
|
oracle: "opus",
|
|
32510
32544
|
architect: "opus"
|
|
32511
32545
|
};
|
|
@@ -32545,6 +32579,7 @@ function installAgents(section, basePath) {
|
|
|
32545
32579
|
} catch (err2) {
|
|
32546
32580
|
throw new FileWriteError(agentsDir, err2 instanceof Error ? err2.message : String(err2));
|
|
32547
32581
|
}
|
|
32582
|
+
rmSync2(join7(agentsDir, `${LEGACY_AGENT_NAME}.md`), { force: true });
|
|
32548
32583
|
for (const agent of config.agents) {
|
|
32549
32584
|
const template = readTemplate(agent.template);
|
|
32550
32585
|
const frontmatter = `---
|
|
@@ -32599,6 +32634,7 @@ function remove2(section, basePath) {
|
|
|
32599
32634
|
rmSync2(file, { force: true });
|
|
32600
32635
|
}
|
|
32601
32636
|
}
|
|
32637
|
+
rmSync2(join7(agentsDir, `${LEGACY_AGENT_NAME}.md`), { force: true });
|
|
32602
32638
|
removeDirIfEmpty(agentsDir);
|
|
32603
32639
|
removeAtelierSettings(claudeDir);
|
|
32604
32640
|
}
|
|
@@ -32717,28 +32753,28 @@ var PROVIDER_MODELS = {
|
|
|
32717
32753
|
};
|
|
32718
32754
|
var DEFAULT_MODELS2 = {
|
|
32719
32755
|
"opencode-zen": {
|
|
32720
|
-
|
|
32756
|
+
sentinel: "opencode/minimax-m2.7",
|
|
32721
32757
|
oracle: "opencode/kimi-k2.6",
|
|
32722
32758
|
architect: "opencode/deepseek-v4-pro",
|
|
32723
32759
|
build: "opencode/deepseek-v4-flash",
|
|
32724
32760
|
plan: "opencode/deepseek-v4-pro"
|
|
32725
32761
|
},
|
|
32726
32762
|
"opencode-go": {
|
|
32727
|
-
|
|
32763
|
+
sentinel: "opencode-go/minimax-m2.7",
|
|
32728
32764
|
oracle: "opencode-go/kimi-k2.6",
|
|
32729
32765
|
architect: "opencode-go/deepseek-v4-pro",
|
|
32730
32766
|
build: "opencode-go/deepseek-v4-flash",
|
|
32731
32767
|
plan: "opencode-go/deepseek-v4-pro"
|
|
32732
32768
|
},
|
|
32733
32769
|
"amazon-bedrock": {
|
|
32734
|
-
|
|
32770
|
+
sentinel: "amazon-bedrock/anthropic-claude-haiku-4-5",
|
|
32735
32771
|
oracle: "amazon-bedrock/anthropic-claude-opus-4-7",
|
|
32736
32772
|
architect: "amazon-bedrock/anthropic-claude-opus-4-7",
|
|
32737
32773
|
build: "amazon-bedrock/anthropic-claude-sonnet-4-5",
|
|
32738
32774
|
plan: "amazon-bedrock/anthropic-claude-haiku-4-5"
|
|
32739
32775
|
},
|
|
32740
32776
|
openai: {
|
|
32741
|
-
|
|
32777
|
+
sentinel: "openai/gpt-5.6-luna",
|
|
32742
32778
|
oracle: "openai/gpt-5.6-sol",
|
|
32743
32779
|
architect: "openai/gpt-5.6-sol",
|
|
32744
32780
|
build: "openai/gpt-5.6-terra",
|
|
@@ -32790,6 +32826,7 @@ function installAgents2(section, basePath) {
|
|
|
32790
32826
|
} catch (err2) {
|
|
32791
32827
|
throw new FileWriteError(agentsDir, err2 instanceof Error ? err2.message : String(err2));
|
|
32792
32828
|
}
|
|
32829
|
+
rmSync3(join8(agentsDir, `${LEGACY_AGENT_NAME}.md`), { force: true });
|
|
32793
32830
|
for (const agent of config.agents) {
|
|
32794
32831
|
const template = readTemplate(agent.template);
|
|
32795
32832
|
const frontmatter = `---
|
|
@@ -32816,13 +32853,13 @@ function mergeHarnessConfig2(section, basePath) {
|
|
|
32816
32853
|
} catch (err2) {
|
|
32817
32854
|
throw new FileWriteError(basePath, err2 instanceof Error ? err2.message : String(err2));
|
|
32818
32855
|
}
|
|
32819
|
-
const
|
|
32856
|
+
const sentinel = config.agents.find((a) => a.name === "sentinel");
|
|
32820
32857
|
const architect = config.agents.find((a) => a.name === "architect");
|
|
32821
32858
|
const atelierFields = {
|
|
32822
32859
|
agent: {
|
|
32823
32860
|
build: {
|
|
32824
32861
|
mode: "primary",
|
|
32825
|
-
model: config.build_model ||
|
|
32862
|
+
model: config.build_model || sentinel?.model || DEFAULT_MODELS2[config.provider].build
|
|
32826
32863
|
},
|
|
32827
32864
|
plan: {
|
|
32828
32865
|
mode: "primary",
|
|
@@ -32874,6 +32911,7 @@ function removeAgentFiles(opencodeRoot, config) {
|
|
|
32874
32911
|
rmSync3(file, { force: true });
|
|
32875
32912
|
}
|
|
32876
32913
|
}
|
|
32914
|
+
rmSync3(join8(agentsDir, `${LEGACY_AGENT_NAME}.md`), { force: true });
|
|
32877
32915
|
removeDirIfEmpty2(agentsDir);
|
|
32878
32916
|
}
|
|
32879
32917
|
function removeDirIfEmpty2(dir) {
|
|
@@ -34045,7 +34083,7 @@ var OPENAI_MODELS = [
|
|
|
34045
34083
|
];
|
|
34046
34084
|
var DEFAULT_MODELS3 = {
|
|
34047
34085
|
default_model: "gpt-5.6-terra",
|
|
34048
|
-
|
|
34086
|
+
sentinel: "gpt-5.6-luna",
|
|
34049
34087
|
oracle: "gpt-5.6-sol",
|
|
34050
34088
|
architect: "gpt-5.6-sol"
|
|
34051
34089
|
};
|
|
@@ -34098,6 +34136,7 @@ function installAgents3(section, basePath) {
|
|
|
34098
34136
|
} catch (err2) {
|
|
34099
34137
|
throw new FileWriteError(agentsDir, err2 instanceof Error ? err2.message : String(err2));
|
|
34100
34138
|
}
|
|
34139
|
+
rmSync4(join9(agentsDir, `${LEGACY_AGENT_NAME}.toml`), { force: true });
|
|
34101
34140
|
for (const agent of config.agents) {
|
|
34102
34141
|
const template = readTemplate(agent.template);
|
|
34103
34142
|
const content = {
|
|
@@ -34167,6 +34206,7 @@ function remove4(section, basePath) {
|
|
|
34167
34206
|
rmSync4(file, { force: true });
|
|
34168
34207
|
}
|
|
34169
34208
|
}
|
|
34209
|
+
rmSync4(join9(agentsDir, `${LEGACY_AGENT_NAME}.toml`), { force: true });
|
|
34170
34210
|
removeDirIfEmpty3(agentsDir);
|
|
34171
34211
|
cleanCodexConfig(codexDir);
|
|
34172
34212
|
removeEmptyCodexDir(codexDir);
|
|
@@ -34246,22 +34286,123 @@ function isObject(value) {
|
|
|
34246
34286
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
34247
34287
|
}
|
|
34248
34288
|
|
|
34289
|
+
// src/adapters/cursor.ts
|
|
34290
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync5, readdirSync as readdirSync4, rmSync as rmSync5, rmdirSync as rmdirSync4, writeFileSync as writeFileSync6 } from "fs";
|
|
34291
|
+
import { join as join10 } from "path";
|
|
34292
|
+
var CURSOR_MODELS = [
|
|
34293
|
+
"composer-2.5",
|
|
34294
|
+
"cursor-grok-4.5-high",
|
|
34295
|
+
"gpt-5.6-luna-medium",
|
|
34296
|
+
"gpt-5.6-terra-medium",
|
|
34297
|
+
"gpt-5.6-sol-medium",
|
|
34298
|
+
"claude-opus-4-8-high",
|
|
34299
|
+
"claude-sonnet-5-high",
|
|
34300
|
+
"kimi-k2.7-code",
|
|
34301
|
+
"glm-5.2-high"
|
|
34302
|
+
];
|
|
34303
|
+
var DEFAULT_MODELS4 = {
|
|
34304
|
+
sentinel: "composer-2.5",
|
|
34305
|
+
oracle: "claude-opus-4-8-high",
|
|
34306
|
+
architect: "gpt-5.6-sol-medium"
|
|
34307
|
+
};
|
|
34308
|
+
var cursorAdapter = {
|
|
34309
|
+
name: "cursor",
|
|
34310
|
+
configSchema: CursorConfigSchema,
|
|
34311
|
+
defaultSection: defaultSection4,
|
|
34312
|
+
modelsForProvider: modelsForProvider4,
|
|
34313
|
+
promptSection: promptSection4,
|
|
34314
|
+
installAgents: installAgents4,
|
|
34315
|
+
mergeHarnessConfig: mergeHarnessConfig4,
|
|
34316
|
+
fileList: fileList4,
|
|
34317
|
+
remove: remove5
|
|
34318
|
+
};
|
|
34319
|
+
function defaultSection4() {
|
|
34320
|
+
return {
|
|
34321
|
+
agents: AGENT_NAMES.map((name) => ({ template: name, name, model: DEFAULT_MODELS4[name] }))
|
|
34322
|
+
};
|
|
34323
|
+
}
|
|
34324
|
+
function modelsForProvider4(_provider) {
|
|
34325
|
+
return CURSOR_MODELS;
|
|
34326
|
+
}
|
|
34327
|
+
async function promptSection4(prompt2, section) {
|
|
34328
|
+
const config = section;
|
|
34329
|
+
const answers = await prompt2.prompt(AGENT_NAMES.map((name) => ({
|
|
34330
|
+
type: "list",
|
|
34331
|
+
name,
|
|
34332
|
+
message: `Select model for ${name}`,
|
|
34333
|
+
choices: CURSOR_MODELS,
|
|
34334
|
+
default: config.agents.find((agent) => agent.name === name)?.model ?? DEFAULT_MODELS4[name]
|
|
34335
|
+
})));
|
|
34336
|
+
return {
|
|
34337
|
+
agents: AGENT_NAMES.map((name) => ({
|
|
34338
|
+
template: name,
|
|
34339
|
+
name,
|
|
34340
|
+
model: answers[name] ?? DEFAULT_MODELS4[name]
|
|
34341
|
+
}))
|
|
34342
|
+
};
|
|
34343
|
+
}
|
|
34344
|
+
function installAgents4(section, basePath) {
|
|
34345
|
+
const config = section;
|
|
34346
|
+
const agentsDir = join10(basePath, ".cursor", "agents");
|
|
34347
|
+
try {
|
|
34348
|
+
mkdirSync5(agentsDir, { recursive: true });
|
|
34349
|
+
} catch (err2) {
|
|
34350
|
+
throw new FileWriteError(agentsDir, err2 instanceof Error ? err2.message : String(err2));
|
|
34351
|
+
}
|
|
34352
|
+
rmSync5(join10(agentsDir, `${LEGACY_AGENT_NAME}.md`), { force: true });
|
|
34353
|
+
for (const agent of config.agents) {
|
|
34354
|
+
const template = readTemplate(agent.template);
|
|
34355
|
+
const content = `---
|
|
34356
|
+
name: ${agent.name}
|
|
34357
|
+
description: ${template.description}
|
|
34358
|
+
model: ${agent.model}
|
|
34359
|
+
---
|
|
34360
|
+
${template.body}`;
|
|
34361
|
+
const agentPath = join10(agentsDir, `${agent.name}.md`);
|
|
34362
|
+
writeFileSync6(agentPath, content);
|
|
34363
|
+
console.log(`Created ${shortPath(agentPath)}`);
|
|
34364
|
+
}
|
|
34365
|
+
}
|
|
34366
|
+
function mergeHarnessConfig4(_section, _basePath) {}
|
|
34367
|
+
function fileList4(basePath) {
|
|
34368
|
+
return AGENT_NAMES.map((name) => {
|
|
34369
|
+
const path2 = join10(basePath, ".cursor", "agents", `${name}.md`);
|
|
34370
|
+
return { path: path2, exists: existsSync6(path2) };
|
|
34371
|
+
});
|
|
34372
|
+
}
|
|
34373
|
+
function remove5(section, basePath) {
|
|
34374
|
+
const config = section;
|
|
34375
|
+
const agentsDir = join10(basePath, ".cursor", "agents");
|
|
34376
|
+
try {
|
|
34377
|
+
for (const agent of config.agents) {
|
|
34378
|
+
rmSync5(join10(agentsDir, `${agent.name}.md`), { force: true });
|
|
34379
|
+
}
|
|
34380
|
+
rmSync5(join10(agentsDir, `${LEGACY_AGENT_NAME}.md`), { force: true });
|
|
34381
|
+
if (existsSync6(agentsDir) && readdirSync4(agentsDir).length === 0) {
|
|
34382
|
+
rmdirSync4(agentsDir);
|
|
34383
|
+
}
|
|
34384
|
+
} catch (err2) {
|
|
34385
|
+
throw new FileWriteError(agentsDir, err2 instanceof Error ? err2.message : String(err2));
|
|
34386
|
+
}
|
|
34387
|
+
}
|
|
34388
|
+
|
|
34249
34389
|
// src/adapters/index.ts
|
|
34250
34390
|
registerAdapter(claudeAdapter);
|
|
34251
34391
|
registerAdapter(opencodeAdapter);
|
|
34252
34392
|
registerAdapter(codexAdapter);
|
|
34393
|
+
registerAdapter(cursorAdapter);
|
|
34253
34394
|
|
|
34254
34395
|
// src/atelier.ts
|
|
34255
|
-
var
|
|
34396
|
+
var harnessChoices2 = Harness.join(", ");
|
|
34256
34397
|
var program2 = new Command;
|
|
34257
|
-
program2.name("atelier").description("Atelier CLI - configure Claude Code, OpenCode, and
|
|
34258
|
-
program2.command("init", { isDefault: true }).description("Initialize atelier globally").option(`--harness <type>`, `Harness type (${
|
|
34398
|
+
program2.name("atelier").description("Atelier CLI - configure Claude Code, OpenCode, Codex, and Cursor for spec-driven development").version("0.1.0");
|
|
34399
|
+
program2.command("init", { isDefault: true }).description("Initialize atelier globally").option(`--harness <type>`, `Harness type (${harnessChoices2})`).option("--yes", "Non-interactive mode with defaults").action((options2) => {
|
|
34259
34400
|
init(options2).catch(handleError);
|
|
34260
34401
|
});
|
|
34261
|
-
program2.command("update").description("Update atelier agents").option(`--harness <type>`, `Harness type (${
|
|
34402
|
+
program2.command("update").description("Update atelier agents").option(`--harness <type>`, `Harness type (${harnessChoices2})`).action((options2) => {
|
|
34262
34403
|
update(options2).catch(handleError);
|
|
34263
34404
|
});
|
|
34264
|
-
program2.command("remove").description("Remove a configured harness from atelier").option(`--harness <type>`, `Harness type (${
|
|
34405
|
+
program2.command("remove").description("Remove a configured harness from atelier").option(`--harness <type>`, `Harness type (${harnessChoices2})`).action((options2) => {
|
|
34265
34406
|
remove(options2).catch(handleError);
|
|
34266
34407
|
});
|
|
34267
34408
|
program2.parse();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@martinffx/atelier",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Personal development toolkit - spec-driven development, code quality, deep thinking, and ecosystem patterns",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"claude-code",
|
|
13
13
|
"opencode",
|
|
14
14
|
"codex",
|
|
15
|
+
"cursor",
|
|
15
16
|
"ai-agents",
|
|
16
17
|
"spec-driven-development"
|
|
17
18
|
],
|
|
@@ -34,7 +34,7 @@ Use these concrete harness subagent types. If an exact match is unavailable, use
|
|
|
34
34
|
|
|
35
35
|
| `subagent_type` | Purpose |
|
|
36
36
|
|-----------------|---------|
|
|
37
|
-
| `
|
|
37
|
+
| `sentinel` | Triage only: changed-file analysis, context retrieval, reviewer selection |
|
|
38
38
|
| `oracle` | Parallel reviewer personas, evidence-based critique, failure-mode analysis, challenge validation |
|
|
39
39
|
| `architect` | Architecture, design-boundary, data-model, and API-contract review |
|
|
40
40
|
|
|
@@ -67,7 +67,7 @@ Follows [code-subagents](../code-subagents/SKILL.md) patterns:
|
|
|
67
67
|
|
|
68
68
|
| Agent | Used In Step |
|
|
69
69
|
|-------|--------------|
|
|
70
|
-
| `
|
|
70
|
+
| `sentinel` | Triage only (context retrieval, file analysis) |
|
|
71
71
|
| `oracle` | Reviewers and challenge validation |
|
|
72
72
|
| `architect` | Architect (architecture review) |
|
|
73
73
|
|
|
@@ -34,12 +34,12 @@ Capture the list of changed files and the full diff.
|
|
|
34
34
|
|
|
35
35
|
**Purpose:** Analyze diff to determine context, select reviewers, identify relevant skills to look for.
|
|
36
36
|
|
|
37
|
-
**Uses:** `
|
|
37
|
+
**Uses:** `sentinel` agent.
|
|
38
38
|
|
|
39
39
|
### Subagent Invocation
|
|
40
40
|
|
|
41
41
|
```yaml
|
|
42
|
-
subagent_type:
|
|
42
|
+
subagent_type: sentinel
|
|
43
43
|
description: "Triage diff for code review"
|
|
44
44
|
prompt: |
|
|
45
45
|
Analyze this code diff to determine review needs.
|
|
@@ -364,7 +364,7 @@ Display findings in terminal per [output.md](./output.md).
|
|
|
364
364
|
| Step | Subagent | Uses | Parallel? | Purpose |
|
|
365
365
|
|------|----------|------|----------|---------|
|
|
366
366
|
| 1 | Get Diff | inline | — | `git diff <branch>` |
|
|
367
|
-
| 2 | Triage | `
|
|
367
|
+
| 2 | Triage | `sentinel` agent | No | Detect context, select reviewers, identify relevant skills to look for |
|
|
368
368
|
| 3 | Reviewers | `oracle` agent | Yes (per reviewer) | Specialty analysis |
|
|
369
369
|
| 4 | Synthesis | inline | No | Deduplicate and group |
|
|
370
370
|
| 5 | Architect | `architect` agent | No | Architecture review |
|
|
@@ -1,25 +1,23 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: code-subagents
|
|
3
3
|
description: >
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
and integration of results. Trigger when executing plan tasks with subagent support, when
|
|
8
|
-
facing 2+ independent problems, or when the user asks to use subagents for implementation.
|
|
4
|
+
Implementation subagent dispatch patterns. Use when independent implementation work is
|
|
5
|
+
available and subagents can execute it. Covers parallel dispatch, shared-tree patch
|
|
6
|
+
snapshots, one combined review per completed batch, and serial integration.
|
|
9
7
|
user-invocable: false
|
|
10
8
|
---
|
|
11
9
|
|
|
12
|
-
#
|
|
10
|
+
# Implementation Subagents
|
|
13
11
|
|
|
14
|
-
Fresh subagent per task.
|
|
15
|
-
when dependent.
|
|
12
|
+
Fresh subagent per task. One combined review per completed batch. Parallel when independent,
|
|
13
|
+
sequential when dependent.
|
|
16
14
|
|
|
17
15
|
## When to Use Subagents
|
|
18
16
|
|
|
19
17
|
**Use when:**
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
- Each problem can be understood without context from
|
|
18
|
+
- 2+ independent work items do not share state or files
|
|
19
|
+
- Each work item has explicit requirements, constraints, files, and validation
|
|
20
|
+
- Each problem can be understood without context from the other work items
|
|
23
21
|
|
|
24
22
|
**Don't use when:**
|
|
25
23
|
- Tasks are tightly coupled (editing the same files)
|
|
@@ -53,6 +51,13 @@ Task C (notification tests) ──→ review → complete
|
|
|
53
51
|
**Independence check:** Would fixing Task A affect Task B? Would they edit the same files?
|
|
54
52
|
If no to both, dispatch in parallel.
|
|
55
53
|
|
|
54
|
+
For shared-tree parallel work:
|
|
55
|
+
|
|
56
|
+
1. Assign each task an exclusive file list before dispatch
|
|
57
|
+
2. Do not let implementers stage or commit changes
|
|
58
|
+
3. Capture a path-scoped `git diff` for each task when it reports completion
|
|
59
|
+
4. Run tasks sequentially if their file ownership overlaps or cannot be isolated
|
|
60
|
+
|
|
56
61
|
---
|
|
57
62
|
|
|
58
63
|
## Prompt Templates
|
|
@@ -60,15 +65,14 @@ If no to both, dispatch in parallel.
|
|
|
60
65
|
Use these templates when dispatching subagents. Each template is battle-tested — don't
|
|
61
66
|
improvise, use them as-is and fill in the variables.
|
|
62
67
|
|
|
63
|
-
- **[references/
|
|
64
|
-
- **[references/
|
|
65
|
-
- **[references/code-quality-reviewer-prompt.md](references/code-quality-reviewer-prompt.md)** — Code quality review. Critical/Important/Minor severity.
|
|
68
|
+
- **[references/implementor-prompt.md](references/implementor-prompt.md)** — Dispatch an implementer. Includes self-review checklist.
|
|
69
|
+
- **[references/batch-reviewer-prompt.md](references/batch-reviewer-prompt.md)** — Combined plan and code-quality review for one completed batch.
|
|
66
70
|
|
|
67
71
|
### Prompt quality rules
|
|
68
72
|
|
|
69
73
|
- **Focused** — one task, one problem domain
|
|
70
|
-
- **Self-contained** — all context needed is in the prompt.
|
|
71
|
-
|
|
74
|
+
- **Self-contained** — all context needed is in the prompt. Provide the complete work-item
|
|
75
|
+
requirements; do not make the subagent recover context
|
|
72
76
|
- **Specific about files** — exact paths, not "the relevant files"
|
|
73
77
|
- **Specific about output** — what should the subagent return?
|
|
74
78
|
- **Constrained** — what should they NOT touch?
|
|
@@ -84,63 +88,30 @@ improvise, use them as-is and fill in the variables.
|
|
|
84
88
|
|
|
85
89
|
---
|
|
86
90
|
|
|
87
|
-
##
|
|
88
|
-
|
|
89
|
-
Every completed task gets two reviews in order. Do not skip either. Do not reverse the order.
|
|
90
|
-
|
|
91
|
-
### Stage 1: Spec Compliance
|
|
92
|
-
|
|
93
|
-
Does the implementation match what was specified?
|
|
91
|
+
## Batch Review
|
|
94
92
|
|
|
95
|
-
|
|
96
|
-
## Spec Review
|
|
93
|
+
Run one combined review after every completed batch, not separate reviews for each task.
|
|
97
94
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
**Task spec:** [paste task from plan.json]
|
|
101
|
-
|
|
102
|
-
**Files changed:** [list from subagent output]
|
|
103
|
-
|
|
104
|
-
Check:
|
|
105
|
-
1. Are all requirements from the task spec implemented?
|
|
106
|
-
2. Is anything implemented that wasn't specified? (over-building)
|
|
107
|
-
3. Do tests cover the specified acceptance criteria?
|
|
108
|
-
4. Does the implementation match the design in design.md?
|
|
109
|
-
|
|
110
|
-
Report: List any gaps or extras. Mark ✅ if compliant, ❌ if not.
|
|
111
|
-
```
|
|
95
|
+
Give one fresh reviewer:
|
|
112
96
|
|
|
113
|
-
|
|
114
|
-
|
|
97
|
+
- The complete requirements for work items in the batch
|
|
98
|
+
- The relevant constraints
|
|
99
|
+
- The path-scoped patch captured for each task
|
|
100
|
+
- The implementers' reports and validation results
|
|
115
101
|
|
|
116
|
-
|
|
102
|
+
The reviewer checks both requirements compliance and code quality:
|
|
117
103
|
|
|
118
|
-
|
|
104
|
+
1. Every requirement and acceptance criterion is implemented
|
|
105
|
+
2. The batch follows the supplied constraints
|
|
106
|
+
3. No unrequested work or out-of-scope files are included
|
|
107
|
+
4. Tests are meaningful and cover the right boundaries
|
|
108
|
+
5. The code follows existing patterns without unnecessary complexity
|
|
119
109
|
|
|
120
|
-
|
|
121
|
-
## Code Quality Review
|
|
110
|
+
Use [references/batch-reviewer-prompt.md](references/batch-reviewer-prompt.md) as written.
|
|
122
111
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
Check:
|
|
128
|
-
1. Does the code follow existing patterns and conventions?
|
|
129
|
-
2. Are tests meaningful (not just asserting true)?
|
|
130
|
-
3. Is there unnecessary complexity?
|
|
131
|
-
4. Are edge cases handled?
|
|
132
|
-
5. Is the code clean (no dead code, no unnecessary comments)?
|
|
133
|
-
|
|
134
|
-
Rate issues as Critical (blocks merge), Important (should fix), or Minor (nice to have).
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
If the quality reviewer finds Critical or Important issues → implementer fixes → reviewer
|
|
138
|
-
reviews again. Minor issues can be noted and moved past.
|
|
139
|
-
|
|
140
|
-
### Why this order matters
|
|
141
|
-
|
|
142
|
-
Spec compliance first because there's no point polishing code that doesn't meet the spec.
|
|
143
|
-
Quality second because compliant code still needs to be well-built.
|
|
112
|
+
If the reviewer finds Critical or Important issues, send each issue back to the relevant
|
|
113
|
+
implementer, refresh its path-scoped patch, and review the batch again. Minor issues may be
|
|
114
|
+
noted and moved past.
|
|
144
115
|
|
|
145
116
|
---
|
|
146
117
|
|
|
@@ -161,9 +132,11 @@ they're thinking rather than guessing.
|
|
|
161
132
|
After subagents complete (especially parallel dispatch):
|
|
162
133
|
|
|
163
134
|
1. **Read each summary** — understand what changed
|
|
164
|
-
2. **
|
|
165
|
-
3. **
|
|
166
|
-
4. **
|
|
135
|
+
2. **Capture task patches** — use each task's exclusive file list
|
|
136
|
+
3. **Review the batch** — one combined requirements and quality review
|
|
137
|
+
4. **Run full test suite** — verify all changes work together
|
|
138
|
+
5. **Commit** — the coordinator commits the reviewed batch serially
|
|
139
|
+
6. **Update progress tracking** — when the caller uses it
|
|
167
140
|
|
|
168
141
|
If there are conflicts between parallel results, resolve them manually. Don't dispatch
|
|
169
142
|
another subagent to merge — that requires too much context.
|
|
@@ -176,9 +149,5 @@ If a subagent fails a task:
|
|
|
176
149
|
|
|
177
150
|
- **Don't fix it manually** — that pollutes your context
|
|
178
151
|
- **Dispatch a fix subagent** with specific instructions about what went wrong
|
|
179
|
-
- **If it fails twice**, stop and escalate to the human. The
|
|
180
|
-
|
|
181
|
-
If failure reveals a design problem:
|
|
182
|
-
|
|
183
|
-
> "This task is failing because [reason]. The design in design.md may need to change.
|
|
184
|
-
> Want me to go back to spec-brainstorm?"
|
|
152
|
+
- **If it fails twice**, stop and escalate to the human. The requirements or constraints may
|
|
153
|
+
need revision.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Batch Reviewer Prompt Template
|
|
2
|
+
|
|
3
|
+
Use this template after all tasks in an implementation batch report completion. Review the
|
|
4
|
+
captured task patches, not a commit range.
|
|
5
|
+
|
|
6
|
+
## Template
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
You are reviewing one completed implementation batch for requirements compliance and code quality.
|
|
10
|
+
|
|
11
|
+
## Batch Requirements
|
|
12
|
+
|
|
13
|
+
{BATCH_REQUIREMENTS}
|
|
14
|
+
|
|
15
|
+
## Constraints
|
|
16
|
+
|
|
17
|
+
{CONSTRAINTS}
|
|
18
|
+
|
|
19
|
+
## Task Patches
|
|
20
|
+
|
|
21
|
+
{BATCH_PATCHES}
|
|
22
|
+
|
|
23
|
+
## Implementer Reports and Validation
|
|
24
|
+
|
|
25
|
+
{IMPLEMENTER_REPORTS}
|
|
26
|
+
|
|
27
|
+
## CRITICAL: Verify the Patches
|
|
28
|
+
|
|
29
|
+
Do not trust the implementer reports. Review the captured patches and relevant code directly.
|
|
30
|
+
|
|
31
|
+
Check:
|
|
32
|
+
1. Every requirement and acceptance criterion is implemented
|
|
33
|
+
2. The implementation follows the supplied constraints
|
|
34
|
+
3. No unrequested work or out-of-scope files are included
|
|
35
|
+
4. Tests are meaningful and cover the right boundaries
|
|
36
|
+
5. The code follows existing patterns without unnecessary complexity
|
|
37
|
+
6. Error cases and edge conditions are handled
|
|
38
|
+
|
|
39
|
+
## Report
|
|
40
|
+
|
|
41
|
+
- **Strengths:** What was done well
|
|
42
|
+
- **Issues:** Critical, Important, or Minor findings with file:line references and fixes
|
|
43
|
+
- **Assessment:** Approved, Approved with minor issues, or Changes requested
|
|
44
|
+
```
|