@corners/cli 0.0.4 → 0.0.6
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.d.ts.map +1 -1
- package/dist/cli.js +656 -105
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +11 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/guidance.d.ts.map +1 -1
- package/dist/guidance.js +15 -12
- package/dist/guidance.js.map +1 -1
- package/dist/skills.d.ts +41 -0
- package/dist/skills.d.ts.map +1 -0
- package/dist/skills.js +160 -0
- package/dist/skills.js.map +1 -0
- package/dist/support.d.ts +9 -0
- package/dist/support.d.ts.map +1 -1
- package/dist/support.js +50 -1
- package/dist/support.js.map +1 -1
- package/package.json +3 -2
- package/skills/corners-ask/SKILL.md +223 -0
- package/skills/corners-plan/SKILL.md +253 -0
- package/skills/corners-push/SKILL.md +177 -0
- package/skills/corners-sync/SKILL.md +245 -0
package/dist/skills.js
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill management for Corners CLI.
|
|
3
|
+
* Handles bundled skill discovery, installation, auto-sync, and state resolution.
|
|
4
|
+
*/
|
|
5
|
+
import { createHash } from "node:crypto";
|
|
6
|
+
import { readFile } from "node:fs/promises";
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
import { fileURLToPath } from "node:url";
|
|
9
|
+
import { buildPlannedEdit, readOptionalUtf8, writePlannedEdits, } from "./support.js";
|
|
10
|
+
export const BUNDLED_SKILLS = [
|
|
11
|
+
{ name: "corners-ask", dirName: "corners-ask", fileName: "SKILL.md" },
|
|
12
|
+
{ name: "corners-plan", dirName: "corners-plan", fileName: "SKILL.md" },
|
|
13
|
+
{ name: "corners-push", dirName: "corners-push", fileName: "SKILL.md" },
|
|
14
|
+
{ name: "corners-sync", dirName: "corners-sync", fileName: "SKILL.md" },
|
|
15
|
+
];
|
|
16
|
+
export function getBundledSkillsDir() {
|
|
17
|
+
return fileURLToPath(new URL("../skills", import.meta.url));
|
|
18
|
+
}
|
|
19
|
+
export function getBundledSkillPath(skill) {
|
|
20
|
+
return join(getBundledSkillsDir(), skill.dirName, skill.fileName);
|
|
21
|
+
}
|
|
22
|
+
export function getInstalledSkillPath(rootDir, skill) {
|
|
23
|
+
return join(rootDir, ".claude", "skills", skill.dirName, skill.fileName);
|
|
24
|
+
}
|
|
25
|
+
export function parseSkillFrontmatter(content) {
|
|
26
|
+
const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
27
|
+
if (!match) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
const block = match[1];
|
|
31
|
+
const nameMatch = block.match(/^name:\s*(.+)$/m);
|
|
32
|
+
const versionMatch = block.match(/^version:\s*(.+)$/m);
|
|
33
|
+
if (!nameMatch || !versionMatch) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
let description = "";
|
|
37
|
+
const descBlockMatch = block.match(/^description:\s*\|\s*\r?\n([\s\S]*?)(?=\n[a-z][\w-]*:|\s*$)/m);
|
|
38
|
+
if (descBlockMatch) {
|
|
39
|
+
description = descBlockMatch[1]
|
|
40
|
+
.split(/\r?\n/)
|
|
41
|
+
.map((line) => line.replace(/^ {2}/, "").trim())
|
|
42
|
+
.filter(Boolean)
|
|
43
|
+
.join(" ");
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
const descInlineMatch = block.match(/^description:\s*(.+)$/m);
|
|
47
|
+
if (descInlineMatch) {
|
|
48
|
+
description = descInlineMatch[1].trim();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
name: nameMatch[1].trim(),
|
|
53
|
+
version: versionMatch[1].trim(),
|
|
54
|
+
description,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
export function computeSkillHash(content) {
|
|
58
|
+
return createHash("sha256")
|
|
59
|
+
.update(content, "utf8")
|
|
60
|
+
.digest("hex")
|
|
61
|
+
.slice(0, 16);
|
|
62
|
+
}
|
|
63
|
+
export async function resolveSkillsState(rootDir, config) {
|
|
64
|
+
const skills = [];
|
|
65
|
+
let hasStale = false;
|
|
66
|
+
for (const skill of BUNDLED_SKILLS) {
|
|
67
|
+
const bundledContent = await readFile(getBundledSkillPath(skill), "utf8");
|
|
68
|
+
const bundledFrontmatter = parseSkillFrontmatter(bundledContent);
|
|
69
|
+
const installedPath = getInstalledSkillPath(rootDir, skill);
|
|
70
|
+
const installedContent = await readOptionalUtf8(installedPath);
|
|
71
|
+
if (installedContent === null) {
|
|
72
|
+
hasStale = true;
|
|
73
|
+
skills.push({
|
|
74
|
+
name: skill.name,
|
|
75
|
+
state: "missing",
|
|
76
|
+
installedVersion: null,
|
|
77
|
+
bundledVersion: bundledFrontmatter?.version ?? "unknown",
|
|
78
|
+
installedPath,
|
|
79
|
+
});
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
const bundledHash = computeSkillHash(bundledContent);
|
|
83
|
+
const installedHash = computeSkillHash(installedContent);
|
|
84
|
+
const installedFrontmatter = parseSkillFrontmatter(installedContent);
|
|
85
|
+
if (bundledHash === installedHash) {
|
|
86
|
+
skills.push({
|
|
87
|
+
name: skill.name,
|
|
88
|
+
state: "current",
|
|
89
|
+
installedVersion: installedFrontmatter?.version ?? "unknown",
|
|
90
|
+
bundledVersion: bundledFrontmatter?.version ?? "unknown",
|
|
91
|
+
installedPath,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
hasStale = true;
|
|
96
|
+
skills.push({
|
|
97
|
+
name: skill.name,
|
|
98
|
+
state: "stale",
|
|
99
|
+
installedVersion: installedFrontmatter?.version ?? "unknown",
|
|
100
|
+
bundledVersion: bundledFrontmatter?.version ?? "unknown",
|
|
101
|
+
installedPath,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
stale: hasStale,
|
|
107
|
+
lastSyncedAt: config.skills?.syncedAt ?? null,
|
|
108
|
+
skills,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
export async function buildSkillPlannedEdits(rootDir) {
|
|
112
|
+
const edits = [];
|
|
113
|
+
for (const skill of BUNDLED_SKILLS) {
|
|
114
|
+
const bundledContent = await readFile(getBundledSkillPath(skill), "utf8");
|
|
115
|
+
const installedPath = getInstalledSkillPath(rootDir, skill);
|
|
116
|
+
const edit = await buildPlannedEdit(installedPath, bundledContent);
|
|
117
|
+
if (edit) {
|
|
118
|
+
edits.push(edit);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return edits;
|
|
122
|
+
}
|
|
123
|
+
export async function buildInstalledSkillReferences(syncedAt) {
|
|
124
|
+
const refs = [];
|
|
125
|
+
for (const skill of BUNDLED_SKILLS) {
|
|
126
|
+
const content = await readFile(getBundledSkillPath(skill), "utf8");
|
|
127
|
+
const frontmatter = parseSkillFrontmatter(content);
|
|
128
|
+
refs.push({
|
|
129
|
+
name: skill.name,
|
|
130
|
+
version: frontmatter?.version ?? "unknown",
|
|
131
|
+
contentHash: computeSkillHash(content),
|
|
132
|
+
installedAt: syncedAt,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
return refs;
|
|
136
|
+
}
|
|
137
|
+
export function withUpdatedSkillsConfig(config, installedSkills, syncedAt) {
|
|
138
|
+
return {
|
|
139
|
+
...config,
|
|
140
|
+
skills: {
|
|
141
|
+
installedSkills,
|
|
142
|
+
syncedAt,
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
export async function syncSkillsIfNeeded(rootDir, config, writeConfig) {
|
|
147
|
+
if (!config.skills) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
const edits = await buildSkillPlannedEdits(rootDir);
|
|
151
|
+
if (edits.length === 0) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
await writePlannedEdits(edits);
|
|
155
|
+
const syncedAt = new Date().toISOString();
|
|
156
|
+
const refs = await buildInstalledSkillReferences(syncedAt);
|
|
157
|
+
const nextConfig = withUpdatedSkillsConfig(config, refs, syncedAt);
|
|
158
|
+
await writeConfig(rootDir, nextConfig);
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=skills.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills.js","sourceRoot":"","sources":["../src/skills.ts"],"names":[],"mappings":"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"}
|
package/dist/support.d.ts
CHANGED
|
@@ -15,7 +15,16 @@ export declare function printLine(stream: NodeJS.WritableStream, value: string):
|
|
|
15
15
|
export declare function readTextFromStdin(stdin: NodeJS.ReadableStream): Promise<string | null>;
|
|
16
16
|
export declare function openUrlInBrowser(url: string): Promise<boolean>;
|
|
17
17
|
export declare function toGraphQLWorkstreamUpdateType(value: string): string;
|
|
18
|
+
export declare function toGraphQLWorkstreamStatus(value: string): string;
|
|
18
19
|
export declare function toGraphQLAttachmentKind(value: string): string;
|
|
19
20
|
export declare function toIsoString(value?: Date): string;
|
|
20
21
|
export declare function sleep(ms: number): Promise<void>;
|
|
22
|
+
export type PlannedEdit = {
|
|
23
|
+
path: string;
|
|
24
|
+
action: "create" | "update";
|
|
25
|
+
content: string;
|
|
26
|
+
};
|
|
27
|
+
export declare function readOptionalUtf8(path: string): Promise<string | null>;
|
|
28
|
+
export declare function buildPlannedEdit(path: string, nextContent: string): Promise<PlannedEdit | null>;
|
|
29
|
+
export declare function writePlannedEdits(edits: PlannedEdit[]): Promise<void>;
|
|
21
30
|
//# sourceMappingURL=support.d.ts.map
|
package/dist/support.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"support.d.ts","sourceRoot":"","sources":["../src/support.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"support.d.ts","sourceRoot":"","sources":["../src/support.ts"],"names":[],"mappings":"AAOA,qBAAa,QAAS,SAAQ,KAAK;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;gBAGrB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QACR,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC,EAAE,OAAO,CAAC;KAChB;CAQJ;AAED,wBAAgB,eAAe,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAQ7D;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAW1C;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,cAAc,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAE7E;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,cAAc,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAE5E;AAED,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,MAAM,CAAC,cAAc,GAC3B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAcxB;AAED,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAkBpE;AAED,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAenE;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAgB/D;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAoB7D;AAED,wBAAgB,WAAW,CAAC,KAAK,GAAE,IAAiB,GAAG,MAAM,CAE5D;AAED,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAI/C;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC5B,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAS3E;AAED,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAW7B;AAED,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAK3E"}
|
package/dist/support.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
2
|
import { readFileSync } from "node:fs";
|
|
3
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
4
|
+
import { dirname } from "node:path";
|
|
3
5
|
let cachedVersion = null;
|
|
4
6
|
export class CLIError extends Error {
|
|
5
7
|
exitCode;
|
|
@@ -79,6 +81,21 @@ export function toGraphQLWorkstreamUpdateType(value) {
|
|
|
79
81
|
throw new CLIError(`Invalid update type: ${value}. Expected status, blocker, learning, or outcome.`);
|
|
80
82
|
}
|
|
81
83
|
}
|
|
84
|
+
export function toGraphQLWorkstreamStatus(value) {
|
|
85
|
+
switch (value.trim().toLowerCase()) {
|
|
86
|
+
case "scoping":
|
|
87
|
+
return "SCOPING";
|
|
88
|
+
case "in_progress":
|
|
89
|
+
case "in-progress":
|
|
90
|
+
return "IN_PROGRESS";
|
|
91
|
+
case "blocked":
|
|
92
|
+
return "BLOCKED";
|
|
93
|
+
case "done":
|
|
94
|
+
return "DONE";
|
|
95
|
+
default:
|
|
96
|
+
throw new CLIError(`Invalid workstream status: ${value}. Expected scoping, in_progress, blocked, or done.`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
82
99
|
export function toGraphQLAttachmentKind(value) {
|
|
83
100
|
switch (value.trim().toLowerCase()) {
|
|
84
101
|
case "thread":
|
|
@@ -90,8 +107,12 @@ export function toGraphQLAttachmentKind(value) {
|
|
|
90
107
|
case "calendar-event":
|
|
91
108
|
case "calendar_event":
|
|
92
109
|
return "CALENDAR_EVENT";
|
|
110
|
+
case "todolist":
|
|
111
|
+
case "todo_list":
|
|
112
|
+
case "todo-list":
|
|
113
|
+
return "TODOLIST";
|
|
93
114
|
default:
|
|
94
|
-
throw new CLIError(`Invalid attachment kind: ${value}. Expected thread, document, datatable, or
|
|
115
|
+
throw new CLIError(`Invalid attachment kind: ${value}. Expected thread, document, datatable, calendar_event, or todolist.`);
|
|
95
116
|
}
|
|
96
117
|
}
|
|
97
118
|
export function toIsoString(value = new Date()) {
|
|
@@ -102,4 +123,32 @@ export function sleep(ms) {
|
|
|
102
123
|
setTimeout(resolve, ms);
|
|
103
124
|
});
|
|
104
125
|
}
|
|
126
|
+
export async function readOptionalUtf8(path) {
|
|
127
|
+
try {
|
|
128
|
+
return await readFile(path, "utf8");
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
if (error.code === "ENOENT") {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
throw error;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
export async function buildPlannedEdit(path, nextContent) {
|
|
138
|
+
const existing = await readOptionalUtf8(path);
|
|
139
|
+
if (existing === nextContent) {
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
return {
|
|
143
|
+
path,
|
|
144
|
+
action: existing === null ? "create" : "update",
|
|
145
|
+
content: nextContent,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
export async function writePlannedEdits(edits) {
|
|
149
|
+
for (const edit of edits) {
|
|
150
|
+
await mkdir(dirname(edit.path), { recursive: true });
|
|
151
|
+
await writeFile(edit.path, edit.content, "utf8");
|
|
152
|
+
}
|
|
153
|
+
}
|
|
105
154
|
//# sourceMappingURL=support.js.map
|
package/dist/support.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"support.js","sourceRoot":"","sources":["../src/support.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"support.js","sourceRoot":"","sources":["../src/support.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@corners/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
"corners": "./dist/index.js"
|
|
10
10
|
},
|
|
11
11
|
"files": [
|
|
12
|
-
"dist"
|
|
12
|
+
"dist",
|
|
13
|
+
"skills"
|
|
13
14
|
],
|
|
14
15
|
"publishConfig": {
|
|
15
16
|
"access": "public"
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: corners-ask
|
|
3
|
+
version: 0.1.0
|
|
4
|
+
description: |
|
|
5
|
+
Post a durable question to a workstream for team input.
|
|
6
|
+
Offers structured templates and auto-generates rationale from code context.
|
|
7
|
+
allowed-tools:
|
|
8
|
+
- Bash
|
|
9
|
+
- Read
|
|
10
|
+
- AskUserQuestion
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# /corners-ask — "I need the team's input"
|
|
14
|
+
|
|
15
|
+
Post a well-structured question to your workstream. The question is visible to the
|
|
16
|
+
whole team in corner chat. When they answer, skill continuation can auto-resume
|
|
17
|
+
your work if configured.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Step 0: Preamble
|
|
22
|
+
|
|
23
|
+
Run these commands to check auth and resolve context:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
corners auth status --json 2>/dev/null || echo "CORNERS_CLI_MISSING"
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
corners workstream current --json 2>/dev/null
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
_BRANCH=$(git branch --show-current 2>/dev/null || echo "unknown")
|
|
35
|
+
echo "BRANCH: $_BRANCH"
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
**Error handling — check in this order:**
|
|
39
|
+
|
|
40
|
+
1. If `CORNERS_CLI_MISSING` or `command not found`: tell user to install (`npm install -g @corners/cli`) and **STOP**.
|
|
41
|
+
2. If `loggedIn=false` OR `remoteValid=false`: tell user to run `corners auth login` and **STOP**.
|
|
42
|
+
3. If `resolvedCorner` is null: tell user to run `corners corner use <id>` and **STOP**.
|
|
43
|
+
4. If `connectedWorkstreamIds` is empty: tell user to run `/corners-sync` first and **STOP**.
|
|
44
|
+
|
|
45
|
+
Use the first connected workstream ID for all subsequent steps.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Step 1: Gather Code Context
|
|
50
|
+
|
|
51
|
+
Run:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
git diff --stat 2>/dev/null | head -10
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
git log --oneline -5 2>/dev/null
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Note the current branch, recently modified files, and recent commit messages.
|
|
62
|
+
This context will be used to auto-generate the question's rationale.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Step 2: Choose Question Template
|
|
67
|
+
|
|
68
|
+
Use AskUserQuestion:
|
|
69
|
+
- Re-ground: "Workstream question on branch {branch}."
|
|
70
|
+
- Question: "What kind of question do you need to ask the team?"
|
|
71
|
+
- Options:
|
|
72
|
+
- **A) Architecture decision** — "We need to choose between technical approaches. I'll help you frame the options and tradeoffs."
|
|
73
|
+
- **B) Scope clarification** — "Something might be in or out of scope. I'll help you ask clearly."
|
|
74
|
+
- **C) Blocker escalation** — "You're blocked and need someone to unblock you. I'll help frame the urgency."
|
|
75
|
+
- **D) Freeform** — "Custom question — I'll help you sharpen it."
|
|
76
|
+
|
|
77
|
+
Note the selected template for Step 3.
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Step 3: Formulate the Question
|
|
82
|
+
|
|
83
|
+
Based on the selected template, guide the user through formulation.
|
|
84
|
+
|
|
85
|
+
### Template A: Architecture Decision
|
|
86
|
+
|
|
87
|
+
Use AskUserQuestion:
|
|
88
|
+
- Question: "What's the technical decision you're facing? Describe the options you see."
|
|
89
|
+
- Options: freeform text
|
|
90
|
+
|
|
91
|
+
Then draft the question in this structure:
|
|
92
|
+
```
|
|
93
|
+
We need to decide: {user's decision}
|
|
94
|
+
|
|
95
|
+
Options:
|
|
96
|
+
A) {option 1} — {tradeoff}
|
|
97
|
+
B) {option 2} — {tradeoff}
|
|
98
|
+
C) {option 3 if applicable}
|
|
99
|
+
|
|
100
|
+
Context: Currently working on branch {branch}. Recent changes: {summary from git context}.
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Template B: Scope Clarification
|
|
104
|
+
|
|
105
|
+
Use AskUserQuestion:
|
|
106
|
+
- Question: "What's the scope question? What might be in or out?"
|
|
107
|
+
- Options: freeform text
|
|
108
|
+
|
|
109
|
+
Draft:
|
|
110
|
+
```
|
|
111
|
+
Scope question: {user's question}
|
|
112
|
+
|
|
113
|
+
Current context: Working on {branch}. This came up while {brief context from git}.
|
|
114
|
+
If in scope: {implication}
|
|
115
|
+
If out of scope: {implication}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Template C: Blocker Escalation
|
|
119
|
+
|
|
120
|
+
Use AskUserQuestion:
|
|
121
|
+
- Question: "What are you blocked on? Who or what can unblock you?"
|
|
122
|
+
- Options: freeform text
|
|
123
|
+
|
|
124
|
+
Draft:
|
|
125
|
+
```
|
|
126
|
+
Blocked: {user's blocker description}
|
|
127
|
+
|
|
128
|
+
Impact: {what can't proceed until this is resolved}
|
|
129
|
+
Needed from: {person or team if known}
|
|
130
|
+
Branch: {branch}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Template D: Freeform
|
|
134
|
+
|
|
135
|
+
Use AskUserQuestion:
|
|
136
|
+
- Question: "What do you want to ask the team?"
|
|
137
|
+
- Options: freeform text
|
|
138
|
+
|
|
139
|
+
Use the user's text directly.
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Step 4: Refine and Confirm
|
|
144
|
+
|
|
145
|
+
Present the drafted question to the user via AskUserQuestion:
|
|
146
|
+
- Show the full question text
|
|
147
|
+
- Show the auto-generated rationale (derived from git context: "This question arose while
|
|
148
|
+
working on branch {branch}, which modifies {files}. Recent commits: {summary}.")
|
|
149
|
+
- Show 2-3 suggested answers (derived from the template — for architecture decisions,
|
|
150
|
+
the options become suggested answers; for scope, "In scope" / "Out of scope" / "Defer";
|
|
151
|
+
for blockers, "I can help" / "Escalate to {person}" / "Deprioritize")
|
|
152
|
+
- Options: "Post as-is" / "Edit question" / "Edit rationale" / "Cancel"
|
|
153
|
+
|
|
154
|
+
If the user wants to edit, use AskUserQuestion for the specific field and re-present.
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## Step 5: Post the Question
|
|
159
|
+
|
|
160
|
+
Post via heredoc for shell safety:
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
corners workstream question ask <workstreamId> \
|
|
164
|
+
--question "$(cat <<'CORNERS_MSG'
|
|
165
|
+
<final question text>
|
|
166
|
+
CORNERS_MSG
|
|
167
|
+
)" \
|
|
168
|
+
--rationale "$(cat <<'CORNERS_MSG'
|
|
169
|
+
<final rationale text>
|
|
170
|
+
CORNERS_MSG
|
|
171
|
+
)" \
|
|
172
|
+
--suggested-answer "<answer 1>" \
|
|
173
|
+
--suggested-answer "<answer 2>" \
|
|
174
|
+
--json
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Parse the response to confirm success and extract the question ID.
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## Step 6: Blocker Follow-up (Template C only)
|
|
182
|
+
|
|
183
|
+
If the user selected "Blocker escalation" in Step 2, also push a blocker update:
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
corners workstream push <workstreamId> --type blocker --message "$(cat <<'CORNERS_MSG'
|
|
187
|
+
<brief blocker description from the question>
|
|
188
|
+
CORNERS_MSG
|
|
189
|
+
)" --json
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## Step 7: Confirm
|
|
195
|
+
|
|
196
|
+
Display:
|
|
197
|
+
|
|
198
|
+
```
|
|
199
|
+
Posted question to workstream {name} ({id}):
|
|
200
|
+
"{first 80 chars of question}..."
|
|
201
|
+
Suggested answers: {list}
|
|
202
|
+
{If blocker also posted: "Also posted blocker update."}
|
|
203
|
+
|
|
204
|
+
The team will see this in corner chat.
|
|
205
|
+
When they answer, skill continuation will auto-resume if configured.
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## Manual Equivalent
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
# Post a question
|
|
214
|
+
corners workstream question ask <wsId> \
|
|
215
|
+
--question "What should we do about X?" \
|
|
216
|
+
--rationale "This came up while working on Y" \
|
|
217
|
+
--suggested-answer "Option A" \
|
|
218
|
+
--suggested-answer "Option B" \
|
|
219
|
+
--json
|
|
220
|
+
|
|
221
|
+
# Also post a blocker (if applicable)
|
|
222
|
+
corners workstream push <wsId> --type blocker --message "Blocked on X" --json
|
|
223
|
+
```
|