@clue-ai/cli 0.0.6 → 0.0.7
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/README.md +8 -11
- package/bin/clue-cli.mjs +114 -21
- package/commands/claude-code/clue-init.md +6 -5
- package/commands/codex/clue-init.md +6 -5
- package/package.json +1 -1
- package/src/ai-provider.mjs +3 -2
- package/src/command-spec.mjs +2 -0
- package/src/contracts.mjs +5 -4
- package/src/init-tool.mjs +5 -6
- package/src/public-schema.cjs +47 -0
- package/src/semantic-agent-runner.mjs +157 -0
- package/src/semantic-ai-config.mjs +17 -0
- package/src/semantic-ci.mjs +419 -57
- package/src/setup-check.mjs +28 -2
- package/src/setup-prepare.mjs +106 -11
- package/src/setup-tool.mjs +159 -11
package/src/setup-check.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { access, readFile } from "node:fs/promises";
|
|
2
2
|
import { join, relative, resolve } from "node:path";
|
|
3
|
+
import { validateSemanticCiRequest } from "./contracts.mjs";
|
|
3
4
|
import {
|
|
4
5
|
findLifecycleCallApiNames,
|
|
5
6
|
findLifecycleGuardViolations,
|
|
@@ -14,7 +15,7 @@ const disallowedWorkflowMetadataPattern =
|
|
|
14
15
|
const SETUP_SKILLS = [
|
|
15
16
|
"clue-setup-orchestrator",
|
|
16
17
|
"clue-route-semantic-snapshot",
|
|
17
|
-
"clue-semantic-
|
|
18
|
+
"clue-semantic-gen",
|
|
18
19
|
"clue-sdk-instrumentation",
|
|
19
20
|
"clue-setup-audit",
|
|
20
21
|
"clue-local-verification",
|
|
@@ -31,6 +32,24 @@ const REQUIRED_LIFECYCLE_APIS = [
|
|
|
31
32
|
"ClueSetAccount",
|
|
32
33
|
"ClueLogout",
|
|
33
34
|
];
|
|
35
|
+
|
|
36
|
+
const semanticRequestFromWorkflow = (workflow) => {
|
|
37
|
+
const match = workflow.match(
|
|
38
|
+
/CLUE_SEMANTIC_REQUEST_JSON: \|\n([\s\S]*?)\n\s*run: \|/,
|
|
39
|
+
);
|
|
40
|
+
if (!match) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
const requestJson = match[1]
|
|
44
|
+
.split("\n")
|
|
45
|
+
.map((line) => line.replace(/^ {12}/, ""))
|
|
46
|
+
.join("\n");
|
|
47
|
+
try {
|
|
48
|
+
return validateSemanticCiRequest(JSON.parse(requestJson));
|
|
49
|
+
} catch {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
};
|
|
34
53
|
const BACKEND_SDK_MARKERS = [
|
|
35
54
|
"clue-fastapi-sdk",
|
|
36
55
|
"clue-django-sdk",
|
|
@@ -300,18 +319,25 @@ export const runSetupCheck = async ({
|
|
|
300
319
|
const absoluteWorkflowPath = join(resolvedRepoRoot, workflowPath);
|
|
301
320
|
if (await exists(absoluteWorkflowPath)) {
|
|
302
321
|
const workflow = await readFile(absoluteWorkflowPath, "utf8");
|
|
322
|
+
const semanticRequest = semanticRequestFromWorkflow(workflow);
|
|
303
323
|
addCheck(
|
|
304
324
|
checks,
|
|
305
325
|
"semantic_workflow",
|
|
306
326
|
workflow.includes(
|
|
307
|
-
"npx @clue-ai/cli semantic-
|
|
327
|
+
"npx @clue-ai/cli semantic-gen --request-env CLUE_SEMANTIC_REQUEST_JSON --repo .",
|
|
308
328
|
) &&
|
|
329
|
+
semanticRequest !== null &&
|
|
309
330
|
workflow.includes("CLUE_SEMANTIC_REQUEST_JSON: |") &&
|
|
310
331
|
workflow.includes("CLUE_API_KEY: ${{ secrets.CLUE_API_KEY }}") &&
|
|
311
332
|
workflow.includes(
|
|
312
333
|
"CLUE_AI_PROVIDER_API_KEY: ${{ secrets.CLUE_AI_PROVIDER_API_KEY }}",
|
|
313
334
|
) &&
|
|
314
335
|
workflow.includes("CLUE_AI_PROVIDER: ${{ vars.CLUE_AI_PROVIDER }}") &&
|
|
336
|
+
workflow.includes("CLUE_AI_MODEL: ${{ vars.CLUE_AI_MODEL }}") &&
|
|
337
|
+
!workflow.includes('"ai_provider": "${{ vars.CLUE_AI_PROVIDER }}"') &&
|
|
338
|
+
!workflow.includes('"ai_provider_base_url"') &&
|
|
339
|
+
!workflow.includes('"ai_model": "${{ vars.CLUE_AI_MODEL }}"') &&
|
|
340
|
+
!workflow.includes('"root_path"') &&
|
|
315
341
|
workflow.includes("permissions:\n contents: read") &&
|
|
316
342
|
workflow.includes("persist-credentials: false") &&
|
|
317
343
|
!disallowedWorkflowMetadataPattern.test(workflow),
|
package/src/setup-prepare.mjs
CHANGED
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
import { runSetupDetect } from "./setup-detect.mjs";
|
|
8
8
|
|
|
9
9
|
const DEFAULT_SETUP_MANIFEST_PATH = ".clue/setup-manifest.json";
|
|
10
|
+
const DEFAULT_ENV_GUIDE_PATH = ".env.clue";
|
|
10
11
|
const BROWSER_INGEST_PATH = "/api/v1/ingest/browser";
|
|
11
12
|
const BACKEND_INGEST_PATH = "/api/v1/ingest/backend";
|
|
12
13
|
|
|
@@ -16,6 +17,12 @@ const writeJson = async ({ repoRoot, path, value }) => {
|
|
|
16
17
|
await writeFile(absolutePath, `${JSON.stringify(value, null, 2)}\n`, "utf8");
|
|
17
18
|
};
|
|
18
19
|
|
|
20
|
+
const writeText = async ({ repoRoot, path, value }) => {
|
|
21
|
+
const absolutePath = join(resolve(repoRoot), path);
|
|
22
|
+
await mkdir(dirname(absolutePath), { recursive: true });
|
|
23
|
+
await writeFile(absolutePath, value, "utf8");
|
|
24
|
+
};
|
|
25
|
+
|
|
19
26
|
const firstCandidateOrBlocker = (detection) => {
|
|
20
27
|
if (!detection.detected || detection.candidates.length === 0) {
|
|
21
28
|
return {
|
|
@@ -135,6 +142,7 @@ const buildEnvironmentInstructions = ({ manifest, setupContext }) => {
|
|
|
135
142
|
const watchTargets = manifest.lifecycle_verification.watch_targets;
|
|
136
143
|
return {
|
|
137
144
|
status: "ready",
|
|
145
|
+
env_file_path: DEFAULT_ENV_GUIDE_PATH,
|
|
138
146
|
message: "各サービスの env ファイルに以下を設定してください。",
|
|
139
147
|
service_env_blocks: watchTargets.map((target) => ({
|
|
140
148
|
kind: target.kind,
|
|
@@ -160,6 +168,71 @@ const buildEnvironmentInstructions = ({ manifest, setupContext }) => {
|
|
|
160
168
|
};
|
|
161
169
|
};
|
|
162
170
|
|
|
171
|
+
const buildEnvironmentGuideText = (instructions) => {
|
|
172
|
+
if (!instructions || instructions.status !== "ready") return null;
|
|
173
|
+
const lines = [
|
|
174
|
+
"# Clue setup environment values",
|
|
175
|
+
"# This file contains setup secrets. Do not commit it.",
|
|
176
|
+
"",
|
|
177
|
+
instructions.message,
|
|
178
|
+
"",
|
|
179
|
+
];
|
|
180
|
+
for (const block of instructions.service_env_blocks) {
|
|
181
|
+
lines.push(
|
|
182
|
+
`[${block.kind}] ${block.root_path} (${block.env_file_candidates.join(" or ")})`,
|
|
183
|
+
block.env_block,
|
|
184
|
+
"",
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
lines.push(
|
|
188
|
+
"GitHub Secrets",
|
|
189
|
+
...instructions.ci_github.secrets.map(
|
|
190
|
+
(entry) => `${entry.name}=${entry.value}`,
|
|
191
|
+
),
|
|
192
|
+
"",
|
|
193
|
+
);
|
|
194
|
+
if (instructions.ci_github.variables.length > 0) {
|
|
195
|
+
lines.push(
|
|
196
|
+
"GitHub Variables",
|
|
197
|
+
...instructions.ci_github.variables.map(
|
|
198
|
+
(entry) => `${entry.name}=${entry.value}`,
|
|
199
|
+
),
|
|
200
|
+
"",
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
return `${lines.join("\n")}\n`;
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
const summarizeEnvironmentInstructions = (instructions) => {
|
|
207
|
+
if (!instructions || instructions.status !== "ready") {
|
|
208
|
+
return instructions;
|
|
209
|
+
}
|
|
210
|
+
return {
|
|
211
|
+
status: "ready",
|
|
212
|
+
env_file_path: instructions.env_file_path,
|
|
213
|
+
message:
|
|
214
|
+
`${instructions.env_file_path} を開き、各サービスの env と GitHub Secrets に反映してください。`,
|
|
215
|
+
service_env_block_count: instructions.service_env_blocks.length,
|
|
216
|
+
github_secret_names: instructions.ci_github.secrets.map(
|
|
217
|
+
(entry) => entry.name,
|
|
218
|
+
),
|
|
219
|
+
github_variable_names: instructions.ci_github.variables.map(
|
|
220
|
+
(entry) => entry.name,
|
|
221
|
+
),
|
|
222
|
+
};
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
const writeEnvironmentGuideIfReady = async ({ repoRoot, instructions }) => {
|
|
226
|
+
const content = buildEnvironmentGuideText(instructions);
|
|
227
|
+
if (!content) return null;
|
|
228
|
+
await writeText({
|
|
229
|
+
repoRoot,
|
|
230
|
+
path: instructions.env_file_path,
|
|
231
|
+
value: content,
|
|
232
|
+
});
|
|
233
|
+
return instructions.env_file_path;
|
|
234
|
+
};
|
|
235
|
+
|
|
163
236
|
export const runSetupPrepare = async ({
|
|
164
237
|
repoRoot,
|
|
165
238
|
target,
|
|
@@ -189,12 +262,14 @@ export const runSetupPrepare = async ({
|
|
|
189
262
|
path: setupManifestPath,
|
|
190
263
|
value: manifest,
|
|
191
264
|
});
|
|
265
|
+
const environmentInstructions = buildEnvironmentInstructions({
|
|
266
|
+
manifest,
|
|
267
|
+
setupContext,
|
|
268
|
+
});
|
|
192
269
|
return {
|
|
193
270
|
...manifest,
|
|
194
|
-
environment_instructions:
|
|
195
|
-
|
|
196
|
-
setupContext,
|
|
197
|
-
}),
|
|
271
|
+
environment_instructions:
|
|
272
|
+
summarizeEnvironmentInstructions(environmentInstructions),
|
|
198
273
|
};
|
|
199
274
|
}
|
|
200
275
|
|
|
@@ -267,23 +342,43 @@ export const runSetupPrepare = async ({
|
|
|
267
342
|
"CLUE_API_KEY",
|
|
268
343
|
"CLUE_AI_PROVIDER",
|
|
269
344
|
"CLUE_AI_PROVIDER_API_KEY",
|
|
345
|
+
"CLUE_AI_MODEL",
|
|
270
346
|
"CLUE_PROJECT_KEY",
|
|
271
347
|
"CLUE_ENVIRONMENT",
|
|
272
348
|
"CLUE_INGEST_ENDPOINT",
|
|
273
349
|
"CLUE_API_BASE_URL",
|
|
274
|
-
"CLUE_AI_MODEL",
|
|
275
350
|
],
|
|
276
351
|
};
|
|
352
|
+
const environmentInstructions = buildEnvironmentInstructions({
|
|
353
|
+
manifest,
|
|
354
|
+
setupContext,
|
|
355
|
+
});
|
|
356
|
+
const manifestWithEnvironmentArtifact = {
|
|
357
|
+
...manifest,
|
|
358
|
+
artifacts: {
|
|
359
|
+
...manifest.artifacts,
|
|
360
|
+
environment_file_path:
|
|
361
|
+
environmentInstructions.status === "ready"
|
|
362
|
+
? environmentInstructions.env_file_path
|
|
363
|
+
: null,
|
|
364
|
+
},
|
|
365
|
+
};
|
|
277
366
|
await writeJson({
|
|
278
367
|
repoRoot: resolvedRepoRoot,
|
|
279
368
|
path: setupManifestPath,
|
|
280
|
-
value:
|
|
369
|
+
value: manifestWithEnvironmentArtifact,
|
|
370
|
+
});
|
|
371
|
+
const environmentFilePath = await writeEnvironmentGuideIfReady({
|
|
372
|
+
repoRoot: resolvedRepoRoot,
|
|
373
|
+
instructions: environmentInstructions,
|
|
281
374
|
});
|
|
282
375
|
return {
|
|
283
|
-
...
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
}
|
|
376
|
+
...manifestWithEnvironmentArtifact,
|
|
377
|
+
artifacts: {
|
|
378
|
+
...manifestWithEnvironmentArtifact.artifacts,
|
|
379
|
+
environment_file_path: environmentFilePath,
|
|
380
|
+
},
|
|
381
|
+
environment_instructions:
|
|
382
|
+
summarizeEnvironmentInstructions(environmentInstructions),
|
|
288
383
|
};
|
|
289
384
|
};
|
package/src/setup-tool.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import readline from "node:readline/promises";
|
|
|
5
5
|
const SKILL_NAMES = [
|
|
6
6
|
"clue-setup-orchestrator",
|
|
7
7
|
"clue-route-semantic-snapshot",
|
|
8
|
-
"clue-semantic-
|
|
8
|
+
"clue-semantic-gen",
|
|
9
9
|
"clue-sdk-instrumentation",
|
|
10
10
|
"clue-setup-audit",
|
|
11
11
|
"clue-local-verification",
|
|
@@ -36,7 +36,7 @@ const skillBody = (name) => {
|
|
|
36
36
|
"Use first when running the full Clue setup so one execution agent per implementation workstream and multiple monitoring agents coordinate separate setup phases.",
|
|
37
37
|
"clue-route-semantic-snapshot":
|
|
38
38
|
"Use when checking backend route coverage and semantic snapshot readiness without hand-authoring generated snapshot files.",
|
|
39
|
-
"clue-semantic-
|
|
39
|
+
"clue-semantic-gen":
|
|
40
40
|
"Use when adding or updating Clue semantic snapshot CI for this repository.",
|
|
41
41
|
"clue-sdk-instrumentation":
|
|
42
42
|
"Use when adding ClueInit, ClueIdentify, ClueSetAccount, and ClueLogout lifecycle calls to a customer repository.",
|
|
@@ -48,6 +48,137 @@ const skillBody = (name) => {
|
|
|
48
48
|
"Use when producing the final Clue setup report with changed files, blockers, env names, and next steps.",
|
|
49
49
|
};
|
|
50
50
|
|
|
51
|
+
const agentRoles = {
|
|
52
|
+
"clue-setup-orchestrator":
|
|
53
|
+
"Coordinator agent. Owns sequencing, agent assignment, gates, and blocker handling. It must not edit product code directly.",
|
|
54
|
+
"clue-route-semantic-snapshot":
|
|
55
|
+
"Semantic route readiness agent. Owns backend route inventory/readiness validation only. It must not author generated snapshot content or SDK code.",
|
|
56
|
+
"clue-semantic-gen":
|
|
57
|
+
"Semantic generation CI agent. Owns machine-owned CI workflow verification/refresh only. It must not hand-write snapshot content or SDK lifecycle code.",
|
|
58
|
+
"clue-sdk-instrumentation":
|
|
59
|
+
"SDK lifecycle implementation agent. Owns Clue SDK dependency, initialization, and lifecycle call implementation only.",
|
|
60
|
+
"clue-setup-audit":
|
|
61
|
+
"Read-only monitoring agent. Owns P0/P1 review for one completed workstream at a time. It must not edit files.",
|
|
62
|
+
"clue-local-verification":
|
|
63
|
+
"Read-only verification agent. Owns setup-check/setup-watch evidence and local verification readiness. It must not edit files.",
|
|
64
|
+
"clue-setup-report":
|
|
65
|
+
"Final reporting agent. Owns concise completion evidence only after execution and monitoring gates pass.",
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const owns = {
|
|
69
|
+
"clue-setup-orchestrator": [
|
|
70
|
+
"read `.clue/setup-manifest.json` first",
|
|
71
|
+
"assign exactly one execution agent per implementation workstream",
|
|
72
|
+
"assign multiple read-only monitoring agents",
|
|
73
|
+
"stop on manifest blockers or P0/P1 findings",
|
|
74
|
+
],
|
|
75
|
+
"clue-route-semantic-snapshot": [
|
|
76
|
+
"backend route discovery readiness",
|
|
77
|
+
"route coverage gaps and unsupported-framework blockers",
|
|
78
|
+
"privacy-safe evidence needed by semantic generation",
|
|
79
|
+
],
|
|
80
|
+
"clue-semantic-gen": [
|
|
81
|
+
"`.github/workflows/clue-semantic-snapshot.yml` generated workflow shape",
|
|
82
|
+
"`semantic-gen` command wiring",
|
|
83
|
+
"GitHub secrets/variables referenced by name only",
|
|
84
|
+
"privacy boundary between customer repo CI and Clue API",
|
|
85
|
+
],
|
|
86
|
+
"clue-sdk-instrumentation": [
|
|
87
|
+
"real Clue SDK imports/dependencies",
|
|
88
|
+
"ClueInit bootstrap placement",
|
|
89
|
+
"ClueIdentify login-success coverage",
|
|
90
|
+
"ClueSetAccount account/workspace/tenant coverage",
|
|
91
|
+
"ClueLogout logout/session-reset coverage",
|
|
92
|
+
"failure isolation so host behavior never depends on Clue success",
|
|
93
|
+
],
|
|
94
|
+
"clue-setup-audit": [
|
|
95
|
+
"line-by-line diff review",
|
|
96
|
+
"responsibility boundary checks",
|
|
97
|
+
"P0/P1 findings before the next workstream continues",
|
|
98
|
+
],
|
|
99
|
+
"clue-local-verification": [
|
|
100
|
+
"`setup-check` evidence",
|
|
101
|
+
"`setup-watch --local` readiness",
|
|
102
|
+
"local URL confirmation without assuming ports",
|
|
103
|
+
],
|
|
104
|
+
"clue-setup-report": [
|
|
105
|
+
"changed files",
|
|
106
|
+
"commands run",
|
|
107
|
+
"skills and agents used",
|
|
108
|
+
"remaining blockers and required env names",
|
|
109
|
+
],
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
const mustNot = {
|
|
113
|
+
"clue-setup-orchestrator": [
|
|
114
|
+
"do product-code implementation itself",
|
|
115
|
+
"merge workstreams into one broad task",
|
|
116
|
+
"continue after a blocker without reporting it",
|
|
117
|
+
],
|
|
118
|
+
"clue-route-semantic-snapshot": [
|
|
119
|
+
"create SDK lifecycle calls",
|
|
120
|
+
"create or edit the CI workflow",
|
|
121
|
+
"hand-author generated semantic snapshot content",
|
|
122
|
+
],
|
|
123
|
+
"clue-semantic-gen": [
|
|
124
|
+
"inspect `.env` or secret files",
|
|
125
|
+
"send raw source files, prompts, completions, or secret values to Clue",
|
|
126
|
+
"hand-edit generated snapshot content",
|
|
127
|
+
],
|
|
128
|
+
"clue-sdk-instrumentation": [
|
|
129
|
+
"create no-op wrappers or placeholder lifecycle functions",
|
|
130
|
+
"place ClueInit on repeated UI/request paths",
|
|
131
|
+
"block login/logout/account/request flows on Clue success",
|
|
132
|
+
"guess service keys or ports",
|
|
133
|
+
],
|
|
134
|
+
"clue-setup-audit": [
|
|
135
|
+
"make edits",
|
|
136
|
+
"approve unclear lifecycle points",
|
|
137
|
+
"approve secret values in code, diff, or report",
|
|
138
|
+
],
|
|
139
|
+
"clue-local-verification": [
|
|
140
|
+
"make edits",
|
|
141
|
+
"assume localhost ports",
|
|
142
|
+
"treat setup-watch as complete before every expected implemented lifecycle check passes or is reported blocked",
|
|
143
|
+
],
|
|
144
|
+
"clue-setup-report": [
|
|
145
|
+
"claim complete with unverified workstreams",
|
|
146
|
+
"include secret values",
|
|
147
|
+
"hide blockers or skipped checks",
|
|
148
|
+
],
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
const outputs = {
|
|
152
|
+
"clue-setup-orchestrator": [
|
|
153
|
+
"agent plan with execution agents, monitoring agents, file ownership, and gate order",
|
|
154
|
+
"blocker list if setup cannot proceed",
|
|
155
|
+
],
|
|
156
|
+
"clue-route-semantic-snapshot": [
|
|
157
|
+
"route readiness result: ready or blocked",
|
|
158
|
+
"route coverage evidence and blocker details",
|
|
159
|
+
],
|
|
160
|
+
"clue-semantic-gen": [
|
|
161
|
+
"CI workflow verification result",
|
|
162
|
+
"whether regeneration was required and which command was used",
|
|
163
|
+
],
|
|
164
|
+
"clue-sdk-instrumentation": [
|
|
165
|
+
"implemented lifecycle locations",
|
|
166
|
+
"dependency/import changes",
|
|
167
|
+
"tests or verification commands",
|
|
168
|
+
],
|
|
169
|
+
"clue-setup-audit": [
|
|
170
|
+
"P0/P1 findings with file references",
|
|
171
|
+
"approval or blocked status for the reviewed workstream",
|
|
172
|
+
],
|
|
173
|
+
"clue-local-verification": [
|
|
174
|
+
"setup-check/setup-watch command evidence",
|
|
175
|
+
"passed, blocked, or cannot-run status with reasons",
|
|
176
|
+
],
|
|
177
|
+
"clue-setup-report": [
|
|
178
|
+
"final report with changed files, commands, skills, agents, verification, blockers, and env names",
|
|
179
|
+
],
|
|
180
|
+
};
|
|
181
|
+
|
|
51
182
|
const steps = {
|
|
52
183
|
"clue-setup-orchestrator": [
|
|
53
184
|
"Use one execution agent per implementation workstream.",
|
|
@@ -55,7 +186,7 @@ const skillBody = (name) => {
|
|
|
55
186
|
"Required execution agents: SDK Lifecycle Execution Agent, Semantic Snapshot Readiness Execution Agent, and Semantic Snapshot CI Execution Agent.",
|
|
56
187
|
"Run execution agents in parallel only when file ownership does not conflict; otherwise run them sequentially with monitor gates between workstreams.",
|
|
57
188
|
"Use multiple monitoring agents for read-only checks, or named review passes if subagents are unavailable.",
|
|
58
|
-
"The initial `clue-ai setup --clue-api-key <key> --clue-api-base-url <url> --project-key <key> --environment <environment>` command already performs repository discovery, semantic CI workflow generation, setup manifest generation, and service-specific environment guidance when backend routes can be detected.",
|
|
189
|
+
"The initial `clue-ai setup --clue-api-key <key> --clue-api-base-url <url> --project-key <key> --environment <environment>` command already performs repository discovery, semantic CI workflow generation, setup manifest generation, and writes service-specific environment guidance to `.env.clue` when backend routes can be detected.",
|
|
59
190
|
"Before implementation, read `.clue/setup-manifest.json` and treat it as the mechanical setup source of truth.",
|
|
60
191
|
"Use the service keys and watch targets from `.clue/setup-manifest.json`; do not invent service keys.",
|
|
61
192
|
"If `.clue/setup-manifest.json` has status `blocked`, stop and report its blockers instead of guessing.",
|
|
@@ -72,7 +203,7 @@ const skillBody = (name) => {
|
|
|
72
203
|
"Do not create or commit `.clue/semantic-request.runtime.json`; the semantic CI request must be passed through the generated workflow environment instead of a repository file.",
|
|
73
204
|
"Keep route coverage/readiness checks separate from CI workflow creation and SDK lifecycle implementation.",
|
|
74
205
|
"Do not create CI workflow files or SDK lifecycle calls from this skill.",
|
|
75
|
-
"Do not create or commit `.clue/semantic-routes.json`; route inventory is dynamic and must be recomputed mechanically by `clue-ai semantic-inventory`, `clue-ai setup-check`, or `clue-ai semantic-
|
|
206
|
+
"Do not create or commit `.clue/semantic-routes.json`; route inventory is dynamic and must be recomputed mechanically by `clue-ai semantic-inventory`, `clue-ai setup-check`, or `clue-ai semantic-gen`.",
|
|
76
207
|
"If route inventory must be inspected locally, run `npx @clue-ai/cli semantic-inventory --framework <framework> --backend-root-path <path> --repo .` and review stdout instead of writing a repo file.",
|
|
77
208
|
"Inspect only allowed source paths.",
|
|
78
209
|
"Identify the backend framework, backend root path, route files, controllers, handlers, and route declaration patterns from privacy-safe evidence.",
|
|
@@ -87,21 +218,22 @@ const skillBody = (name) => {
|
|
|
87
218
|
"The expected generated snapshot structure preserves unresolved_operation_effects with missing_context instead of fabricating unknown operation effects.",
|
|
88
219
|
"Report route coverage gaps, unsupported backend frameworks, and unclear backend roots as blockers instead of guessing.",
|
|
89
220
|
],
|
|
90
|
-
"clue-semantic-
|
|
221
|
+
"clue-semantic-gen": [
|
|
91
222
|
"Use this skill as the source of truth for semantic snapshot CI workflow format.",
|
|
92
223
|
"Keep CI workflow creation separate from route coverage/readiness checks and SDK lifecycle implementation.",
|
|
93
224
|
"Do not author semantic snapshot content, runtime request files, or SDK lifecycle calls from this skill.",
|
|
94
225
|
"Treat `.github/workflows/clue-semantic-snapshot.yml` as a machine-owned artifact generated by `clue-ai setup`; do not hand-edit it.",
|
|
95
226
|
"Create or update `.github/workflows/clue-semantic-snapshot.yml` only by running `npx @clue-ai/cli semantic-workflow --framework <framework> --backend-root-path <path> --repo .` when it must be refreshed.",
|
|
96
227
|
"If `npx` cannot be used in the current environment, use the local `clue-ai semantic-workflow` command equivalent instead of hand-writing the workflow.",
|
|
97
|
-
"The workflow must pass `CLUE_SEMANTIC_REQUEST_JSON` through the workflow environment and then call `npx @clue-ai/cli semantic-
|
|
228
|
+
"The workflow must pass `CLUE_SEMANTIC_REQUEST_JSON` through the workflow environment and then call `npx @clue-ai/cli semantic-gen --request-env CLUE_SEMANTIC_REQUEST_JSON --repo .`.",
|
|
98
229
|
"Do not create, commit, or stage `.clue/semantic-request.runtime.json` in the customer repository.",
|
|
99
230
|
"The workflow must not send GitHub actor, triggering_actor, sender, repository owner, repository name, or default branch to Clue.",
|
|
100
|
-
"The workflow should send only repository id, commit sha, workflow run id, project key variable, service key, framework, source path allowlist, source path denylist, Clue API base URL variable
|
|
231
|
+
"The workflow should send only repository id, commit sha, workflow run id, project key variable, service key, framework, source path allowlist, source path denylist, and Clue API base URL variable.",
|
|
101
232
|
"Use minimal GitHub permissions and checkout without persisted credentials when generating the workflow.",
|
|
102
233
|
"Reference GitHub Secrets and Variables by name only.",
|
|
103
234
|
"Required GitHub secrets are `CLUE_API_KEY` and `CLUE_AI_PROVIDER_API_KEY`.",
|
|
104
235
|
"Required GitHub variables are `CLUE_AI_PROVIDER` and `CLUE_AI_MODEL`.",
|
|
236
|
+
"Semantic generation runs inside the customer repository CI with the customer AI provider key; do not send raw source code, prompts, or completions to Clue.",
|
|
105
237
|
"Do not print or commit secret values.",
|
|
106
238
|
],
|
|
107
239
|
"clue-sdk-instrumentation": [
|
|
@@ -117,7 +249,7 @@ const skillBody = (name) => {
|
|
|
117
249
|
"If `npx` cannot be used in the current environment, use the local `clue-ai lifecycle-apply` command equivalent instead of manually applying the exact replacements.",
|
|
118
250
|
"Delete the temporary lifecycle plan file after applying it unless the user explicitly asks to keep it for review.",
|
|
119
251
|
"Use environment variable names for Clue configuration values; do not paste project keys or API keys into code.",
|
|
120
|
-
"For local env files, use the service-specific env blocks
|
|
252
|
+
"For local env files, use the service-specific env blocks written to `.env.clue` by `clue-ai setup`; do not ask the user to guess `CLUE_SERVICE_KEY`.",
|
|
121
253
|
"For browser code, use `CLUE_PROJECT_KEY`, `CLUE_ENVIRONMENT`, and `CLUE_INGEST_ENDPOINT`. Let the target framework expose or inject those values safely without hard-coding a Next.js-only prefix.",
|
|
122
254
|
"For FastAPI code, add `clue-fastapi-sdk` to the backend dependency file when missing, import `clue_init_fastapi` plus `ClueIdentify`, `ClueSetAccount`, and `ClueLogout` where needed, and use `CLUE_PROJECT_KEY`, `CLUE_ENVIRONMENT`, `CLUE_API_KEY`, and `CLUE_INGEST_ENDPOINT`.",
|
|
123
255
|
"Use `CLUE_SERVICE_KEY` as the canonical local service identifier. Do not ask the user to manage a separate producer id; SDKs should send producer id as the service key for setup verification compatibility.",
|
|
@@ -157,11 +289,11 @@ const skillBody = (name) => {
|
|
|
157
289
|
"Confirm generated skill files exist.",
|
|
158
290
|
"Confirm workflow files and SDK lifecycle imports/calls exist when those phases have run.",
|
|
159
291
|
"Confirm backend routes have a backend Clue SDK dependency/import/init when a backend exists.",
|
|
160
|
-
"Confirm `.github/workflows/clue-semantic-snapshot.yml` calls `npx @clue-ai/cli semantic-
|
|
292
|
+
"Confirm `.github/workflows/clue-semantic-snapshot.yml` calls `npx @clue-ai/cli semantic-gen --request-env CLUE_SEMANTIC_REQUEST_JSON`.",
|
|
161
293
|
"Confirm the semantic workflow does not send GitHub actor, triggering_actor, sender, repository owner, repository name, or default branch to Clue.",
|
|
162
294
|
"Confirm `.clue/semantic-request.runtime.json` is not created, committed, or staged.",
|
|
163
295
|
"Run `npx @clue-ai/cli setup-check --framework <framework> --backend-root-path <path> --repo . --target <codex|claude_code> --require-sdk-lifecycle` when possible.",
|
|
164
|
-
"For interactive local verification, run `npx @clue-ai/cli setup-watch --
|
|
296
|
+
"For interactive local verification, run `npx @clue-ai/cli setup-watch --local` and operate every local frontend/backend service until all expected checks pass.",
|
|
165
297
|
"Only include lifecycle checks that the implementation ownership plan expects for that service. If a service emits an undeclared lifecycle event, treat it as a possible duplicate instrumentation issue.",
|
|
166
298
|
"Never assume localhost ports. Ask the repository scripts, env examples, or the running service output for the actual frontend/backend URLs.",
|
|
167
299
|
"If `npx` cannot be used in the current environment, use the local `clue-ai setup-check` command equivalent.",
|
|
@@ -187,7 +319,23 @@ const skillBody = (name) => {
|
|
|
187
319
|
`description: ${descriptions[name]}`,
|
|
188
320
|
"---",
|
|
189
321
|
"",
|
|
190
|
-
"#
|
|
322
|
+
"# Agent Role",
|
|
323
|
+
"",
|
|
324
|
+
agentRoles[name],
|
|
325
|
+
"",
|
|
326
|
+
"# Owns",
|
|
327
|
+
"",
|
|
328
|
+
...owns[name].map((item) => `- ${item}`),
|
|
329
|
+
"",
|
|
330
|
+
"# Must Not",
|
|
331
|
+
"",
|
|
332
|
+
...mustNot[name].map((item) => `- ${item}`),
|
|
333
|
+
"",
|
|
334
|
+
"# Output Contract",
|
|
335
|
+
"",
|
|
336
|
+
...outputs[name].map((item) => `- ${item}`),
|
|
337
|
+
"",
|
|
338
|
+
"# Shared Rules",
|
|
191
339
|
"",
|
|
192
340
|
"- For full Clue setup, use one execution agent per implementation workstream and multiple monitoring agents for read-only checks.",
|
|
193
341
|
"- The full setup must start with `clue-setup-orchestrator`.",
|