create-snipara 2.0.10 → 2.0.12
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 +3 -0
- package/dist/index.js +243 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -14,6 +14,9 @@ npx create-snipara
|
|
|
14
14
|
creates or reuses auth, writes Hosted MCP config, and prepares the local project
|
|
15
15
|
so an LLM client can use Snipara context and reviewed memory. The default path is
|
|
16
16
|
hosted-only so the first success is a grounded answer, not a local tooling tour.
|
|
17
|
+
It is also the canonical activation engine behind editor setup docs: VS Code can
|
|
18
|
+
surface activation as a native command, Cursor can pair OpenVSX UI with Hosted
|
|
19
|
+
MCP, but both paths should land on the same project context.
|
|
17
20
|
|
|
18
21
|
Use it when the goal is outcome-first agent work: the user asks for judgment,
|
|
19
22
|
implementation, release, or verification, and the agent handles Snipara context,
|
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.12",
|
|
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",
|
|
@@ -107,6 +107,8 @@ var DEVICE_CLIENT_ID = "create-snipara";
|
|
|
107
107
|
var DAY_ZERO_CORPUS_MAX_FILES = 8;
|
|
108
108
|
var DAY_ZERO_CORPUS_MAX_FILE_CHARS = 12e3;
|
|
109
109
|
var DAY_ZERO_CORPUS_MAX_TOTAL_CHARS = 5e4;
|
|
110
|
+
var ACTIVATION_MANIFEST_SCHEMA_VERSION = "snipara.activation.manifest.v1";
|
|
111
|
+
var ACTIVATION_CONSUMER_CONTRACT_VERSION = "snipara.editor.activation.v1";
|
|
110
112
|
var EXPERIENCE_GOAL_SECTION = `## Experience Goal
|
|
111
113
|
|
|
112
114
|
The target experience is outcome-first agent work across supported clients:
|
|
@@ -140,15 +142,23 @@ function getActivationDir() {
|
|
|
140
142
|
function getActivationManifestPath() {
|
|
141
143
|
return path.join(getActivationDir(), "manifest.json");
|
|
142
144
|
}
|
|
145
|
+
function getStableActivationManifestPath() {
|
|
146
|
+
return path.join(getActivationDir(), "activation-manifest.json");
|
|
147
|
+
}
|
|
143
148
|
function getActivationHandoffPath() {
|
|
144
149
|
return path.join(getActivationDir(), "handoff.md");
|
|
145
150
|
}
|
|
151
|
+
function getFirstWorkBriefPath() {
|
|
152
|
+
return path.join(getActivationDir(), "first-brief.md");
|
|
153
|
+
}
|
|
146
154
|
function getMemoryCandidatesPath() {
|
|
147
155
|
return path.join(getActivationDir(), "memory-candidates.json");
|
|
148
156
|
}
|
|
149
157
|
function writeActivationManifest(manifest) {
|
|
150
158
|
fs.mkdirSync(getActivationDir(), { recursive: true });
|
|
151
|
-
|
|
159
|
+
const payload = JSON.stringify(manifest, null, 2) + "\n";
|
|
160
|
+
fs.writeFileSync(getActivationManifestPath(), payload, "utf8");
|
|
161
|
+
fs.writeFileSync(getStableActivationManifestPath(), payload, "utf8");
|
|
152
162
|
}
|
|
153
163
|
function updateActivationManifest(manifest) {
|
|
154
164
|
manifest.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -427,6 +437,9 @@ function writeInitialHandoff(answers, manifest) {
|
|
|
427
437
|
`Repo path: ${manifest.repoPath}`,
|
|
428
438
|
`Git branch: ${manifest.git.branch ?? "not detected"}`,
|
|
429
439
|
`Git remote: ${manifest.git.remote ?? "not detected"}`,
|
|
440
|
+
`Activation doctrine: ${manifest.surfaceContract.doctrine}`,
|
|
441
|
+
`Activation engine: ${manifest.surfaceContract.engine}`,
|
|
442
|
+
`Entry point: ${manifest.surfaceContract.entryPoint}`,
|
|
430
443
|
"",
|
|
431
444
|
"## Activation lanes",
|
|
432
445
|
...Object.entries(manifest.lanes).map(
|
|
@@ -440,6 +453,7 @@ function writeInitialHandoff(answers, manifest) {
|
|
|
440
453
|
...recentCommits.length > 0 ? recentCommits.map((line) => `- ${line}`) : ["- not available"],
|
|
441
454
|
"",
|
|
442
455
|
"## Next",
|
|
456
|
+
`- ${manifest.surfaceContract.nextSurfaceAction}`,
|
|
443
457
|
"- Ask the coding agent what it should know before editing the first target area.",
|
|
444
458
|
"- Review memory candidates before accepting durable memory.",
|
|
445
459
|
"- Connect GitHub later for PRs, reviews, team sync, and continuous sync.",
|
|
@@ -447,6 +461,24 @@ function writeInitialHandoff(answers, manifest) {
|
|
|
447
461
|
];
|
|
448
462
|
fs.writeFileSync(getActivationHandoffPath(), lines.join("\n"), "utf8");
|
|
449
463
|
}
|
|
464
|
+
function writeFirstWorkBrief(manifest) {
|
|
465
|
+
fs.mkdirSync(getActivationDir(), { recursive: true });
|
|
466
|
+
const lines = [
|
|
467
|
+
`# ${manifest.firstBrief.title}`,
|
|
468
|
+
"",
|
|
469
|
+
`Status: ${manifest.firstBrief.status}`,
|
|
470
|
+
`Activation: ${manifest.activationId}`,
|
|
471
|
+
`Client: ${getClientDisplayName(manifest.aiClient)}`,
|
|
472
|
+
"",
|
|
473
|
+
...manifest.firstBrief.sections.flatMap((section) => [
|
|
474
|
+
`## ${section.title}`,
|
|
475
|
+
"",
|
|
476
|
+
...section.lines.map((line) => `- ${line}`),
|
|
477
|
+
""
|
|
478
|
+
])
|
|
479
|
+
];
|
|
480
|
+
fs.writeFileSync(getFirstWorkBriefPath(), lines.join("\n"), "utf8");
|
|
481
|
+
}
|
|
450
482
|
function detectLocalActivationScan(detection) {
|
|
451
483
|
const cwd = process.cwd();
|
|
452
484
|
const exists = (relativePath) => fs.existsSync(path.join(cwd, relativePath));
|
|
@@ -549,6 +581,7 @@ function findDecisionArchaeologySources(cwd) {
|
|
|
549
581
|
return [.../* @__PURE__ */ new Set([...directSources, ...archaeologySources])].slice(0, 80);
|
|
550
582
|
}
|
|
551
583
|
function createInitialFirstWorkBrief(answers, detection, scan) {
|
|
584
|
+
const surfaceContract = buildActivationSurfaceContract(answers.aiClient);
|
|
552
585
|
const githubLine = answers.githubRepo ? `GitHub detected: ${answers.githubRepo.fullName}` : "No GitHub integration required for first value.";
|
|
553
586
|
const commands = scan.scripts.length > 0 ? scan.scripts.join(", ") : "no package scripts detected";
|
|
554
587
|
const docs = scan.files.candidateDocs.length > 0 ? scan.files.candidateDocs.join(", ") : "no standard docs detected";
|
|
@@ -566,6 +599,7 @@ function createInitialFirstWorkBrief(answers, detection, scan) {
|
|
|
566
599
|
detection.inGitRepo ? "Local Git repository detected." : "Local folder detected.",
|
|
567
600
|
githubLine,
|
|
568
601
|
`AI client: ${getClientDisplayName(answers.aiClient)}.`,
|
|
602
|
+
`Activation entry point: ${surfaceContract.entryPoint}.`,
|
|
569
603
|
`Languages: ${languages}.`
|
|
570
604
|
]
|
|
571
605
|
},
|
|
@@ -594,7 +628,10 @@ function createInitialFirstWorkBrief(answers, detection, scan) {
|
|
|
594
628
|
},
|
|
595
629
|
{
|
|
596
630
|
title: "Suggested next task",
|
|
597
|
-
lines: [
|
|
631
|
+
lines: [
|
|
632
|
+
surfaceContract.nextSurfaceAction,
|
|
633
|
+
"Ask your agent what it should know before editing the first target area."
|
|
634
|
+
]
|
|
598
635
|
},
|
|
599
636
|
{
|
|
600
637
|
title: "Top impacted modules",
|
|
@@ -612,10 +649,14 @@ function createActivationManifest(answers, detection, mode = "default", scan) {
|
|
|
612
649
|
const hasCompanion = answers.installCompanion;
|
|
613
650
|
const localScan = scan ?? detectLocalActivationScan(detection);
|
|
614
651
|
const dayZeroQuery = "What is this project, what is currently in flight, and what should an agent know before making the first edit?";
|
|
652
|
+
const surfaceContract = buildActivationSurfaceContract(answers.aiClient);
|
|
615
653
|
return {
|
|
616
654
|
version: "create-snipara-activation-v1",
|
|
655
|
+
schemaVersion: ACTIVATION_MANIFEST_SCHEMA_VERSION,
|
|
617
656
|
activationId: buildActivationId(),
|
|
618
657
|
mode,
|
|
658
|
+
surfaceContract,
|
|
659
|
+
consumerContract: buildEditorActivationConsumerContract(answers.aiClient),
|
|
619
660
|
activationMetric: {
|
|
620
661
|
name: "time_to_how_did_it_know_that",
|
|
621
662
|
targetMinutes: 5,
|
|
@@ -683,9 +724,13 @@ function createActivationManifest(answers, detection, mode = "default", scan) {
|
|
|
683
724
|
)
|
|
684
725
|
},
|
|
685
726
|
artifacts: {
|
|
727
|
+
activationManifestPath: path.relative(process.cwd(), getStableActivationManifestPath()),
|
|
728
|
+
legacyManifestPath: path.relative(process.cwd(), getActivationManifestPath()),
|
|
729
|
+
firstBriefPath: null,
|
|
686
730
|
handoffPath: null,
|
|
687
731
|
memoryCandidatesPath: null
|
|
688
732
|
},
|
|
733
|
+
nextActions: buildActivationNextActions(surfaceContract, answers),
|
|
689
734
|
firstBrief: createInitialFirstWorkBrief(answers, detection, localScan),
|
|
690
735
|
createdAt: now,
|
|
691
736
|
updatedAt: now
|
|
@@ -888,10 +933,12 @@ function createActivationArtifacts(answers, manifest) {
|
|
|
888
933
|
"Initial local handoff created.",
|
|
889
934
|
manifest.artifacts.handoffPath
|
|
890
935
|
);
|
|
936
|
+
writeFirstWorkBrief(manifest);
|
|
937
|
+
manifest.artifacts.firstBriefPath = path.relative(process.cwd(), getFirstWorkBriefPath());
|
|
891
938
|
manifest.lanes.firstBrief = createActivationLane(
|
|
892
939
|
"ready",
|
|
893
940
|
"First Work Brief generated from local setup and scan signals.",
|
|
894
|
-
|
|
941
|
+
manifest.artifacts.firstBriefPath
|
|
895
942
|
);
|
|
896
943
|
updateActivationManifest(manifest);
|
|
897
944
|
}
|
|
@@ -984,7 +1031,7 @@ function buildProgram() {
|
|
|
984
1031
|
).option("--advanced", "Show advanced profile, project id, hooks, GitHub, and sandbox prompts").option(
|
|
985
1032
|
"--profile <profile>",
|
|
986
1033
|
"Install profile: hosted-only, hosted-companion, full-stack, runtime-only"
|
|
987
|
-
).option("--skip-companion", "Skip local companion CLI installation").option("--skip-mcp", "Skip local snipara-mcp package installation").option("--skip-runtime", "Skip snipara-sandbox installation").option("--skip-hooks", "Skip hook generation").option("--skip-test", "Skip hosted connection test").option("--with-orchestrator", "Install optional snipara-orchestrator package").option("--github", "Open GitHub repository automation setup when a git remote is detected").option("--skip-github", "Skip the GitHub automation prompt").option("--github-path <path>", "Optional GitHub path filter for the initial repository sync").option("--starter", "Mark this run as a starter activation and print dashboard-first guidance").option("--runtime-only", "Install only Snipara Sandbox").addOption(new Option("--full", "Legacy alias for --profile full-stack").hideHelp()).option("-y, --yes", "Accept defaults without prompting").action(async (options) => {
|
|
1034
|
+
).option("--skip-companion", "Skip local companion CLI installation").option("--skip-mcp", "Skip local snipara-mcp package installation").option("--skip-runtime", "Skip snipara-sandbox installation").option("--skip-hooks", "Skip hook generation").option("--skip-test", "Skip hosted connection test").option("--with-orchestrator", "Install optional snipara-orchestrator package").option("--github", "Open GitHub repository automation setup when a git remote is detected").option("--skip-github", "Skip the GitHub automation prompt").option("--github-path <path>", "Optional GitHub path filter for the initial repository sync").option("--starter", "Mark this run as a starter activation and print dashboard-first guidance").option("--json", "Print a machine-readable activation summary after setup").option("--runtime-only", "Install only Snipara Sandbox").addOption(new Option("--full", "Legacy alias for --profile full-stack").hideHelp()).option("-y, --yes", "Accept defaults without prompting").action(async (options) => {
|
|
988
1035
|
printBanner();
|
|
989
1036
|
await runInit(options);
|
|
990
1037
|
});
|
|
@@ -1025,7 +1072,7 @@ function addSharedRootOptions(program) {
|
|
|
1025
1072
|
).option("--advanced", "Show advanced profile, project id, hooks, GitHub, and sandbox prompts").option(
|
|
1026
1073
|
"--profile <profile>",
|
|
1027
1074
|
"Install profile: hosted-only, hosted-companion, full-stack, runtime-only"
|
|
1028
|
-
).option("--skip-companion", "Skip local companion CLI installation").option("--skip-mcp", "Skip local snipara-mcp package installation").option("--skip-runtime", "Skip snipara-sandbox installation").option("--skip-hooks", "Skip hook generation").option("--skip-test", "Skip hosted connection test").option("--with-orchestrator", "Install optional snipara-orchestrator package").option("--github", "Open GitHub repository automation setup when a git remote is detected").option("--skip-github", "Skip the GitHub automation prompt").option("--github-path <path>", "Optional GitHub path filter for the initial repository sync").option("--starter", "Mark this run as a starter activation and print dashboard-first guidance").option("--runtime-only", "Install only Snipara Sandbox").addOption(new Option("--full", "Legacy alias for --profile full-stack").hideHelp()).option("-y, --yes", "Accept defaults without prompting");
|
|
1075
|
+
).option("--skip-companion", "Skip local companion CLI installation").option("--skip-mcp", "Skip local snipara-mcp package installation").option("--skip-runtime", "Skip snipara-sandbox installation").option("--skip-hooks", "Skip hook generation").option("--skip-test", "Skip hosted connection test").option("--with-orchestrator", "Install optional snipara-orchestrator package").option("--github", "Open GitHub repository automation setup when a git remote is detected").option("--skip-github", "Skip the GitHub automation prompt").option("--github-path <path>", "Optional GitHub path filter for the initial repository sync").option("--starter", "Mark this run as a starter activation and print dashboard-first guidance").option("--json", "Print a machine-readable activation summary after setup").option("--runtime-only", "Install only Snipara Sandbox").addOption(new Option("--full", "Legacy alias for --profile full-stack").hideHelp()).option("-y, --yes", "Accept defaults without prompting");
|
|
1029
1076
|
}
|
|
1030
1077
|
async function main() {
|
|
1031
1078
|
const program = buildProgram();
|
|
@@ -1125,6 +1172,7 @@ function parseInitOptionsFromArgv(args) {
|
|
|
1125
1172
|
"--github": "github",
|
|
1126
1173
|
"--skip-github": "skipGithub",
|
|
1127
1174
|
"--starter": "starter",
|
|
1175
|
+
"--json": "json",
|
|
1128
1176
|
"--yes": "yes",
|
|
1129
1177
|
"-y": "yes"
|
|
1130
1178
|
};
|
|
@@ -1189,6 +1237,11 @@ async function runInit(options) {
|
|
|
1189
1237
|
runLocalSourceActivation(answers, activationManifest);
|
|
1190
1238
|
createActivationArtifacts(answers, activationManifest);
|
|
1191
1239
|
printSuccess(answers, validationReport, activationManifest);
|
|
1240
|
+
if (normalizedOptions.json) {
|
|
1241
|
+
console.log(
|
|
1242
|
+
JSON.stringify(buildActivationJsonSummary(activationManifest, validationReport), null, 2)
|
|
1243
|
+
);
|
|
1244
|
+
}
|
|
1192
1245
|
if (answers.configureGitHub && answers.githubRepo) {
|
|
1193
1246
|
await openGitHubAutomation(answers);
|
|
1194
1247
|
}
|
|
@@ -1196,6 +1249,35 @@ async function runInit(options) {
|
|
|
1196
1249
|
await runSandboxInit();
|
|
1197
1250
|
}
|
|
1198
1251
|
}
|
|
1252
|
+
function buildActivationJsonSummary(manifest, validation) {
|
|
1253
|
+
const laneEntries = Object.entries(manifest.lanes);
|
|
1254
|
+
const failedLanes = laneEntries.filter(([, lane]) => lane.status === "failed").map(([name]) => name);
|
|
1255
|
+
const pendingLanes = laneEntries.filter(([, lane]) => lane.status === "queued" || lane.status === "indexing").map(([name]) => name);
|
|
1256
|
+
const activationStatus = failedLanes.length > 0 ? "partial" : pendingLanes.length > 0 ? "partial" : "complete";
|
|
1257
|
+
return {
|
|
1258
|
+
ok: true,
|
|
1259
|
+
activationStatus,
|
|
1260
|
+
activationId: manifest.activationId,
|
|
1261
|
+
schemaVersion: manifest.schemaVersion,
|
|
1262
|
+
consumerContractVersion: manifest.consumerContract.version,
|
|
1263
|
+
projectSlug: manifest.projectSlug,
|
|
1264
|
+
aiClient: manifest.aiClient,
|
|
1265
|
+
profile: validation.profile,
|
|
1266
|
+
artifacts: manifest.artifacts,
|
|
1267
|
+
lanes: Object.fromEntries(
|
|
1268
|
+
laneEntries.map(([name, lane]) => [
|
|
1269
|
+
name,
|
|
1270
|
+
{
|
|
1271
|
+
status: lane.status,
|
|
1272
|
+
detail: lane.detail,
|
|
1273
|
+
command: lane.command
|
|
1274
|
+
}
|
|
1275
|
+
])
|
|
1276
|
+
),
|
|
1277
|
+
nextActions: manifest.nextActions,
|
|
1278
|
+
exitCode: activationStatus === "complete" ? 0 : manifest.consumerContract.exitCodes.activation_partial
|
|
1279
|
+
};
|
|
1280
|
+
}
|
|
1199
1281
|
async function runDoctor(options) {
|
|
1200
1282
|
const normalizedOptions = normalizeMaintenanceOptions(options);
|
|
1201
1283
|
const requestedClient = normalizeClientOption(normalizedOptions.client);
|
|
@@ -1279,11 +1361,12 @@ async function runUpgrade(options) {
|
|
|
1279
1361
|
printDoctorReport(detectEnvironment(), report);
|
|
1280
1362
|
}
|
|
1281
1363
|
async function runPrintConfig(options) {
|
|
1364
|
+
const normalizedOptions = normalizeMaintenanceOptions(options);
|
|
1282
1365
|
const detection = detectEnvironment();
|
|
1283
|
-
const answers = loadExistingAnswers(
|
|
1366
|
+
const answers = loadExistingAnswers(normalizedOptions);
|
|
1284
1367
|
const githubRepo = detectGitRepository();
|
|
1285
1368
|
const githubAnswerPacks = githubRepo ? `${githubRepo.fullName} can be connected with npx create-snipara --github` : "requires a GitHub-backed git remote";
|
|
1286
|
-
if (
|
|
1369
|
+
if (normalizedOptions.json) {
|
|
1287
1370
|
console.log(
|
|
1288
1371
|
JSON.stringify(
|
|
1289
1372
|
{
|
|
@@ -3330,6 +3413,124 @@ function readCompanionConfigFile(filePath) {
|
|
|
3330
3413
|
return {};
|
|
3331
3414
|
}
|
|
3332
3415
|
}
|
|
3416
|
+
function buildActivationSurfaceContract(client) {
|
|
3417
|
+
const shared = {
|
|
3418
|
+
doctrine: "one_activation_engine_multiple_entry_points",
|
|
3419
|
+
engine: "create-snipara",
|
|
3420
|
+
firstSuccessState: "Hosted MCP connected, local workspace context seeded, and a First Work Brief ready for the next agent session.",
|
|
3421
|
+
mustNotDuplicate: [
|
|
3422
|
+
"Local source scan heuristics",
|
|
3423
|
+
"First Work Brief generation",
|
|
3424
|
+
"memory-candidate extraction",
|
|
3425
|
+
"Hosted MCP config contract"
|
|
3426
|
+
]
|
|
3427
|
+
};
|
|
3428
|
+
if (client === "cursor") {
|
|
3429
|
+
return {
|
|
3430
|
+
...shared,
|
|
3431
|
+
entryPoint: "Cursor extension or Cursor agent instructions call create-snipara",
|
|
3432
|
+
clientRole: "Lightweight editor surface: expose rules, skills, and the canonical bootstrap path; do not fork activation logic.",
|
|
3433
|
+
nextSurfaceAction: "In Cursor, ask the agent to run or verify `npx create-snipara@latest init --client cursor --starter`, then use the generated rules and Hosted MCP tools."
|
|
3434
|
+
};
|
|
3435
|
+
}
|
|
3436
|
+
if (client === "vscode") {
|
|
3437
|
+
return {
|
|
3438
|
+
...shared,
|
|
3439
|
+
entryPoint: "VS Code extension command or create-snipara bootstrap",
|
|
3440
|
+
clientRole: "Native editor UX surface: provide SecretStorage, progress, panels, status, and Copilot handoff while keeping activation semantics aligned with create-snipara.",
|
|
3441
|
+
nextSurfaceAction: "In VS Code, run `Snipara: Activate Workspace` when the extension is installed, or keep using this generated pack when bootstrapping from the terminal."
|
|
3442
|
+
};
|
|
3443
|
+
}
|
|
3444
|
+
if (client === "claude-code") {
|
|
3445
|
+
return {
|
|
3446
|
+
...shared,
|
|
3447
|
+
entryPoint: "Claude Code plugin or create-snipara bootstrap",
|
|
3448
|
+
clientRole: "Agent-first surface: load Hosted MCP and project instructions, then use Companion only for explicit local continuity workflows.",
|
|
3449
|
+
nextSurfaceAction: "Start a new Claude Code session and validate Snipara tools before enabling hooks or managed workflows."
|
|
3450
|
+
};
|
|
3451
|
+
}
|
|
3452
|
+
return {
|
|
3453
|
+
...shared,
|
|
3454
|
+
entryPoint: `${getClientDisplayName(client)} setup generated by create-snipara`,
|
|
3455
|
+
clientRole: "MCP-compatible surface: consume the generated Hosted MCP reference and AGENTS.md rather than owning a separate activation model.",
|
|
3456
|
+
nextSurfaceAction: "Restart or reload the client, verify Snipara tools, then ask the first grounded project question from the generated First Work Brief."
|
|
3457
|
+
};
|
|
3458
|
+
}
|
|
3459
|
+
function buildEditorActivationConsumerContract(client) {
|
|
3460
|
+
const secretRule = client === "vscode" ? "Use VS Code SecretStorage for SNIPARA_API_KEY and pass it to create-snipara through the child-process environment; never write raw secrets into extension settings or logs." : "Pass SNIPARA_API_KEY through the process environment or client secret store; never parse, log, or persist raw secrets from terminal output.";
|
|
3461
|
+
return {
|
|
3462
|
+
version: ACTIVATION_CONSUMER_CONTRACT_VERSION,
|
|
3463
|
+
audience: "editor_extension",
|
|
3464
|
+
stableFiles: {
|
|
3465
|
+
activationManifest: ".snipara/activation/activation-manifest.json",
|
|
3466
|
+
firstBrief: ".snipara/activation/first-brief.md",
|
|
3467
|
+
handoff: ".snipara/activation/handoff.md",
|
|
3468
|
+
memoryCandidates: ".snipara/activation/memory-candidates.json"
|
|
3469
|
+
},
|
|
3470
|
+
requiredManifestFields: [
|
|
3471
|
+
"schemaVersion",
|
|
3472
|
+
"consumerContract.version",
|
|
3473
|
+
"surfaceContract",
|
|
3474
|
+
"artifacts.activationManifestPath",
|
|
3475
|
+
"artifacts.firstBriefPath",
|
|
3476
|
+
"artifacts.handoffPath",
|
|
3477
|
+
"lanes.connection.status",
|
|
3478
|
+
"lanes.firstBrief.status",
|
|
3479
|
+
"nextActions"
|
|
3480
|
+
],
|
|
3481
|
+
laneStatuses: ["ready", "indexing", "queued", "needs_review", "skipped", "failed"],
|
|
3482
|
+
exitCodes: {
|
|
3483
|
+
success: 0,
|
|
3484
|
+
activation_partial: 10,
|
|
3485
|
+
auth_required: 20,
|
|
3486
|
+
missing_api_key: 21,
|
|
3487
|
+
missing_node_or_npm: 30,
|
|
3488
|
+
activation_failed: 40
|
|
3489
|
+
},
|
|
3490
|
+
parseRule: "Read .snipara/activation/activation-manifest.json as the source of truth. If --json is used, parse the last JSON object from stdout as a summary pointer, not as the full durable state.",
|
|
3491
|
+
secretRule
|
|
3492
|
+
};
|
|
3493
|
+
}
|
|
3494
|
+
function buildActivationNextActions(surfaceContract, answers) {
|
|
3495
|
+
const actions = [
|
|
3496
|
+
{
|
|
3497
|
+
id: "open_first_work_brief",
|
|
3498
|
+
label: "Open First Work Brief",
|
|
3499
|
+
target: "editor",
|
|
3500
|
+
when: "artifacts.firstBriefPath is present and lanes.firstBrief.status is ready"
|
|
3501
|
+
},
|
|
3502
|
+
{
|
|
3503
|
+
id: "handoff_to_agent",
|
|
3504
|
+
label: "Hand off to the coding agent",
|
|
3505
|
+
target: "agent",
|
|
3506
|
+
when: "lanes.connection.status is ready and First Work Brief has been shown"
|
|
3507
|
+
},
|
|
3508
|
+
{
|
|
3509
|
+
id: "review_memory_candidates",
|
|
3510
|
+
label: "Review memory candidates",
|
|
3511
|
+
target: "editor",
|
|
3512
|
+
when: "lanes.memoryCandidates.status is needs_review"
|
|
3513
|
+
}
|
|
3514
|
+
];
|
|
3515
|
+
if (answers.aiClient === "vscode") {
|
|
3516
|
+
actions.unshift({
|
|
3517
|
+
id: "vscode_activate_workspace",
|
|
3518
|
+
label: "Snipara: Activate Workspace",
|
|
3519
|
+
command: "Snipara: Activate Workspace",
|
|
3520
|
+
target: "editor",
|
|
3521
|
+
when: "VS Code extension command is available"
|
|
3522
|
+
});
|
|
3523
|
+
} else {
|
|
3524
|
+
actions.unshift({
|
|
3525
|
+
id: "verify_surface_activation",
|
|
3526
|
+
label: "Verify activation surface",
|
|
3527
|
+
command: surfaceContract.nextSurfaceAction,
|
|
3528
|
+
target: "agent",
|
|
3529
|
+
when: "editor-specific command is unavailable"
|
|
3530
|
+
});
|
|
3531
|
+
}
|
|
3532
|
+
return actions;
|
|
3533
|
+
}
|
|
3333
3534
|
function getClientGuidance(client) {
|
|
3334
3535
|
if (client === "claude-code") {
|
|
3335
3536
|
return [
|
|
@@ -3339,6 +3540,7 @@ function getClientGuidance(client) {
|
|
|
3339
3540
|
}
|
|
3340
3541
|
if (client === "cursor") {
|
|
3341
3542
|
return [
|
|
3543
|
+
"Cursor is a lightweight editor entry point: use create-snipara as the canonical activation engine, then let Cursor consume the generated rules and Hosted MCP context.",
|
|
3342
3544
|
"Cursor reads the generated .mcp.json directly, so the hosted Snipara MCP surface is available after restart.",
|
|
3343
3545
|
"Use the companion CLI only for explicit upload, planning, chunk lookup, doctor, and task commit workflows outside the editor UI."
|
|
3344
3546
|
];
|
|
@@ -3374,6 +3576,7 @@ function getClientGuidance(client) {
|
|
|
3374
3576
|
}
|
|
3375
3577
|
if (client === "vscode") {
|
|
3376
3578
|
return [
|
|
3579
|
+
"VS Code can provide native activation UX, but create-snipara remains the canonical activation contract for generated files and local briefing semantics.",
|
|
3377
3580
|
"VS Code and Copilot-style clients should use Hosted MCP plus AGENTS.md for project workflow rules.",
|
|
3378
3581
|
"Use .snipara/templates/vscode-mcp-reference.json as the Snipara server reference when adding an MCP server."
|
|
3379
3582
|
];
|
|
@@ -3639,11 +3842,24 @@ function buildClientPackMarkdown(answers, commands, guidance) {
|
|
|
3639
3842
|
const bootstrapCommand = commands.find(
|
|
3640
3843
|
(command) => command.title === "Bootstrap local companion"
|
|
3641
3844
|
);
|
|
3845
|
+
const surfaceContract = buildActivationSurfaceContract(answers.aiClient);
|
|
3642
3846
|
return `# Snipara Pack: ${clientName}
|
|
3643
3847
|
|
|
3644
3848
|
This pack is the client-specific overlay for the generated Snipara project setup.
|
|
3645
3849
|
Use \`AGENTS.md\` as the shared source of agent behavior, then apply the client-specific files below.
|
|
3646
3850
|
|
|
3851
|
+
## Activation Contract
|
|
3852
|
+
|
|
3853
|
+
- Doctrine: one activation engine, multiple entry points
|
|
3854
|
+
- Canonical engine: \`${surfaceContract.engine}\`
|
|
3855
|
+
- Entry point: ${surfaceContract.entryPoint}
|
|
3856
|
+
- Client role: ${surfaceContract.clientRole}
|
|
3857
|
+
- First success state: ${surfaceContract.firstSuccessState}
|
|
3858
|
+
- Next surface action: ${surfaceContract.nextSurfaceAction}
|
|
3859
|
+
|
|
3860
|
+
The client-specific files in this pack should not reimplement local source scanning,
|
|
3861
|
+
First Work Brief generation, memory-candidate extraction, or Hosted MCP config semantics.
|
|
3862
|
+
|
|
3647
3863
|
## Hosted MCP
|
|
3648
3864
|
|
|
3649
3865
|
- Endpoint: \`${buildHostedMcpEndpoint(answers)}\`
|
|
@@ -3692,6 +3908,8 @@ async function createCompanionPack(answers) {
|
|
|
3692
3908
|
const readme = `# Snipara Companion Pack
|
|
3693
3909
|
|
|
3694
3910
|
This project uses Snipara as a hosted-first project intelligence layer with source-backed context, reviewed memory, and local companion workflow helpers.
|
|
3911
|
+
The activation doctrine is: one shared activation engine, multiple entry points.
|
|
3912
|
+
\`create-snipara\` is the canonical bootstrap; editor extensions and plugins should provide UI, rules, or handoff affordances without forking the activation engine.
|
|
3695
3913
|
|
|
3696
3914
|
## Install Profile
|
|
3697
3915
|
|
|
@@ -3721,6 +3939,18 @@ This project uses Snipara as a hosted-first project intelligence layer with sour
|
|
|
3721
3939
|
|
|
3722
3940
|
${guidance.map((line) => `- ${line}`).join("\n")}
|
|
3723
3941
|
|
|
3942
|
+
## Activation Continuity Loop
|
|
3943
|
+
|
|
3944
|
+
After the First Work Brief, use Companion when local continuity matters:
|
|
3945
|
+
|
|
3946
|
+
1. Start or resume with \`${COMPANION_NPX_COMMAND} session-bootstrap --include-session-context --max-context-tokens 1000\`.
|
|
3947
|
+
2. Refresh local source context with \`${COMPANION_NPX_COMMAND} source sync --json\` after meaningful doc or code movement.
|
|
3948
|
+
3. Before risky edits, use \`${COMPANION_NPX_COMMAND} code impact --changed-files <files> --diff-summary "<change>"\`.
|
|
3949
|
+
4. End durable work with \`${COMPANION_NPX_COMMAND} task-commit --summary "<what changed>" --files <files>\`.
|
|
3950
|
+
|
|
3951
|
+
Keep quick editor usage in the editor. Use Companion for explicit continuity, source refresh,
|
|
3952
|
+
workflow phase state, guards, impact checks, business-folder onboarding, and durable task memory.
|
|
3953
|
+
|
|
3724
3954
|
## Business Folder Onboarding
|
|
3725
3955
|
|
|
3726
3956
|
Use this when Claude, ChatGPT, Codex, or another LLM client has already materialized Drive, Notion, Gmail, or local business files into a folder.
|
|
@@ -4511,6 +4741,11 @@ function printActivationSummary(manifest) {
|
|
|
4511
4741
|
` Day-zero corpus: ${manifest.dayZeroCorpus.status} - ${manifest.dayZeroCorpus.detail}`
|
|
4512
4742
|
)
|
|
4513
4743
|
);
|
|
4744
|
+
console.log(chalk.bold("\nActivation surface:\n"));
|
|
4745
|
+
console.log(` Engine: ${manifest.surfaceContract.engine}`);
|
|
4746
|
+
console.log(` Entry point: ${manifest.surfaceContract.entryPoint}`);
|
|
4747
|
+
console.log(chalk.dim(` Role: ${manifest.surfaceContract.clientRole}`));
|
|
4748
|
+
console.log(chalk.dim(` Next: ${manifest.surfaceContract.nextSurfaceAction}`));
|
|
4514
4749
|
console.log(chalk.bold("\nAgent readiness:\n"));
|
|
4515
4750
|
console.log(` ${manifest.agentReadiness.summary}`);
|
|
4516
4751
|
for (const finding of manifest.agentReadiness.stalenessFindings.slice(0, 3)) {
|
package/package.json
CHANGED