codebyplan 1.13.12 → 1.13.14
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/dist/cli.js +328 -2
- package/package.json +2 -2
- package/templates/hooks/hooks.json +0 -4
- package/templates/rules/task-routing-recommendation.md +51 -0
- package/templates/settings.project.base.json +8 -0
- package/templates/skills/cbp-round-check/SKILL.md +28 -4
- package/templates/skills/cbp-round-end/SKILL.md +35 -12
- package/templates/skills/cbp-round-execute/SKILL.md +30 -7
- package/templates/skills/cbp-round-input/SKILL.md +31 -10
- package/templates/skills/cbp-round-start/SKILL.md +35 -14
- package/templates/skills/cbp-round-update/SKILL.md +43 -12
- package/templates/skills/cbp-standalone-task-check/SKILL.md +152 -0
- package/templates/skills/cbp-standalone-task-complete/SKILL.md +201 -0
- package/templates/skills/cbp-standalone-task-create/SKILL.md +150 -0
- package/templates/skills/cbp-standalone-task-start/SKILL.md +177 -0
- package/templates/skills/cbp-standalone-task-testing/SKILL.md +210 -0
- package/templates/skills/cbp-task-check/SKILL.md +5 -5
- package/templates/skills/cbp-task-complete/SKILL.md +9 -22
- package/templates/skills/cbp-task-create/SKILL.md +11 -31
- package/templates/skills/cbp-task-start/SKILL.md +6 -13
- package/templates/skills/cbp-task-testing/SKILL.md +5 -5
package/dist/cli.js
CHANGED
|
@@ -14,7 +14,7 @@ var VERSION, PACKAGE_NAME;
|
|
|
14
14
|
var init_version = __esm({
|
|
15
15
|
"src/lib/version.ts"() {
|
|
16
16
|
"use strict";
|
|
17
|
-
VERSION = "1.13.
|
|
17
|
+
VERSION = "1.13.14";
|
|
18
18
|
PACKAGE_NAME = "codebyplan";
|
|
19
19
|
}
|
|
20
20
|
});
|
|
@@ -1281,7 +1281,11 @@ var init_template_walker = __esm({
|
|
|
1281
1281
|
"hooks/validate-structure-lengths.sh",
|
|
1282
1282
|
"hooks/validate-structure-smoke.sh",
|
|
1283
1283
|
"hooks/validate-context-usage.sh",
|
|
1284
|
-
"hooks/validate-git-commit.sh"
|
|
1284
|
+
"hooks/validate-git-commit.sh",
|
|
1285
|
+
// Advisory GATE-6 sibling-identity nudge — fires ONLY in the templates source
|
|
1286
|
+
// repo (detects packages/codebyplan-package/templates/). A no-op for consumers,
|
|
1287
|
+
// so it ships neither in hooks.json nor as a copied file.
|
|
1288
|
+
"hooks/cbp-canonical-templates-nudge.sh"
|
|
1285
1289
|
]);
|
|
1286
1290
|
}
|
|
1287
1291
|
});
|
|
@@ -5897,6 +5901,310 @@ var init_resolve_worktree2 = __esm({
|
|
|
5897
5901
|
}
|
|
5898
5902
|
});
|
|
5899
5903
|
|
|
5904
|
+
// src/cli/create-org.ts
|
|
5905
|
+
var create_org_exports = {};
|
|
5906
|
+
__export(create_org_exports, {
|
|
5907
|
+
runCreateOrg: () => runCreateOrg
|
|
5908
|
+
});
|
|
5909
|
+
import { stdin as stdin3, stdout as stdout4 } from "node:process";
|
|
5910
|
+
import { createInterface as createInterface3 } from "node:readline/promises";
|
|
5911
|
+
function deriveSlug(name) {
|
|
5912
|
+
const trimmed = name.trim();
|
|
5913
|
+
if (trimmed === "") return "";
|
|
5914
|
+
const slug = trimmed.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
5915
|
+
return slug || "org";
|
|
5916
|
+
}
|
|
5917
|
+
async function runCreateOrg() {
|
|
5918
|
+
const rl = createInterface3({ input: stdin3, output: stdout4 });
|
|
5919
|
+
console.log("\n CodeByPlan \u2014 Create Organization\n");
|
|
5920
|
+
try {
|
|
5921
|
+
const rawName = (await rl.question(" Organization name: ")).trim();
|
|
5922
|
+
if (!rawName) {
|
|
5923
|
+
console.error("\n Error: Organization name cannot be empty.\n");
|
|
5924
|
+
process.exitCode = 1;
|
|
5925
|
+
return;
|
|
5926
|
+
}
|
|
5927
|
+
const slug = deriveSlug(rawName);
|
|
5928
|
+
if (slug) {
|
|
5929
|
+
console.log(` Slug preview: ${slug}
|
|
5930
|
+
`);
|
|
5931
|
+
}
|
|
5932
|
+
let response;
|
|
5933
|
+
try {
|
|
5934
|
+
response = await apiPost("/organizations", {
|
|
5935
|
+
name: rawName
|
|
5936
|
+
});
|
|
5937
|
+
} catch (err) {
|
|
5938
|
+
if (err instanceof ApiError) {
|
|
5939
|
+
console.error(`
|
|
5940
|
+
Error: ${err.message} (HTTP ${err.status})
|
|
5941
|
+
`);
|
|
5942
|
+
} else {
|
|
5943
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
5944
|
+
console.error(`
|
|
5945
|
+
Error: ${msg}
|
|
5946
|
+
`);
|
|
5947
|
+
}
|
|
5948
|
+
process.exitCode = 1;
|
|
5949
|
+
return;
|
|
5950
|
+
}
|
|
5951
|
+
const org = response.data;
|
|
5952
|
+
console.log("\n Organization created successfully.\n");
|
|
5953
|
+
console.log(` id: ${org.id}`);
|
|
5954
|
+
console.log(` name: ${org.name}`);
|
|
5955
|
+
console.log(` slug: ${org.slug}
|
|
5956
|
+
`);
|
|
5957
|
+
} finally {
|
|
5958
|
+
rl.close();
|
|
5959
|
+
}
|
|
5960
|
+
}
|
|
5961
|
+
var init_create_org = __esm({
|
|
5962
|
+
"src/cli/create-org.ts"() {
|
|
5963
|
+
"use strict";
|
|
5964
|
+
init_api();
|
|
5965
|
+
}
|
|
5966
|
+
});
|
|
5967
|
+
|
|
5968
|
+
// src/cli/create-project.ts
|
|
5969
|
+
var create_project_exports = {};
|
|
5970
|
+
__export(create_project_exports, {
|
|
5971
|
+
runCreateProject: () => runCreateProject
|
|
5972
|
+
});
|
|
5973
|
+
import { stdin as stdin4, stdout as stdout5 } from "node:process";
|
|
5974
|
+
import { createInterface as createInterface4 } from "node:readline/promises";
|
|
5975
|
+
function deriveSlug2(name) {
|
|
5976
|
+
const trimmed = name.trim();
|
|
5977
|
+
if (trimmed === "") return "";
|
|
5978
|
+
const slug = trimmed.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
5979
|
+
return slug || "project";
|
|
5980
|
+
}
|
|
5981
|
+
async function runCreateProject() {
|
|
5982
|
+
const rl = createInterface4({ input: stdin4, output: stdout5 });
|
|
5983
|
+
console.log("\n CodeByPlan \u2014 Create Project\n");
|
|
5984
|
+
try {
|
|
5985
|
+
const orgIdFlag = (() => {
|
|
5986
|
+
const idx = process.argv.indexOf("--org-id");
|
|
5987
|
+
return idx !== -1 ? process.argv[idx + 1] ?? "" : "";
|
|
5988
|
+
})();
|
|
5989
|
+
let organizationId;
|
|
5990
|
+
if (orgIdFlag) {
|
|
5991
|
+
organizationId = orgIdFlag.trim();
|
|
5992
|
+
} else {
|
|
5993
|
+
let orgs = null;
|
|
5994
|
+
try {
|
|
5995
|
+
const resp = await apiGet("/organizations");
|
|
5996
|
+
if (resp.data && resp.data.length > 0) {
|
|
5997
|
+
orgs = resp.data;
|
|
5998
|
+
}
|
|
5999
|
+
} catch {
|
|
6000
|
+
}
|
|
6001
|
+
if (orgs && orgs.length > 0) {
|
|
6002
|
+
console.log(" Available organizations:\n");
|
|
6003
|
+
orgs.forEach((org, i) => {
|
|
6004
|
+
console.log(` ${i + 1}. ${org.name} (${org.slug}) [${org.id}]`);
|
|
6005
|
+
});
|
|
6006
|
+
console.log("");
|
|
6007
|
+
const rawChoice = (await rl.question(
|
|
6008
|
+
` Select organization (1\u2013${orgs.length}) or paste an org ID: `
|
|
6009
|
+
)).trim();
|
|
6010
|
+
const choiceNum = parseInt(rawChoice, 10);
|
|
6011
|
+
if (!isNaN(choiceNum) && choiceNum >= 1 && choiceNum <= orgs.length) {
|
|
6012
|
+
organizationId = orgs[choiceNum - 1].id;
|
|
6013
|
+
} else if (rawChoice) {
|
|
6014
|
+
organizationId = rawChoice;
|
|
6015
|
+
} else {
|
|
6016
|
+
console.error("\n Error: Organization selection cannot be empty.\n");
|
|
6017
|
+
process.exitCode = 1;
|
|
6018
|
+
return;
|
|
6019
|
+
}
|
|
6020
|
+
} else {
|
|
6021
|
+
const rawOrgId = (await rl.question(" Organization ID: ")).trim();
|
|
6022
|
+
if (!rawOrgId) {
|
|
6023
|
+
console.error("\n Error: Organization ID cannot be empty.\n");
|
|
6024
|
+
process.exitCode = 1;
|
|
6025
|
+
return;
|
|
6026
|
+
}
|
|
6027
|
+
organizationId = rawOrgId;
|
|
6028
|
+
}
|
|
6029
|
+
}
|
|
6030
|
+
const rawName = (await rl.question(" Project name: ")).trim();
|
|
6031
|
+
if (!rawName) {
|
|
6032
|
+
console.error("\n Error: Project name cannot be empty.\n");
|
|
6033
|
+
process.exitCode = 1;
|
|
6034
|
+
return;
|
|
6035
|
+
}
|
|
6036
|
+
const slug = deriveSlug2(rawName);
|
|
6037
|
+
if (slug) {
|
|
6038
|
+
console.log(` Slug preview: ${slug}
|
|
6039
|
+
`);
|
|
6040
|
+
}
|
|
6041
|
+
let response;
|
|
6042
|
+
try {
|
|
6043
|
+
response = await apiPost("/projects", {
|
|
6044
|
+
organization_id: organizationId,
|
|
6045
|
+
name: rawName
|
|
6046
|
+
});
|
|
6047
|
+
} catch (err) {
|
|
6048
|
+
if (err instanceof ApiError) {
|
|
6049
|
+
console.error(`
|
|
6050
|
+
Error: ${err.message} (HTTP ${err.status})
|
|
6051
|
+
`);
|
|
6052
|
+
} else {
|
|
6053
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
6054
|
+
console.error(`
|
|
6055
|
+
Error: ${msg}
|
|
6056
|
+
`);
|
|
6057
|
+
}
|
|
6058
|
+
process.exitCode = 1;
|
|
6059
|
+
return;
|
|
6060
|
+
}
|
|
6061
|
+
const project = response.data;
|
|
6062
|
+
console.log("\n Project created successfully.\n");
|
|
6063
|
+
console.log(` id: ${project.id}`);
|
|
6064
|
+
console.log(` name: ${project.name}`);
|
|
6065
|
+
console.log(` slug: ${project.slug}
|
|
6066
|
+
`);
|
|
6067
|
+
} finally {
|
|
6068
|
+
rl.close();
|
|
6069
|
+
}
|
|
6070
|
+
}
|
|
6071
|
+
var init_create_project = __esm({
|
|
6072
|
+
"src/cli/create-project.ts"() {
|
|
6073
|
+
"use strict";
|
|
6074
|
+
init_api();
|
|
6075
|
+
}
|
|
6076
|
+
});
|
|
6077
|
+
|
|
6078
|
+
// src/cli/create-repo.ts
|
|
6079
|
+
var create_repo_exports = {};
|
|
6080
|
+
__export(create_repo_exports, {
|
|
6081
|
+
runCreateRepo: () => runCreateRepo
|
|
6082
|
+
});
|
|
6083
|
+
import { stdin as stdin5, stdout as stdout6 } from "node:process";
|
|
6084
|
+
import { createInterface as createInterface5 } from "node:readline/promises";
|
|
6085
|
+
async function runCreateRepo() {
|
|
6086
|
+
const rl = createInterface5({ input: stdin5, output: stdout6 });
|
|
6087
|
+
console.log("\n CodeByPlan \u2014 Create Repository\n");
|
|
6088
|
+
try {
|
|
6089
|
+
const projectIdFlag = (() => {
|
|
6090
|
+
const idx = process.argv.indexOf("--project-id");
|
|
6091
|
+
return idx !== -1 ? process.argv[idx + 1] ?? "" : "";
|
|
6092
|
+
})();
|
|
6093
|
+
let projectId;
|
|
6094
|
+
if (projectIdFlag) {
|
|
6095
|
+
const trimmedFlag = projectIdFlag.trim();
|
|
6096
|
+
if (!UUID_RE.test(trimmedFlag)) {
|
|
6097
|
+
console.error("\n Error: Project ID must be a valid UUID.\n");
|
|
6098
|
+
process.exitCode = 1;
|
|
6099
|
+
return;
|
|
6100
|
+
}
|
|
6101
|
+
projectId = trimmedFlag;
|
|
6102
|
+
} else {
|
|
6103
|
+
let projects = null;
|
|
6104
|
+
try {
|
|
6105
|
+
const resp = await apiGet("/projects");
|
|
6106
|
+
if (resp.data && resp.data.length > 0) {
|
|
6107
|
+
projects = resp.data;
|
|
6108
|
+
}
|
|
6109
|
+
} catch {
|
|
6110
|
+
}
|
|
6111
|
+
if (projects && projects.length > 0) {
|
|
6112
|
+
console.log(" Available projects:\n");
|
|
6113
|
+
projects.forEach((proj, i) => {
|
|
6114
|
+
console.log(
|
|
6115
|
+
` ${i + 1}. ${proj.name} (${proj.slug}) [${proj.id}]`
|
|
6116
|
+
);
|
|
6117
|
+
});
|
|
6118
|
+
console.log("");
|
|
6119
|
+
const rawChoice = (await rl.question(
|
|
6120
|
+
` Select project (1\u2013${projects.length}) or paste a project ID: `
|
|
6121
|
+
)).trim();
|
|
6122
|
+
const choiceNum = parseInt(rawChoice, 10);
|
|
6123
|
+
if (!isNaN(choiceNum) && choiceNum >= 1 && choiceNum <= projects.length) {
|
|
6124
|
+
projectId = projects[choiceNum - 1].id;
|
|
6125
|
+
} else if (rawChoice) {
|
|
6126
|
+
if (!UUID_RE.test(rawChoice)) {
|
|
6127
|
+
console.error("\n Error: Project ID must be a valid UUID.\n");
|
|
6128
|
+
process.exitCode = 1;
|
|
6129
|
+
return;
|
|
6130
|
+
}
|
|
6131
|
+
projectId = rawChoice;
|
|
6132
|
+
} else {
|
|
6133
|
+
console.error("\n Error: Project selection cannot be empty.\n");
|
|
6134
|
+
process.exitCode = 1;
|
|
6135
|
+
return;
|
|
6136
|
+
}
|
|
6137
|
+
} else {
|
|
6138
|
+
const rawProjectId = (await rl.question(" Project ID: ")).trim();
|
|
6139
|
+
if (!rawProjectId) {
|
|
6140
|
+
console.error("\n Error: Project ID cannot be empty.\n");
|
|
6141
|
+
process.exitCode = 1;
|
|
6142
|
+
return;
|
|
6143
|
+
}
|
|
6144
|
+
if (!UUID_RE.test(rawProjectId)) {
|
|
6145
|
+
console.error("\n Error: Project ID must be a valid UUID.\n");
|
|
6146
|
+
process.exitCode = 1;
|
|
6147
|
+
return;
|
|
6148
|
+
}
|
|
6149
|
+
projectId = rawProjectId;
|
|
6150
|
+
}
|
|
6151
|
+
}
|
|
6152
|
+
const rawName = (await rl.question(" Repository name: ")).trim();
|
|
6153
|
+
if (!rawName) {
|
|
6154
|
+
console.error("\n Error: Repository name cannot be empty.\n");
|
|
6155
|
+
process.exitCode = 1;
|
|
6156
|
+
return;
|
|
6157
|
+
}
|
|
6158
|
+
const rawPath = (await rl.question(" Local path (optional, press Enter to skip): ")).trim();
|
|
6159
|
+
const rawBranch = (await rl.question(
|
|
6160
|
+
" Default git branch (optional, press Enter for 'main'): "
|
|
6161
|
+
)).trim();
|
|
6162
|
+
const git_branch = rawBranch || "main";
|
|
6163
|
+
let response;
|
|
6164
|
+
try {
|
|
6165
|
+
response = await apiPost("/repos", {
|
|
6166
|
+
project_id: projectId,
|
|
6167
|
+
name: rawName,
|
|
6168
|
+
...rawPath ? { path: rawPath } : {},
|
|
6169
|
+
git_branch
|
|
6170
|
+
});
|
|
6171
|
+
} catch (err) {
|
|
6172
|
+
if (err instanceof ApiError) {
|
|
6173
|
+
console.error(`
|
|
6174
|
+
Error: ${err.message} (HTTP ${err.status})
|
|
6175
|
+
`);
|
|
6176
|
+
} else {
|
|
6177
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
6178
|
+
console.error(`
|
|
6179
|
+
Error: ${msg}
|
|
6180
|
+
`);
|
|
6181
|
+
}
|
|
6182
|
+
process.exitCode = 1;
|
|
6183
|
+
return;
|
|
6184
|
+
}
|
|
6185
|
+
const repo = response.data;
|
|
6186
|
+
console.log("\n Repository created successfully.\n");
|
|
6187
|
+
console.log(` id: ${repo.id}`);
|
|
6188
|
+
console.log(` name: ${repo.name}`);
|
|
6189
|
+
console.log(` git_branch: ${repo.git_branch ?? git_branch}`);
|
|
6190
|
+
console.log(
|
|
6191
|
+
`
|
|
6192
|
+
Tip: run \`codebyplan setup\` from the repo directory to link it.
|
|
6193
|
+
`
|
|
6194
|
+
);
|
|
6195
|
+
} finally {
|
|
6196
|
+
rl.close();
|
|
6197
|
+
}
|
|
6198
|
+
}
|
|
6199
|
+
var UUID_RE;
|
|
6200
|
+
var init_create_repo = __esm({
|
|
6201
|
+
"src/cli/create-repo.ts"() {
|
|
6202
|
+
"use strict";
|
|
6203
|
+
init_api();
|
|
6204
|
+
UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
6205
|
+
}
|
|
6206
|
+
});
|
|
6207
|
+
|
|
5900
6208
|
// src/cli/version-status.ts
|
|
5901
6209
|
var version_status_exports = {};
|
|
5902
6210
|
__export(version_status_exports, {
|
|
@@ -7875,6 +8183,21 @@ void (async () => {
|
|
|
7875
8183
|
await runResolveWorktree2();
|
|
7876
8184
|
process.exit(0);
|
|
7877
8185
|
}
|
|
8186
|
+
if (arg === "create-org") {
|
|
8187
|
+
const { runCreateOrg: runCreateOrg2 } = await Promise.resolve().then(() => (init_create_org(), create_org_exports));
|
|
8188
|
+
await runCreateOrg2();
|
|
8189
|
+
process.exit(0);
|
|
8190
|
+
}
|
|
8191
|
+
if (arg === "create-project") {
|
|
8192
|
+
const { runCreateProject: runCreateProject2 } = await Promise.resolve().then(() => (init_create_project(), create_project_exports));
|
|
8193
|
+
await runCreateProject2();
|
|
8194
|
+
process.exit(0);
|
|
8195
|
+
}
|
|
8196
|
+
if (arg === "create-repo") {
|
|
8197
|
+
const { runCreateRepo: runCreateRepo2 } = await Promise.resolve().then(() => (init_create_repo(), create_repo_exports));
|
|
8198
|
+
await runCreateRepo2();
|
|
8199
|
+
process.exit(0);
|
|
8200
|
+
}
|
|
7878
8201
|
if (arg === "version-status") {
|
|
7879
8202
|
const { runVersionStatus: runVersionStatus2 } = await Promise.resolve().then(() => (init_version_status(), version_status_exports));
|
|
7880
8203
|
await runVersionStatus2();
|
|
@@ -7970,6 +8293,9 @@ void (async () => {
|
|
|
7970
8293
|
codebyplan logout Clear cached OAuth tokens
|
|
7971
8294
|
codebyplan whoami Show currently authenticated identity
|
|
7972
8295
|
codebyplan upgrade-auth Migrate legacy x-api-key MCP config to OAuth
|
|
8296
|
+
codebyplan create-org Create a new organization (interactive prompt)
|
|
8297
|
+
codebyplan create-project Create a new project within an organization (interactive prompt)
|
|
8298
|
+
codebyplan create-repo Create a new repository within a project (interactive prompt)
|
|
7973
8299
|
codebyplan config Sync repo config from DB to .codebyplan/ files
|
|
7974
8300
|
codebyplan ports Verify port allocations against local package.json scripts
|
|
7975
8301
|
codebyplan tech-stack Detect and sync tech stack dependencies
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codebyplan",
|
|
3
|
-
"version": "1.13.
|
|
3
|
+
"version": "1.13.14",
|
|
4
4
|
"description": "CLI for CodeByPlan — AI-powered development planning and tracking",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -61,6 +61,6 @@
|
|
|
61
61
|
"prettier": "^3.8.1",
|
|
62
62
|
"typescript": "^5",
|
|
63
63
|
"typescript-eslint": "^8.20.0",
|
|
64
|
-
"vitest": "^4.
|
|
64
|
+
"vitest": "^4.1.2"
|
|
65
65
|
}
|
|
66
66
|
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: task-routing-recommendation
|
|
3
|
+
scope: repo-only:codebyplan
|
|
4
|
+
description: Routing guide — when to use /cbp-task-* vs /cbp-standalone-task-*
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Task Routing Recommendation
|
|
8
|
+
|
|
9
|
+
## Two-Family Command Surface
|
|
10
|
+
|
|
11
|
+
CodeByPlan has two families of task commands since CHK-141:
|
|
12
|
+
|
|
13
|
+
| Family | Commands | When to use |
|
|
14
|
+
|--------|----------|-------------|
|
|
15
|
+
| Checkpoint-bound | `/cbp-task-create`, `/cbp-task-start {chk}-{task}`, `/cbp-task-check`, `/cbp-task-testing`, `/cbp-task-complete` | Work that belongs to a CHK-NNN checkpoint |
|
|
16
|
+
| Standalone | `/cbp-standalone-task-create`, `/cbp-standalone-task-start {task}`, `/cbp-standalone-task-check`, `/cbp-standalone-task-testing`, `/cbp-standalone-task-complete` | Independent work not tied to any checkpoint |
|
|
17
|
+
|
|
18
|
+
## Round Commands (Both Families)
|
|
19
|
+
|
|
20
|
+
All `/cbp-round-*` commands work for both task families. The correct family is detected from the active task:
|
|
21
|
+
- Checkpoint-bound task in progress → round commands use checkpoint MCP tools
|
|
22
|
+
- Standalone task in progress → round commands use standalone MCP tools
|
|
23
|
+
|
|
24
|
+
## Identifier Format
|
|
25
|
+
|
|
26
|
+
| Context | Correct format | Example |
|
|
27
|
+
|---------|----------------|---------|
|
|
28
|
+
| Checkpoint-bound task | `{chk}-{task}` | `141-3` = CHK-141 TASK-3 |
|
|
29
|
+
| Standalone task | `{task}` (bare number) | `45` = standalone TASK-45 |
|
|
30
|
+
| Round of checkpoint task | `{chk}-{task}-{round}` | `141-3-1` |
|
|
31
|
+
| Round of standalone task | `{task}-{round}` | `45-2` |
|
|
32
|
+
|
|
33
|
+
## Bare-Number Rejection Rule
|
|
34
|
+
|
|
35
|
+
Since CHK-141, `/cbp-task-*` commands reject bare-number arguments. If you type `/cbp-task-start 45`, you will see:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
task-start: bare number `45` is no longer valid here.
|
|
39
|
+
Use /cbp-standalone-task-start 45 instead — bare numbers no longer route to standalone tasks.
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Close-Out Routing
|
|
43
|
+
|
|
44
|
+
After task completion, routes use single-directive form (never A/B/C menus):
|
|
45
|
+
|
|
46
|
+
**Checkpoint-bound task complete:**
|
|
47
|
+
- More tasks in checkpoint → auto-triggers next task (same context)
|
|
48
|
+
- Last task in checkpoint → `Next: /clear, then /cbp-checkpoint-check`
|
|
49
|
+
|
|
50
|
+
**Standalone task complete:**
|
|
51
|
+
- Always → `Next: /cbp-session-end` (or `/cbp-standalone-task-create` for new work)
|
|
@@ -58,6 +58,8 @@
|
|
|
58
58
|
"mcp__codebyplan__create_launch",
|
|
59
59
|
"mcp__codebyplan__update_launch",
|
|
60
60
|
"mcp__codebyplan__delete_launch",
|
|
61
|
+
"mcp__codebyplan__create_organization",
|
|
62
|
+
"mcp__codebyplan__create_project",
|
|
61
63
|
"mcp__codebyplan__create_repo",
|
|
62
64
|
"mcp__codebyplan__delete_session_log",
|
|
63
65
|
"mcp__codebyplan__delete_worktree",
|
|
@@ -67,6 +69,12 @@
|
|
|
67
69
|
"mcp__codebyplan__release_assignment",
|
|
68
70
|
"Bash(codebyplan setup:*)",
|
|
69
71
|
"Bash(npx codebyplan setup:*)",
|
|
72
|
+
"Bash(codebyplan create-org:*)",
|
|
73
|
+
"Bash(npx codebyplan create-org:*)",
|
|
74
|
+
"Bash(codebyplan create-project:*)",
|
|
75
|
+
"Bash(npx codebyplan create-project:*)",
|
|
76
|
+
"Bash(codebyplan create-repo:*)",
|
|
77
|
+
"Bash(npx codebyplan create-repo:*)",
|
|
70
78
|
"Bash(codebyplan login:*)",
|
|
71
79
|
"Bash(npx codebyplan login:*)",
|
|
72
80
|
"Bash(codebyplan logout:*)",
|
|
@@ -7,6 +7,27 @@ effort: low
|
|
|
7
7
|
|
|
8
8
|
<!-- Re-read this file before executing. Do not rely on memory. -->
|
|
9
9
|
|
|
10
|
+
## Kind Detection
|
|
11
|
+
|
|
12
|
+
Inspect the resolved identifier from argument parsing to determine the task kind:
|
|
13
|
+
|
|
14
|
+
| Identifier shape | KIND |
|
|
15
|
+
|-----------------|------|
|
|
16
|
+
| `{task}-{round}` (2-segment, e.g. `45-2`) | `standalone` |
|
|
17
|
+
| `{chk}-{task}-{round}` (3-segment, e.g. `141-3-1`) | `checkpoint` |
|
|
18
|
+
| _(empty / free-text)_ | Check `get_current_standalone_task` first; if found → `standalone`. Else → `checkpoint` via `get_current_task`. |
|
|
19
|
+
|
|
20
|
+
Set `KIND` for the rest of this skill. MCP tool names vary by KIND:
|
|
21
|
+
|
|
22
|
+
| Operation | `checkpoint` KIND | `standalone` KIND |
|
|
23
|
+
|-----------|------------------|-------------------|
|
|
24
|
+
| Get task | `get_current_task(repo_id)` | `get_current_standalone_task(repo_id)` |
|
|
25
|
+
| Get rounds | `get_rounds(task_id)` | `get_standalone_rounds(standalone_task_id)` |
|
|
26
|
+
| Add round | `add_round(task_id, ...)` | `add_standalone_round(standalone_task_id, ...)` |
|
|
27
|
+
| Update round | `update_round(round_id, ...)` | `update_standalone_round(standalone_round_id, ...)` |
|
|
28
|
+
| Complete round | `complete_round(round_id, duration_minutes?)` | `complete_standalone_round(standalone_round_id, duration_minutes?, caller_worktree_id)` ⚠️ `caller_worktree_id` is REQUIRED for standalone |
|
|
29
|
+
| Update task | `update_task(task_id, ...)` | `update_standalone_task(standalone_task_id, ...)` |
|
|
30
|
+
|
|
10
31
|
# Round Check Command
|
|
11
32
|
|
|
12
33
|
Run automated checks independently with mandatory execution. Updates round QA. Hard fails if mandatory checks (build/lint/types) fail.
|
|
@@ -15,7 +36,10 @@ Run automated checks independently with mandatory execution. Updates round QA. H
|
|
|
15
36
|
|
|
16
37
|
### Step 1: Get Current Round
|
|
17
38
|
|
|
18
|
-
Use
|
|
39
|
+
Use Kind Detection above to set KIND. Then:
|
|
40
|
+
|
|
41
|
+
- **checkpoint KIND**: MCP `get_current_task(repo_id)` to find active task, then `get_rounds(task_id)` to find the in-progress round.
|
|
42
|
+
- **standalone KIND**: MCP `get_current_standalone_task(repo_id)` to find active task, then `get_standalone_rounds(standalone_task_id)` to find the in-progress round.
|
|
19
43
|
|
|
20
44
|
### Step 2: Determine Project Root
|
|
21
45
|
|
|
@@ -59,7 +83,7 @@ Scan all captured output for:
|
|
|
59
83
|
|
|
60
84
|
### Step 6: Save QA Results
|
|
61
85
|
|
|
62
|
-
Update round QA via MCP `update_round(round_id, qa: ...)
|
|
86
|
+
Update round QA via MCP `update_round(round_id, qa: ...)` (checkpoint KIND) or `update_standalone_round(standalone_round_id, qa: ...)` (standalone KIND):
|
|
63
87
|
|
|
64
88
|
```json
|
|
65
89
|
{
|
|
@@ -99,6 +123,6 @@ If soft failures only: `Run /cbp-round-start to trigger auto-fix, or fix manuall
|
|
|
99
123
|
|
|
100
124
|
## Integration
|
|
101
125
|
|
|
102
|
-
- **Reads**: MCP `get_current_task`, `get_rounds`
|
|
103
|
-
- **Writes**: MCP `update_round` (qa field)
|
|
126
|
+
- **Reads**: MCP `get_current_task` / `get_current_standalone_task`, `get_rounds` / `get_standalone_rounds` (per KIND)
|
|
127
|
+
- **Writes**: MCP `update_round` / `update_standalone_round` (qa field) — per KIND
|
|
104
128
|
- **Standalone**: Can be run independently at any time
|
|
@@ -5,6 +5,27 @@ description: Summary wrap-up after testing phase completes
|
|
|
5
5
|
effort: high
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
+
## Kind Detection
|
|
9
|
+
|
|
10
|
+
Inspect the resolved identifier from argument parsing to determine the task kind:
|
|
11
|
+
|
|
12
|
+
| Identifier shape | KIND |
|
|
13
|
+
|-----------------|------|
|
|
14
|
+
| `{task}-{round}` (2-segment, e.g. `45-2`) | `standalone` |
|
|
15
|
+
| `{chk}-{task}-{round}` (3-segment, e.g. `141-3-1`) | `checkpoint` |
|
|
16
|
+
| _(empty / free-text)_ | Check `get_current_standalone_task` first; if found → `standalone`. Else → `checkpoint` via `get_current_task`. |
|
|
17
|
+
|
|
18
|
+
Set `KIND` for the rest of this skill. MCP tool names vary by KIND:
|
|
19
|
+
|
|
20
|
+
| Operation | `checkpoint` KIND | `standalone` KIND |
|
|
21
|
+
|-----------|------------------|-------------------|
|
|
22
|
+
| Get task | `get_current_task(repo_id)` | `get_current_standalone_task(repo_id)` |
|
|
23
|
+
| Get rounds | `get_rounds(task_id)` | `get_standalone_rounds(standalone_task_id)` |
|
|
24
|
+
| Add round | `add_round(task_id, ...)` | `add_standalone_round(standalone_task_id, ...)` |
|
|
25
|
+
| Update round | `update_round(round_id, ...)` | `update_standalone_round(standalone_round_id, ...)` |
|
|
26
|
+
| Complete round | `complete_round(round_id, duration_minutes?)` | `complete_standalone_round(standalone_round_id, duration_minutes?, caller_worktree_id)` ⚠️ `caller_worktree_id` is REQUIRED for standalone |
|
|
27
|
+
| Update task | `update_task(task_id, ...)` | `update_standalone_task(standalone_task_id, ...)` |
|
|
28
|
+
|
|
8
29
|
# Round End Command
|
|
9
30
|
|
|
10
31
|
Summary phase — presents what was done, then runs code quality review to catch bugs and logic errors that automated checks miss.
|
|
@@ -21,14 +42,16 @@ See `reference/inline-fallback.md` for full trigger table, procedure, and covera
|
|
|
21
42
|
|
|
22
43
|
## Identifier Notation
|
|
23
44
|
|
|
24
|
-
This skill operates on the **active** task/round resolved via MCP
|
|
45
|
+
This skill operates on the **active** task/round resolved via MCP and does not accept a positional identifier argument. Canonical chk-task-round notation — used in prose, error messages, and cross-references — follows `.claude/rules/notation-consistency.md` "CHK / TASK / ROUND Identifier Notation": `108-1` (CHK-108 TASK-1), `45` (standalone TASK-45), `108-1-2` (round 2 of CHK-108 TASK-1), `45-2` (round 2 of standalone TASK-45).
|
|
25
46
|
|
|
26
47
|
## Instructions
|
|
27
48
|
|
|
28
49
|
### Step 1: Get Current Task and Round
|
|
29
50
|
|
|
30
|
-
Use
|
|
31
|
-
|
|
51
|
+
Use Kind Detection above to set KIND. Then:
|
|
52
|
+
|
|
53
|
+
- **checkpoint KIND**: MCP `get_current_task(repo_id)` (pass `checkpoint_id` if known) to find the active task. MCP `get_rounds(task_id)` to find the in-progress round.
|
|
54
|
+
- **standalone KIND**: MCP `get_current_standalone_task(repo_id)` to find the active task. MCP `get_standalone_rounds(standalone_task_id)` to find the in-progress round.
|
|
32
55
|
|
|
33
56
|
Load round context with all outputs (executor_output, testing_qa_output, reviewer_output).
|
|
34
57
|
|
|
@@ -70,11 +93,11 @@ Merge with previous rounds (supersede items for re-modified files, preserve veri
|
|
|
70
93
|
|
|
71
94
|
### Step 4: Update Task Files and QA
|
|
72
95
|
|
|
73
|
-
Update via MCP:
|
|
96
|
+
Update via MCP using KIND-appropriate tools:
|
|
74
97
|
|
|
75
|
-
- `update_task(task_id, files_changed: [...])` — merge with existing
|
|
76
|
-
- `update_round(round_id, files_changed: [...], qa: {items: [auto_qa items + default_checklist items]})` — round-specific
|
|
77
|
-
- `update_task(task_id, qa: {items: [auto_qa items + default_checklist items]})` — aggregated
|
|
98
|
+
- `update_task(task_id, files_changed: [...])` / `update_standalone_task(standalone_task_id, files_changed: [...])` — merge with existing
|
|
99
|
+
- `update_round(round_id, files_changed: [...], qa: {items: [auto_qa items + default_checklist items]})` / `update_standalone_round(standalone_round_id, ...)` — round-specific
|
|
100
|
+
- `update_task(task_id, qa: {items: [auto_qa items + default_checklist items]})` / `update_standalone_task(standalone_task_id, qa: {items: [auto_qa items + default_checklist items]})` — aggregated
|
|
78
101
|
|
|
79
102
|
### Step 5: Present Summary
|
|
80
103
|
|
|
@@ -137,8 +160,8 @@ Example tables and the `inline` option gating spec: see `reference/findings-pres
|
|
|
137
160
|
- Auto-accept ALL findings into `improve_round_findings[]` regardless of severity (the user opted into the loop).
|
|
138
161
|
- Skip the polish-spiral stop-gate (auto-loop has its own cap-exhausted termination).
|
|
139
162
|
- Skip the user findings-decision prompt.
|
|
140
|
-
- Save findings via `update_round` exactly as in manual mode.
|
|
141
|
-
- Auto-trigger `/cbp-round-update` immediately. round-update Step
|
|
163
|
+
- Save findings via `update_round` / `update_standalone_round` per KIND exactly as in manual mode.
|
|
164
|
+
- Auto-trigger `/cbp-round-update` immediately. round-update Step 4 will decide whether to spawn another round or exit clean (see cbp-round-update SKILL.md Step 4).
|
|
142
165
|
|
|
143
166
|
**Else (manual mode — flag absent or false):**
|
|
144
167
|
|
|
@@ -146,7 +169,7 @@ Run the existing flow:
|
|
|
146
169
|
|
|
147
170
|
1. After round 2+, surface the polish-spiral stop-gate per `polish-spiral-stop-gate.md` (defer-to-followups vs continue).
|
|
148
171
|
2. Surface the findings-decision AskUserQuestion (with optional `inline` per the gating rules in `reference/findings-presentation.md`).
|
|
149
|
-
3. Save accepted/rejected findings to round context via MCP `update_round
|
|
172
|
+
3. Save accepted/rejected findings to round context via MCP `update_round` / `update_standalone_round` per KIND:
|
|
150
173
|
```json
|
|
151
174
|
{
|
|
152
175
|
"context": {
|
|
@@ -167,7 +190,7 @@ Run the existing flow:
|
|
|
167
190
|
## Integration
|
|
168
191
|
|
|
169
192
|
- **Triggered by**: `/cbp-round-execute` (auto, after all waves + testing complete)
|
|
170
|
-
- **Reads**: MCP `get_current_task`, `get_rounds
|
|
171
|
-
- **Writes**: MCP `update_round`, `update_task` (files_changed, qa, findings)
|
|
193
|
+
- **Reads**: MCP `get_current_task` / `get_current_standalone_task`, `get_rounds` / `get_standalone_rounds` (per KIND), round context
|
|
194
|
+
- **Writes**: MCP `update_round` / `update_standalone_round`, `update_task` / `update_standalone_task` (files_changed, qa, findings) — per KIND
|
|
172
195
|
- **Spawns**: `cbp-improve-round` (code quality review)
|
|
173
196
|
- **Triggers**: `/cbp-round-update` (auto, after findings handled)
|