create-snipara 2.0.8 → 2.0.9
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 +2 -1
- package/dist/index.js +262 -34
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -26,6 +26,7 @@ Use it for:
|
|
|
26
26
|
- free account signup with reviewed Context + Memory
|
|
27
27
|
- local project wiring, `doctor`, `repair`, and `upgrade`
|
|
28
28
|
- local source activation without GitHub, plus optional GitHub repository sync and PR Answer Packs approval when the current folder is a GitHub repo
|
|
29
|
+
- day-zero Project Intelligence proof: a First Work Brief, a ready-to-run `snipara_context_query`, review-only decision archaeology candidates, possible doc-staleness findings, and an estimated context economy report from the user's own repository
|
|
29
30
|
|
|
30
31
|
## Why It Exists
|
|
31
32
|
|
|
@@ -114,7 +115,7 @@ That distinction matters:
|
|
|
114
115
|
- installs optional `snipara-sandbox`
|
|
115
116
|
- installs optional `snipara-orchestrator` for proof gates, drift checks, and htask workflows when requested
|
|
116
117
|
- configures `.mcp.json`
|
|
117
|
-
- generates merge-ready AI agent templates in `.snipara/templates/`, including
|
|
118
|
+
- generates merge-ready AI agent templates in `.snipara/templates/`, including symbol-card, code-impact, and managed workflow guidance within plan capacity
|
|
118
119
|
- creates `AGENTS.md` and `CLAUDE.md` when missing, or appends a marked Snipara section when those files already exist
|
|
119
120
|
- creates `.cursor/rules/snipara.mdc` and `.codex/config.toml` when those files do not already exist
|
|
120
121
|
- validates Codex config against Hosted MCP plus `bearer_token_env_var = "SNIPARA_API_KEY"` and tells users to restart Codex after MCP config changes
|
package/dist/index.js
CHANGED
|
@@ -13,7 +13,7 @@ import { homedir } from "os";
|
|
|
13
13
|
// package.json
|
|
14
14
|
var package_default = {
|
|
15
15
|
name: "create-snipara",
|
|
16
|
-
version: "2.0.
|
|
16
|
+
version: "2.0.9",
|
|
17
17
|
description: "Onboard Snipara Hosted MCP Context + Memory with auth, companion workflows, and optional Snipara Sandbox",
|
|
18
18
|
main: "dist/index.js",
|
|
19
19
|
type: "module",
|
|
@@ -115,6 +115,19 @@ deployment, and production smoke checks behind the scenes. Surface important
|
|
|
115
115
|
decisions, blockers, and evidence, but do not make the user manually orchestrate
|
|
116
116
|
routine Snipara or release mechanics.`;
|
|
117
117
|
var UNIVERSAL_CLIENT_GUIDANCE = "The target experience is outcome-first: the user can ask for engineering judgment or a release, and the agent should use Snipara context, workflow state, verification, package checks, Git, deploy, and smoke checks without making the user orchestrate routine mechanics.";
|
|
118
|
+
var DECISION_COMMIT_TERMS = [
|
|
119
|
+
"adopt",
|
|
120
|
+
"because",
|
|
121
|
+
"decide",
|
|
122
|
+
"decision",
|
|
123
|
+
"drop",
|
|
124
|
+
"migrate",
|
|
125
|
+
"prefer",
|
|
126
|
+
"replace",
|
|
127
|
+
"revert",
|
|
128
|
+
"standardize",
|
|
129
|
+
"switch"
|
|
130
|
+
];
|
|
118
131
|
function buildActivationId() {
|
|
119
132
|
return `act_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
|
|
120
133
|
}
|
|
@@ -200,23 +213,139 @@ function readRecentCommitSubjects() {
|
|
|
200
213
|
return [];
|
|
201
214
|
}
|
|
202
215
|
}
|
|
216
|
+
function readDecisionCommitSubjectLines() {
|
|
217
|
+
try {
|
|
218
|
+
const output = execSync("git log --pretty=format:%h%x20%s --max-count=50", {
|
|
219
|
+
cwd: process.cwd(),
|
|
220
|
+
encoding: "utf-8",
|
|
221
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
222
|
+
timeout: 1500
|
|
223
|
+
}).trim();
|
|
224
|
+
if (!output) {
|
|
225
|
+
return [];
|
|
226
|
+
}
|
|
227
|
+
return output.split(/\r?\n/).map((line) => line.trim()).filter((line) => DECISION_COMMIT_TERMS.some((term) => line.toLowerCase().includes(term))).slice(0, 8);
|
|
228
|
+
} catch {
|
|
229
|
+
return [];
|
|
230
|
+
}
|
|
231
|
+
}
|
|
203
232
|
function readMemoryCandidateLines(relativePath) {
|
|
204
233
|
const absolutePath = path.join(process.cwd(), relativePath);
|
|
205
234
|
if (!fs.existsSync(absolutePath) || fs.statSync(absolutePath).isDirectory()) {
|
|
206
235
|
return [];
|
|
207
236
|
}
|
|
208
237
|
const content = fs.readFileSync(absolutePath, "utf8").slice(0, 24e3);
|
|
209
|
-
return content.split(/\r?\n/).map((line) => line.trim()).filter((line) => /decision|decided|must|should|always|never|convention|rule/i.test(line)).slice(0,
|
|
238
|
+
return content.split(/\r?\n/).map((line) => line.trim()).filter((line) => /decision|decided|must|should|always|never|convention|rule/i.test(line)).slice(0, 4).map((line) => ({
|
|
239
|
+
source: relativePath,
|
|
240
|
+
text: line.slice(0, 280),
|
|
241
|
+
status: "needs_review",
|
|
242
|
+
reason: "Detected project guidance language. Review before storing as durable memory.",
|
|
243
|
+
evidence: classifyDecisionSource(relativePath)
|
|
244
|
+
}));
|
|
245
|
+
}
|
|
246
|
+
function estimateFileTokens(relativePath) {
|
|
247
|
+
const absolutePath = path.join(process.cwd(), relativePath);
|
|
248
|
+
if (!fs.existsSync(absolutePath) || fs.statSync(absolutePath).isDirectory()) {
|
|
249
|
+
return 0;
|
|
250
|
+
}
|
|
251
|
+
try {
|
|
252
|
+
const content = fs.readFileSync(absolutePath, "utf8");
|
|
253
|
+
return Math.ceil(content.length / 4);
|
|
254
|
+
} catch {
|
|
255
|
+
return 0;
|
|
256
|
+
}
|
|
210
257
|
}
|
|
211
258
|
function buildMemoryCandidatePreviews(scan) {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
)
|
|
259
|
+
const seen = /* @__PURE__ */ new Set();
|
|
260
|
+
const gitCandidates = scan.git.recentDecisionCommits.map((line) => ({
|
|
261
|
+
source: "git log",
|
|
262
|
+
text: line.slice(0, 280),
|
|
263
|
+
status: "needs_review",
|
|
264
|
+
reason: "Detected decision-language in recent commit history. Confirm intent before storing.",
|
|
265
|
+
evidence: "git_commit_subject"
|
|
266
|
+
}));
|
|
267
|
+
const candidates = [
|
|
268
|
+
...scan.files.candidateDocs.flatMap(readMemoryCandidateLines),
|
|
269
|
+
...gitCandidates
|
|
270
|
+
];
|
|
271
|
+
return candidates.filter((candidate) => {
|
|
272
|
+
const key = `${candidate.source}:${candidate.text}`;
|
|
273
|
+
if (seen.has(key)) {
|
|
274
|
+
return false;
|
|
275
|
+
}
|
|
276
|
+
seen.add(key);
|
|
277
|
+
return true;
|
|
278
|
+
}).slice(0, 20);
|
|
279
|
+
}
|
|
280
|
+
function readTextFileSnippet(relativePath, maxChars = 24e3) {
|
|
281
|
+
const absolutePath = path.join(process.cwd(), relativePath);
|
|
282
|
+
if (!fs.existsSync(absolutePath) || fs.statSync(absolutePath).isDirectory()) {
|
|
283
|
+
return "";
|
|
284
|
+
}
|
|
285
|
+
try {
|
|
286
|
+
return fs.readFileSync(absolutePath, "utf8").slice(0, maxChars);
|
|
287
|
+
} catch {
|
|
288
|
+
return "";
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
function buildStalenessFindings(scan) {
|
|
292
|
+
const findings = [];
|
|
293
|
+
const scriptSet = new Set(scan.scripts);
|
|
294
|
+
for (const source of scan.files.candidateDocs.slice(0, 30)) {
|
|
295
|
+
const content = readTextFileSnippet(source);
|
|
296
|
+
if (!content) {
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
const scriptMatches = [...content.matchAll(/\b(?:npm|pnpm|yarn|bun)\s+run\s+([a-z0-9:_-]+)/gi)];
|
|
300
|
+
for (const match of scriptMatches) {
|
|
301
|
+
const scriptName = match[1];
|
|
302
|
+
if (scriptName && !scriptSet.has(scriptName)) {
|
|
303
|
+
findings.push({
|
|
304
|
+
source,
|
|
305
|
+
severity: "possible",
|
|
306
|
+
summary: `Documentation references \`${match[0]}\`, but package.json has no \`${scriptName}\` script.`,
|
|
307
|
+
recommendation: "Verify the setup docs or add the missing script before relying on this instruction."
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
if (scan.packageManagers.length === 1 && scan.packageManagers[0] === "pnpm" && /\bnpm install\b/i.test(content)) {
|
|
312
|
+
findings.push({
|
|
313
|
+
source,
|
|
314
|
+
severity: "possible",
|
|
315
|
+
summary: "Documentation mentions `npm install`, but the repo has a pnpm lockfile.",
|
|
316
|
+
recommendation: "Confirm whether npm remains supported or update setup docs to pnpm."
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
return findings.slice(0, 8);
|
|
321
|
+
}
|
|
322
|
+
function buildContextEconomyReport(scan, dayZeroQuery) {
|
|
323
|
+
const indexedSourceTokens = scan.files.candidateDocs.reduce(
|
|
324
|
+
(total, source) => total + estimateFileTokens(source),
|
|
325
|
+
0
|
|
326
|
+
);
|
|
327
|
+
const rawWindowBaselineTokens = Math.max(indexedSourceTokens, 8e3);
|
|
328
|
+
const estimatedPromptTokens = Math.ceil(dayZeroQuery.length / 4);
|
|
329
|
+
const estimatedRetrievedTokens = Math.min(
|
|
330
|
+
rawWindowBaselineTokens,
|
|
331
|
+
Math.max(estimatedPromptTokens + scan.files.candidateDocs.length * 160, 1200)
|
|
332
|
+
);
|
|
333
|
+
const estimatedSavedTokens = Math.max(0, rawWindowBaselineTokens - estimatedRetrievedTokens);
|
|
334
|
+
return {
|
|
335
|
+
basis: "activation_estimate",
|
|
336
|
+
rawWindowBaselineTokens,
|
|
337
|
+
estimatedRetrievedTokens,
|
|
338
|
+
estimatedSavedTokens,
|
|
339
|
+
savingsPercent: rawWindowBaselineTokens > 0 ? Math.round(estimatedSavedTokens / rawWindowBaselineTokens * 100) : 0,
|
|
340
|
+
note: "Estimated from activation sources until hosted query receipts provide measured savings."
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
function buildAgentReadinessReport(scan) {
|
|
344
|
+
const findings = buildStalenessFindings(scan);
|
|
345
|
+
return {
|
|
346
|
+
stalenessFindings: findings,
|
|
347
|
+
summary: findings.length > 0 ? `${findings.length} possible doc staleness finding(s) need review.` : "No obvious setup-doc staleness found in activation sources."
|
|
348
|
+
};
|
|
220
349
|
}
|
|
221
350
|
function writeMemoryCandidates(candidates) {
|
|
222
351
|
fs.mkdirSync(getActivationDir(), { recursive: true });
|
|
@@ -261,15 +390,7 @@ function writeInitialHandoff(answers, manifest) {
|
|
|
261
390
|
function detectLocalActivationScan(detection) {
|
|
262
391
|
const cwd = process.cwd();
|
|
263
392
|
const exists = (relativePath) => fs.existsSync(path.join(cwd, relativePath));
|
|
264
|
-
const candidateDocs =
|
|
265
|
-
"README.md",
|
|
266
|
-
"AGENTS.md",
|
|
267
|
-
"CLAUDE.md",
|
|
268
|
-
"CHANGELOG.md",
|
|
269
|
-
"docs",
|
|
270
|
-
".cursor/rules",
|
|
271
|
-
".github"
|
|
272
|
-
].filter(exists);
|
|
393
|
+
const candidateDocs = findDecisionArchaeologySources(cwd);
|
|
273
394
|
const lockfiles = ["pnpm-lock.yaml", "package-lock.json", "yarn.lock", "bun.lockb"].filter(
|
|
274
395
|
exists
|
|
275
396
|
);
|
|
@@ -305,15 +426,76 @@ function detectLocalActivationScan(detection) {
|
|
|
305
426
|
git: {
|
|
306
427
|
detected: detection.inGitRepo,
|
|
307
428
|
branch: detection.inGitRepo ? detectGitBranch() : null,
|
|
308
|
-
remote: detection.inGitRepo ? readGitRemote() : null
|
|
429
|
+
remote: detection.inGitRepo ? readGitRemote() : null,
|
|
430
|
+
recentDecisionCommits: detection.inGitRepo ? readDecisionCommitSubjectLines() : []
|
|
431
|
+
}
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
function classifyDecisionSource(relativePath) {
|
|
435
|
+
if (/(^|\/)(adr|decisions?)(\/|$)/i.test(relativePath)) {
|
|
436
|
+
return "adr_or_decision_doc";
|
|
437
|
+
}
|
|
438
|
+
if (/AGENTS\.md|CLAUDE\.md|MEMORY\.md|\.cursor\/rules|copilot-instructions/i.test(relativePath)) {
|
|
439
|
+
return "agent_instruction";
|
|
440
|
+
}
|
|
441
|
+
if (/CHANGELOG/i.test(relativePath)) {
|
|
442
|
+
return "changelog";
|
|
443
|
+
}
|
|
444
|
+
return "project_document";
|
|
445
|
+
}
|
|
446
|
+
function listFilesUnder(relativeDir, maxFiles) {
|
|
447
|
+
const root = path.join(process.cwd(), relativeDir);
|
|
448
|
+
if (!fs.existsSync(root) || !fs.statSync(root).isDirectory()) {
|
|
449
|
+
return [];
|
|
450
|
+
}
|
|
451
|
+
const results = [];
|
|
452
|
+
const visit = (dir) => {
|
|
453
|
+
if (results.length >= maxFiles) {
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
for (const entry of fs.readdirSync(dir).sort()) {
|
|
457
|
+
const absolutePath = path.join(dir, entry);
|
|
458
|
+
const stat = fs.statSync(absolutePath);
|
|
459
|
+
if (stat.isDirectory()) {
|
|
460
|
+
visit(absolutePath);
|
|
461
|
+
} else if (/\.(md|mdx|txt|mdc)$/i.test(entry)) {
|
|
462
|
+
results.push(path.relative(process.cwd(), absolutePath));
|
|
463
|
+
}
|
|
464
|
+
if (results.length >= maxFiles) {
|
|
465
|
+
return;
|
|
466
|
+
}
|
|
309
467
|
}
|
|
310
468
|
};
|
|
469
|
+
visit(root);
|
|
470
|
+
return results;
|
|
471
|
+
}
|
|
472
|
+
function findDecisionArchaeologySources(cwd) {
|
|
473
|
+
const exists = (relativePath) => fs.existsSync(path.join(cwd, relativePath));
|
|
474
|
+
const directSources = [
|
|
475
|
+
"README.md",
|
|
476
|
+
"CHANGELOG.md",
|
|
477
|
+
"MEMORY.md",
|
|
478
|
+
...["AGENTS.md", "CLAUDE.md", ".github/copilot-instructions.md"].filter(
|
|
479
|
+
(source) => exists(source)
|
|
480
|
+
)
|
|
481
|
+
].filter(exists);
|
|
482
|
+
const archaeologySources = [
|
|
483
|
+
...listFilesUnder("docs/adr", 20),
|
|
484
|
+
...listFilesUnder("docs/adrs", 20),
|
|
485
|
+
...listFilesUnder("docs/decision", 20),
|
|
486
|
+
...listFilesUnder("docs/decisions", 20),
|
|
487
|
+
...listFilesUnder(".cursor/rules", 20)
|
|
488
|
+
];
|
|
489
|
+
return [.../* @__PURE__ */ new Set([...directSources, ...archaeologySources])].slice(0, 80);
|
|
311
490
|
}
|
|
312
491
|
function createInitialFirstWorkBrief(answers, detection, scan) {
|
|
313
492
|
const githubLine = answers.githubRepo ? `GitHub detected: ${answers.githubRepo.fullName}` : "No GitHub integration required for first value.";
|
|
314
493
|
const commands = scan.scripts.length > 0 ? scan.scripts.join(", ") : "no package scripts detected";
|
|
315
494
|
const docs = scan.files.candidateDocs.length > 0 ? scan.files.candidateDocs.join(", ") : "no standard docs detected";
|
|
316
495
|
const languages = scan.languages.length > 0 ? scan.languages.join(", ") : "not detected yet";
|
|
496
|
+
const hotFiles = scan.files.candidateDocs.slice(0, 5);
|
|
497
|
+
const hotFileLine = hotFiles.length > 0 ? `First files to ground on: ${hotFiles.join(", ")}.` : "First grounding files will appear after local source sync or hosted provider sync.";
|
|
498
|
+
const dayZeroQuery = "What is this project, what is currently in flight, and what should an agent know before making the first edit?";
|
|
317
499
|
return {
|
|
318
500
|
title: `First Work Brief for ${answers.projectSlug}`,
|
|
319
501
|
status: "partial",
|
|
@@ -332,9 +514,17 @@ function createInitialFirstWorkBrief(answers, detection, scan) {
|
|
|
332
514
|
lines: [
|
|
333
515
|
`Initial docs: ${docs}.`,
|
|
334
516
|
`Package scripts: ${commands}.`,
|
|
517
|
+
hotFileLine,
|
|
335
518
|
"Source indexing runs before claiming architecture certainty."
|
|
336
519
|
]
|
|
337
520
|
},
|
|
521
|
+
{
|
|
522
|
+
title: "Day-zero answer pack",
|
|
523
|
+
lines: [
|
|
524
|
+
`Ask Snipara: "${dayZeroQuery}"`,
|
|
525
|
+
"Goal: reach one correct, non-obvious statement about this repository in under 5 minutes."
|
|
526
|
+
]
|
|
527
|
+
},
|
|
338
528
|
{
|
|
339
529
|
title: "Current risks",
|
|
340
530
|
lines: [
|
|
@@ -349,22 +539,35 @@ function createInitialFirstWorkBrief(answers, detection, scan) {
|
|
|
349
539
|
{
|
|
350
540
|
title: "Top impacted modules",
|
|
351
541
|
lines: [
|
|
352
|
-
"Code Graph is
|
|
353
|
-
"
|
|
542
|
+
"Code Graph is available on Free within capacity caps; first answers improve as symbols index.",
|
|
543
|
+
"For the first PR, run snipara_code_impact or companion code impact before editing."
|
|
354
544
|
]
|
|
355
545
|
}
|
|
356
546
|
]
|
|
357
547
|
};
|
|
358
548
|
}
|
|
359
|
-
function createActivationManifest(answers, detection, mode = "default") {
|
|
549
|
+
function createActivationManifest(answers, detection, mode = "default", scan) {
|
|
360
550
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
361
551
|
const hasHostedConfig = answers.profile !== "runtime-only";
|
|
362
552
|
const hasCompanion = answers.installCompanion;
|
|
363
|
-
const localScan = detectLocalActivationScan(detection);
|
|
553
|
+
const localScan = scan ?? detectLocalActivationScan(detection);
|
|
554
|
+
const dayZeroQuery = "What is this project, what is currently in flight, and what should an agent know before making the first edit?";
|
|
364
555
|
return {
|
|
365
556
|
version: "create-snipara-activation-v1",
|
|
366
557
|
activationId: buildActivationId(),
|
|
367
558
|
mode,
|
|
559
|
+
activationMetric: {
|
|
560
|
+
name: "time_to_how_did_it_know_that",
|
|
561
|
+
targetMinutes: 5,
|
|
562
|
+
proof: "A correct, non-obvious statement about this repository from the first answer pack."
|
|
563
|
+
},
|
|
564
|
+
dayZeroQuery: {
|
|
565
|
+
tool: "snipara_context_query",
|
|
566
|
+
query: dayZeroQuery,
|
|
567
|
+
expectedOutcome: "First own-repo answer pack before the user reads product docs."
|
|
568
|
+
},
|
|
569
|
+
agentReadiness: buildAgentReadinessReport(localScan),
|
|
570
|
+
contextEconomy: buildContextEconomyReport(localScan, dayZeroQuery),
|
|
368
571
|
projectSlug: answers.projectSlug,
|
|
369
572
|
projectId: answers.projectId || null,
|
|
370
573
|
repoPath: process.cwd(),
|
|
@@ -395,7 +598,7 @@ function createActivationManifest(answers, detection, mode = "default") {
|
|
|
395
598
|
),
|
|
396
599
|
codeGraph: createActivationLane(
|
|
397
600
|
hasCompanion ? "queued" : "skipped",
|
|
398
|
-
hasCompanion ? "Code Graph indexing starts from local source overlay." : "Code Graph
|
|
601
|
+
hasCompanion ? "Free Code Graph indexing starts from local source overlay within capacity caps." : "Free Code Graph is available after companion or hosted provider sync."
|
|
399
602
|
),
|
|
400
603
|
memoryCandidates: createActivationLane(
|
|
401
604
|
hasCompanion ? "needs_review" : "skipped",
|
|
@@ -407,7 +610,7 @@ function createActivationManifest(answers, detection, mode = "default") {
|
|
|
407
610
|
),
|
|
408
611
|
firstBrief: createActivationLane(
|
|
409
612
|
"ready",
|
|
410
|
-
"First Work Brief
|
|
613
|
+
"First Work Brief and day-zero answer-pack prompt generated from local setup signals."
|
|
411
614
|
),
|
|
412
615
|
githubSync: createActivationLane(
|
|
413
616
|
answers.configureGitHub && answers.githubRepo ? "queued" : "skipped",
|
|
@@ -776,6 +979,8 @@ function parseInitOptionsFromArgv(args) {
|
|
|
776
979
|
async function runInit(options) {
|
|
777
980
|
const normalizedOptions = normalizeInitOptions(options);
|
|
778
981
|
const answers = await gatherConfiguration(normalizedOptions);
|
|
982
|
+
const activationDetection = detectEnvironment();
|
|
983
|
+
const activationScan = detectLocalActivationScan(activationDetection);
|
|
779
984
|
if (answers.installMcp || answers.installRuntime || answers.installOrchestrator) {
|
|
780
985
|
await installPythonPackages(answers, false);
|
|
781
986
|
}
|
|
@@ -802,8 +1007,9 @@ async function runInit(options) {
|
|
|
802
1007
|
writeDoctorReport(validationReport);
|
|
803
1008
|
const activationManifest = createActivationManifest(
|
|
804
1009
|
answers,
|
|
805
|
-
|
|
806
|
-
normalizedOptions.starter ? "starter" : "default"
|
|
1010
|
+
activationDetection,
|
|
1011
|
+
normalizedOptions.starter ? "starter" : "default",
|
|
1012
|
+
activationScan
|
|
807
1013
|
);
|
|
808
1014
|
runLocalSourceActivation(answers, activationManifest);
|
|
809
1015
|
createActivationArtifacts(answers, activationManifest);
|
|
@@ -2201,8 +2407,8 @@ Agent task lifecycle:
|
|
|
2201
2407
|
work.
|
|
2202
2408
|
6. Use whichever structural code graph tools are exposed in the current session
|
|
2203
2409
|
for callers, imports, neighbors, and path questions. Tool exposure can vary.
|
|
2204
|
-
7.
|
|
2205
|
-
|
|
2410
|
+
7. Use \`snipara_code_symbol_card\` for agent-ready symbol context within plan
|
|
2411
|
+
capacity and \`snipara-companion code impact\` before risky multi-file changes, PR
|
|
2206
2412
|
reviews, routes, services, jobs, auth, billing, deployment, schema, migrations,
|
|
2207
2413
|
or explicit "what is missing" assessments.
|
|
2208
2414
|
8. Use \`snipara_plan\` for complex or multi-surface work in any plan when
|
|
@@ -2269,7 +2475,7 @@ ${EXPERIENCE_GOAL_SECTION}
|
|
|
2269
2475
|
- Use \`snipara_code_callers\`, \`snipara_code_imports\`, \`snipara_code_neighbors\`, or \`snipara_code_shortest_path\` for canonical structural code questions.
|
|
2270
2476
|
- For code impact and structural code questions, use \`snipara-companion code callers/imports/neighbors/shortest-path/impact\` first when \`snipara-companion\` is installed; it auto-selects hosted MCP for clean indexed code or the local overlay for dirty/ahead worktrees and reports \`sourceSelection\`. Use hosted \`snipara_code_impact\` only when companion is unavailable or after push/reindex for canonical graph impact.
|
|
2271
2477
|
- Run \`snipara-companion code impact\` before risky multi-file changes, PR reviews, routes, services, jobs, auth, billing, deployment, schema, migrations, or explicit "what is missing" assessments.
|
|
2272
|
-
-
|
|
2478
|
+
- Use \`snipara_code_symbol_card\` before editing important symbols within plan capacity.
|
|
2273
2479
|
- Check every \`snipara_code_*\` response for indexed commit SHA, indexing time, included files, coverage, and freshness warnings.
|
|
2274
2480
|
- Use local file reads, \`rg\`, \`git status --short\`, and tests for exact edits/current working tree; use Snipara for architecture and indexed code graph context.
|
|
2275
2481
|
- If a broad query is slow, retry once with a narrow keyword query before falling back to local search.
|
|
@@ -2309,7 +2515,7 @@ ${EXPERIENCE_GOAL_SECTION}
|
|
|
2309
2515
|
- Use \`snipara_code_callers\`, \`snipara_code_imports\`, \`snipara_code_neighbors\`, or \`snipara_code_shortest_path\` for canonical structural code questions.
|
|
2310
2516
|
- For code impact and structural code questions, use \`snipara-companion code callers/imports/neighbors/shortest-path/impact\` first when \`snipara-companion\` is installed; it auto-selects hosted MCP for clean indexed code or the local overlay for dirty/ahead worktrees and reports \`sourceSelection\`. Use hosted \`snipara_code_impact\` only when companion is unavailable or after push/reindex for canonical graph impact.
|
|
2311
2517
|
- Run \`snipara-companion code impact\` before risky multi-file changes, PR reviews, routes, services, jobs, auth, billing, deployment, schema, migrations, or explicit "what is missing" assessments.
|
|
2312
|
-
-
|
|
2518
|
+
- Use \`snipara_code_symbol_card\` before editing important symbols within plan capacity.
|
|
2313
2519
|
- Check every \`snipara_code_*\` response for indexed commit SHA, indexing time, included files, coverage, and freshness warnings.
|
|
2314
2520
|
- Use \`snipara_plan\` for complex or multi-surface work when available. Keep simple Q&A on targeted \`snipara_context_query\`; for FULL-mode audits, comparisons, roadmap/implementation planning, release readiness, or package-surface reviews, use \`snipara_decompose\` to preserve axes and \`snipara_multi_query\` for independent follow-up questions when Pro+ tools are exposed.
|
|
2315
2521
|
- Use local file reads, \`rg\`, \`git status --short\`, and tests for exact code edits and current working-tree state.
|
|
@@ -3121,7 +3327,7 @@ function getCompanionCommands(answers) {
|
|
|
3121
3327
|
{
|
|
3122
3328
|
title: "Analyze code impact before a risky change",
|
|
3123
3329
|
command: `${COMPANION_NPX_COMMAND} code impact --changed-files src/api/webhooks.ts tests/webhooks.test.ts --diff-summary "webhook retry hardening"`,
|
|
3124
|
-
purpose: "Use
|
|
3330
|
+
purpose: "Use code impact analysis within plan capacity to surface likely tests, docs, routes, config, and risks."
|
|
3125
3331
|
},
|
|
3126
3332
|
{
|
|
3127
3333
|
title: answers.installOrchestrator ? "Run an explicit production orchestration gate" : "Enable explicit production orchestration",
|
|
@@ -3292,7 +3498,7 @@ ${guidance.map((line) => `- ${line}`).join("\n")}
|
|
|
3292
3498
|
- Use \`answer_pack\` facts, caveats, source maps, and verification checks before making claims.
|
|
3293
3499
|
- For coding tasks, choose a workflow mode before editing: LITE for small single-phase changes, FULL managed workflow for multi-file, risky, release/deploy, architectural, compaction-prone, or future-maintainer-sensitive work.
|
|
3294
3500
|
- Use \`snipara_plan\` for complex or multi-surface work when exposed. Keep simple Q&A on targeted \`snipara_context_query\`; for FULL-mode audits, comparisons, roadmap/implementation planning, release readiness, or package-surface reviews, use \`snipara_decompose\` to preserve axes and \`snipara_multi_query\` for independent follow-up questions when Pro+ tools are exposed.
|
|
3295
|
-
- Use \`snipara_code_symbol_card\` for important symbols. For risky multi-file changes, PR reviews, routes, services, jobs, auth, billing, deployment, schema, migrations, or explicit "what is missing" assessments, use \`snipara-companion code impact\` first when companion is available; use hosted \`snipara_code_impact\` only when companion is unavailable or after push/reindex for canonical graph impact.
|
|
3501
|
+
- Use \`snipara_code_symbol_card\` for important symbols within plan capacity. For risky multi-file changes, PR reviews, routes, services, jobs, auth, billing, deployment, schema, migrations, or explicit "what is missing" assessments, use \`snipara-companion code impact\` first when companion is available; use hosted \`snipara_code_impact\` only when companion is unavailable or after push/reindex for canonical graph impact.
|
|
3296
3502
|
- Use the installed \`snipara-companion\` binary for low-latency hooks; use \`${COMPANION_NPX_COMMAND}\` for one-off terminal commands when freshness matters.
|
|
3297
3503
|
- If a broad query is slow, retry once with a narrow keyword query before falling back to local search.
|
|
3298
3504
|
- Use a JSON machine plan plus \`snipara-companion workflow start\`, \`phase-start\`, \`phase-commit\`, \`workflow resume\`, and \`final-commit\` for multi-phase work. After \`workflow resume\`, rerun \`workflow phase-start <phase_id>\` before editing again.
|
|
@@ -4117,6 +4323,28 @@ function printActivationSummary(manifest) {
|
|
|
4117
4323
|
console.log(chalk.dim(` - ${line}`));
|
|
4118
4324
|
}
|
|
4119
4325
|
}
|
|
4326
|
+
console.log(chalk.bold("\nDay-zero proof:\n"));
|
|
4327
|
+
console.log(` Tool: ${manifest.dayZeroQuery.tool}`);
|
|
4328
|
+
console.log(` Query: ${manifest.dayZeroQuery.query}`);
|
|
4329
|
+
console.log(
|
|
4330
|
+
chalk.dim(
|
|
4331
|
+
` Target: ${manifest.activationMetric.targetMinutes} minutes to a true, non-obvious own-repo answer.`
|
|
4332
|
+
)
|
|
4333
|
+
);
|
|
4334
|
+
console.log(chalk.bold("\nAgent readiness:\n"));
|
|
4335
|
+
console.log(` ${manifest.agentReadiness.summary}`);
|
|
4336
|
+
for (const finding of manifest.agentReadiness.stalenessFindings.slice(0, 3)) {
|
|
4337
|
+
console.log(chalk.dim(` - ${finding.source}: ${finding.summary}`));
|
|
4338
|
+
}
|
|
4339
|
+
console.log(chalk.bold("\nContext economy:\n"));
|
|
4340
|
+
console.log(
|
|
4341
|
+
` Estimated ${manifest.contextEconomy.estimatedRetrievedTokens.toLocaleString("en-US")} tokens retrieved instead of ${manifest.contextEconomy.rawWindowBaselineTokens.toLocaleString("en-US")} raw-window tokens.`
|
|
4342
|
+
);
|
|
4343
|
+
console.log(
|
|
4344
|
+
chalk.dim(
|
|
4345
|
+
` Saved about ${manifest.contextEconomy.estimatedSavedTokens.toLocaleString("en-US")} tokens (${manifest.contextEconomy.savingsPercent}%). ${manifest.contextEconomy.note}`
|
|
4346
|
+
)
|
|
4347
|
+
);
|
|
4120
4348
|
console.log(
|
|
4121
4349
|
chalk.dim(
|
|
4122
4350
|
`
|
package/package.json
CHANGED