create-snipara 2.0.9 → 2.0.11
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 +4 -1
- package/dist/index.js +272 -4
- 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,
|
|
@@ -26,7 +29,7 @@ Use it for:
|
|
|
26
29
|
- free account signup with reviewed Context + Memory
|
|
27
30
|
- local project wiring, `doctor`, `repair`, and `upgrade`
|
|
28
31
|
- 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
|
|
32
|
+
- day-zero Project Intelligence proof: a First Work Brief, a ready-to-run `snipara_context_query`, a small hosted README/docs seed sync for virgin projects, review-only decision archaeology candidates, possible doc-staleness findings, and an estimated context economy report from the user's own repository
|
|
30
33
|
|
|
31
34
|
## Why It Exists
|
|
32
35
|
|
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.11",
|
|
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",
|
|
@@ -104,6 +104,9 @@ var SANDBOX_COMMAND_NAME = "snipara-sandbox";
|
|
|
104
104
|
var LEGACY_SANDBOX_COMMAND_NAME = "rlm";
|
|
105
105
|
var ORCHESTRATOR_COMMAND_NAME = "snipara-orchestrator";
|
|
106
106
|
var DEVICE_CLIENT_ID = "create-snipara";
|
|
107
|
+
var DAY_ZERO_CORPUS_MAX_FILES = 8;
|
|
108
|
+
var DAY_ZERO_CORPUS_MAX_FILE_CHARS = 12e3;
|
|
109
|
+
var DAY_ZERO_CORPUS_MAX_TOTAL_CHARS = 5e4;
|
|
107
110
|
var EXPERIENCE_GOAL_SECTION = `## Experience Goal
|
|
108
111
|
|
|
109
112
|
The target experience is outcome-first agent work across supported clients:
|
|
@@ -288,6 +291,63 @@ function readTextFileSnippet(relativePath, maxChars = 24e3) {
|
|
|
288
291
|
return "";
|
|
289
292
|
}
|
|
290
293
|
}
|
|
294
|
+
function collectDayZeroCorpusDocuments(scan) {
|
|
295
|
+
const documents = [];
|
|
296
|
+
let totalChars = 0;
|
|
297
|
+
const cwd = process.cwd();
|
|
298
|
+
const rootReadmes = fs.existsSync(cwd) ? fs.readdirSync(cwd).filter((entry) => /^readme(?:\.[a-z0-9_-]+)?\.mdx?$/i.test(entry)).sort() : [];
|
|
299
|
+
const sources = [
|
|
300
|
+
...rootReadmes,
|
|
301
|
+
...listFilesUnder("docs", DAY_ZERO_CORPUS_MAX_FILES * 8),
|
|
302
|
+
...scan.files.candidateDocs
|
|
303
|
+
];
|
|
304
|
+
const seen = /* @__PURE__ */ new Set();
|
|
305
|
+
for (const source of sources) {
|
|
306
|
+
const normalized = source.replace(/\\/g, "/");
|
|
307
|
+
if (seen.has(normalized)) {
|
|
308
|
+
continue;
|
|
309
|
+
}
|
|
310
|
+
seen.add(normalized);
|
|
311
|
+
const lower = normalized.toLowerCase();
|
|
312
|
+
const isReadme = /^readme(?:\.[a-z0-9_-]+)?\.mdx?$/.test(lower);
|
|
313
|
+
const isDocsMarkdown = lower.startsWith("docs/") && /\.(?:md|mdx|markdown|txt|rst|adoc)$/.test(lower);
|
|
314
|
+
if (!isReadme && !isDocsMarkdown) {
|
|
315
|
+
continue;
|
|
316
|
+
}
|
|
317
|
+
if (documents.length >= DAY_ZERO_CORPUS_MAX_FILES) {
|
|
318
|
+
break;
|
|
319
|
+
}
|
|
320
|
+
if (totalChars >= DAY_ZERO_CORPUS_MAX_TOTAL_CHARS) {
|
|
321
|
+
break;
|
|
322
|
+
}
|
|
323
|
+
const remainingChars = DAY_ZERO_CORPUS_MAX_TOTAL_CHARS - totalChars;
|
|
324
|
+
const content = readTextFileSnippet(
|
|
325
|
+
source,
|
|
326
|
+
Math.min(DAY_ZERO_CORPUS_MAX_FILE_CHARS, remainingChars)
|
|
327
|
+
).trim();
|
|
328
|
+
if (!content) {
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
documents.push({
|
|
332
|
+
path: normalized,
|
|
333
|
+
content
|
|
334
|
+
});
|
|
335
|
+
totalChars += content.length;
|
|
336
|
+
}
|
|
337
|
+
return documents;
|
|
338
|
+
}
|
|
339
|
+
function createDayZeroCorpusReport(status, documents, detail, options = {}) {
|
|
340
|
+
return {
|
|
341
|
+
status,
|
|
342
|
+
documents: documents.map((document) => ({
|
|
343
|
+
path: document.path,
|
|
344
|
+
chars: document.content.length
|
|
345
|
+
})),
|
|
346
|
+
detail,
|
|
347
|
+
...options.tool ? { tool: options.tool } : {},
|
|
348
|
+
...options.error ? { error: options.error.slice(0, 500) } : {}
|
|
349
|
+
};
|
|
350
|
+
}
|
|
291
351
|
function buildStalenessFindings(scan) {
|
|
292
352
|
const findings = [];
|
|
293
353
|
const scriptSet = new Set(scan.scripts);
|
|
@@ -367,6 +427,9 @@ function writeInitialHandoff(answers, manifest) {
|
|
|
367
427
|
`Repo path: ${manifest.repoPath}`,
|
|
368
428
|
`Git branch: ${manifest.git.branch ?? "not detected"}`,
|
|
369
429
|
`Git remote: ${manifest.git.remote ?? "not detected"}`,
|
|
430
|
+
`Activation doctrine: ${manifest.surfaceContract.doctrine}`,
|
|
431
|
+
`Activation engine: ${manifest.surfaceContract.engine}`,
|
|
432
|
+
`Entry point: ${manifest.surfaceContract.entryPoint}`,
|
|
370
433
|
"",
|
|
371
434
|
"## Activation lanes",
|
|
372
435
|
...Object.entries(manifest.lanes).map(
|
|
@@ -380,6 +443,7 @@ function writeInitialHandoff(answers, manifest) {
|
|
|
380
443
|
...recentCommits.length > 0 ? recentCommits.map((line) => `- ${line}`) : ["- not available"],
|
|
381
444
|
"",
|
|
382
445
|
"## Next",
|
|
446
|
+
`- ${manifest.surfaceContract.nextSurfaceAction}`,
|
|
383
447
|
"- Ask the coding agent what it should know before editing the first target area.",
|
|
384
448
|
"- Review memory candidates before accepting durable memory.",
|
|
385
449
|
"- Connect GitHub later for PRs, reviews, team sync, and continuous sync.",
|
|
@@ -489,6 +553,7 @@ function findDecisionArchaeologySources(cwd) {
|
|
|
489
553
|
return [.../* @__PURE__ */ new Set([...directSources, ...archaeologySources])].slice(0, 80);
|
|
490
554
|
}
|
|
491
555
|
function createInitialFirstWorkBrief(answers, detection, scan) {
|
|
556
|
+
const surfaceContract = buildActivationSurfaceContract(answers.aiClient);
|
|
492
557
|
const githubLine = answers.githubRepo ? `GitHub detected: ${answers.githubRepo.fullName}` : "No GitHub integration required for first value.";
|
|
493
558
|
const commands = scan.scripts.length > 0 ? scan.scripts.join(", ") : "no package scripts detected";
|
|
494
559
|
const docs = scan.files.candidateDocs.length > 0 ? scan.files.candidateDocs.join(", ") : "no standard docs detected";
|
|
@@ -506,6 +571,7 @@ function createInitialFirstWorkBrief(answers, detection, scan) {
|
|
|
506
571
|
detection.inGitRepo ? "Local Git repository detected." : "Local folder detected.",
|
|
507
572
|
githubLine,
|
|
508
573
|
`AI client: ${getClientDisplayName(answers.aiClient)}.`,
|
|
574
|
+
`Activation entry point: ${surfaceContract.entryPoint}.`,
|
|
509
575
|
`Languages: ${languages}.`
|
|
510
576
|
]
|
|
511
577
|
},
|
|
@@ -534,7 +600,10 @@ function createInitialFirstWorkBrief(answers, detection, scan) {
|
|
|
534
600
|
},
|
|
535
601
|
{
|
|
536
602
|
title: "Suggested next task",
|
|
537
|
-
lines: [
|
|
603
|
+
lines: [
|
|
604
|
+
surfaceContract.nextSurfaceAction,
|
|
605
|
+
"Ask your agent what it should know before editing the first target area."
|
|
606
|
+
]
|
|
538
607
|
},
|
|
539
608
|
{
|
|
540
609
|
title: "Top impacted modules",
|
|
@@ -552,10 +621,12 @@ function createActivationManifest(answers, detection, mode = "default", scan) {
|
|
|
552
621
|
const hasCompanion = answers.installCompanion;
|
|
553
622
|
const localScan = scan ?? detectLocalActivationScan(detection);
|
|
554
623
|
const dayZeroQuery = "What is this project, what is currently in flight, and what should an agent know before making the first edit?";
|
|
624
|
+
const surfaceContract = buildActivationSurfaceContract(answers.aiClient);
|
|
555
625
|
return {
|
|
556
626
|
version: "create-snipara-activation-v1",
|
|
557
627
|
activationId: buildActivationId(),
|
|
558
628
|
mode,
|
|
629
|
+
surfaceContract,
|
|
559
630
|
activationMetric: {
|
|
560
631
|
name: "time_to_how_did_it_know_that",
|
|
561
632
|
targetMinutes: 5,
|
|
@@ -566,6 +637,11 @@ function createActivationManifest(answers, detection, mode = "default", scan) {
|
|
|
566
637
|
query: dayZeroQuery,
|
|
567
638
|
expectedOutcome: "First own-repo answer pack before the user reads product docs."
|
|
568
639
|
},
|
|
640
|
+
dayZeroCorpus: createDayZeroCorpusReport(
|
|
641
|
+
"queued",
|
|
642
|
+
collectDayZeroCorpusDocuments(localScan),
|
|
643
|
+
"README and docs Markdown will be submitted to hosted context before the first day-zero query when live hosted checks are enabled."
|
|
644
|
+
),
|
|
569
645
|
agentReadiness: buildAgentReadinessReport(localScan),
|
|
570
646
|
contextEconomy: buildContextEconomyReport(localScan, dayZeroQuery),
|
|
571
647
|
projectSlug: answers.projectSlug,
|
|
@@ -593,8 +669,8 @@ function createActivationManifest(answers, detection, mode = "default", scan) {
|
|
|
593
669
|
hasCompanion ? "Local source activation will create a repository snapshot." : "Install companion later to activate local source context."
|
|
594
670
|
),
|
|
595
671
|
contextIndex: createActivationLane(
|
|
596
|
-
hasCompanion ? "queued" : "skipped",
|
|
597
|
-
hasCompanion ? "Context indexing starts from local docs and instruction files." : "Context indexing requires companion or hosted provider sync."
|
|
672
|
+
hasHostedConfig || hasCompanion ? "queued" : "skipped",
|
|
673
|
+
hasCompanion ? "Context indexing starts from local docs and instruction files." : hasHostedConfig ? "Day-zero README/docs sync will seed hosted context when live hosted checks run." : "Context indexing requires companion or hosted provider sync."
|
|
598
674
|
),
|
|
599
675
|
codeGraph: createActivationLane(
|
|
600
676
|
hasCompanion ? "queued" : "skipped",
|
|
@@ -698,6 +774,115 @@ function runLocalSourceActivation(answers, manifest) {
|
|
|
698
774
|
}
|
|
699
775
|
updateActivationManifest(manifest);
|
|
700
776
|
}
|
|
777
|
+
async function runHostedDayZeroCorpusSync(answers, manifest, enabled) {
|
|
778
|
+
if (answers.profile === "runtime-only") {
|
|
779
|
+
manifest.dayZeroCorpus = createDayZeroCorpusReport(
|
|
780
|
+
"skipped",
|
|
781
|
+
[],
|
|
782
|
+
"Runtime-only profile skipped Hosted MCP config and hosted document sync."
|
|
783
|
+
);
|
|
784
|
+
updateActivationManifest(manifest);
|
|
785
|
+
return;
|
|
786
|
+
}
|
|
787
|
+
if (!enabled) {
|
|
788
|
+
const documents2 = collectDayZeroCorpusDocuments(manifest.localScan);
|
|
789
|
+
manifest.dayZeroCorpus = createDayZeroCorpusReport(
|
|
790
|
+
"skipped",
|
|
791
|
+
documents2,
|
|
792
|
+
"Skipped because hosted validation was disabled with --skip-test."
|
|
793
|
+
);
|
|
794
|
+
updateActivationManifest(manifest);
|
|
795
|
+
return;
|
|
796
|
+
}
|
|
797
|
+
if (answers.apiKeyType === "none" || answers.apiKey.includes("YOUR_")) {
|
|
798
|
+
manifest.dayZeroCorpus = createDayZeroCorpusReport(
|
|
799
|
+
"skipped",
|
|
800
|
+
[],
|
|
801
|
+
"Skipped because no live hosted API key was available."
|
|
802
|
+
);
|
|
803
|
+
updateActivationManifest(manifest);
|
|
804
|
+
return;
|
|
805
|
+
}
|
|
806
|
+
const documents = collectDayZeroCorpusDocuments(manifest.localScan);
|
|
807
|
+
if (documents.length === 0) {
|
|
808
|
+
manifest.dayZeroCorpus = createDayZeroCorpusReport(
|
|
809
|
+
"skipped",
|
|
810
|
+
[],
|
|
811
|
+
"No README or docs Markdown files were found to seed hosted context."
|
|
812
|
+
);
|
|
813
|
+
if (manifest.lanes.contextIndex.status === "queued") {
|
|
814
|
+
manifest.lanes.contextIndex = createActivationLane(
|
|
815
|
+
"skipped",
|
|
816
|
+
"No README or docs Markdown files were found to seed hosted context."
|
|
817
|
+
);
|
|
818
|
+
}
|
|
819
|
+
updateActivationManifest(manifest);
|
|
820
|
+
return;
|
|
821
|
+
}
|
|
822
|
+
const syncTool = "snipara_sync_documents";
|
|
823
|
+
const syncResponse = await callHostedMcp(answers, "tools/call", {
|
|
824
|
+
name: syncTool,
|
|
825
|
+
arguments: {
|
|
826
|
+
documents,
|
|
827
|
+
delete_missing: false
|
|
828
|
+
}
|
|
829
|
+
});
|
|
830
|
+
if (syncResponse.ok && !syncResponse.data.error) {
|
|
831
|
+
manifest.dayZeroCorpus = createDayZeroCorpusReport(
|
|
832
|
+
"submitted",
|
|
833
|
+
documents,
|
|
834
|
+
`Submitted ${documents.length} README/docs files to hosted context for the first day-zero answer pack.`,
|
|
835
|
+
{ tool: syncTool }
|
|
836
|
+
);
|
|
837
|
+
manifest.lanes.contextIndex = createActivationLane(
|
|
838
|
+
"indexing",
|
|
839
|
+
"Day-zero README/docs corpus submitted to hosted context indexing.",
|
|
840
|
+
syncTool
|
|
841
|
+
);
|
|
842
|
+
updateActivationManifest(manifest);
|
|
843
|
+
return;
|
|
844
|
+
}
|
|
845
|
+
const uploadTool = "snipara_upload_document";
|
|
846
|
+
const uploadErrors = [];
|
|
847
|
+
for (const document of documents) {
|
|
848
|
+
const uploadResponse = await callHostedMcp(answers, "tools/call", {
|
|
849
|
+
name: uploadTool,
|
|
850
|
+
arguments: document
|
|
851
|
+
});
|
|
852
|
+
if (!uploadResponse.ok || uploadResponse.data.error) {
|
|
853
|
+
uploadErrors.push(
|
|
854
|
+
uploadResponse.ok ? describeJsonRpcError(uploadResponse.data) : describeHostedHttpFailure(uploadResponse.status, uploadResponse.bodyText)
|
|
855
|
+
);
|
|
856
|
+
break;
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
if (uploadErrors.length === 0) {
|
|
860
|
+
manifest.dayZeroCorpus = createDayZeroCorpusReport(
|
|
861
|
+
"submitted",
|
|
862
|
+
documents,
|
|
863
|
+
`Submitted ${documents.length} README/docs files to hosted context for the first day-zero answer pack.`,
|
|
864
|
+
{ tool: uploadTool }
|
|
865
|
+
);
|
|
866
|
+
manifest.lanes.contextIndex = createActivationLane(
|
|
867
|
+
"indexing",
|
|
868
|
+
"Day-zero README/docs corpus submitted to hosted context indexing.",
|
|
869
|
+
uploadTool
|
|
870
|
+
);
|
|
871
|
+
} else {
|
|
872
|
+
const syncError = syncResponse.ok ? describeJsonRpcError(syncResponse.data) : describeHostedHttpFailure(syncResponse.status, syncResponse.bodyText);
|
|
873
|
+
const detail = `Could not submit the day-zero README/docs corpus. sync_documents: ${syncError}; upload_document: ${uploadErrors[0]}`;
|
|
874
|
+
manifest.dayZeroCorpus = createDayZeroCorpusReport("failed", documents, detail, {
|
|
875
|
+
tool: syncTool,
|
|
876
|
+
error: detail
|
|
877
|
+
});
|
|
878
|
+
manifest.lanes.contextIndex = failActivationLane(
|
|
879
|
+
"Hosted day-zero README/docs sync failed; the first answer may need GitHub, companion, or a later sync.",
|
|
880
|
+
syncTool,
|
|
881
|
+
new Error(detail)
|
|
882
|
+
);
|
|
883
|
+
}
|
|
884
|
+
updateActivationManifest(manifest);
|
|
885
|
+
}
|
|
701
886
|
function createActivationArtifacts(answers, manifest) {
|
|
702
887
|
const candidates = buildMemoryCandidatePreviews(manifest.localScan);
|
|
703
888
|
writeMemoryCandidates(candidates);
|
|
@@ -1011,6 +1196,7 @@ async function runInit(options) {
|
|
|
1011
1196
|
normalizedOptions.starter ? "starter" : "default",
|
|
1012
1197
|
activationScan
|
|
1013
1198
|
);
|
|
1199
|
+
await runHostedDayZeroCorpusSync(answers, activationManifest, !normalizedOptions.skipTest);
|
|
1014
1200
|
runLocalSourceActivation(answers, activationManifest);
|
|
1015
1201
|
createActivationArtifacts(answers, activationManifest);
|
|
1016
1202
|
printSuccess(answers, validationReport, activationManifest);
|
|
@@ -3155,6 +3341,49 @@ function readCompanionConfigFile(filePath) {
|
|
|
3155
3341
|
return {};
|
|
3156
3342
|
}
|
|
3157
3343
|
}
|
|
3344
|
+
function buildActivationSurfaceContract(client) {
|
|
3345
|
+
const shared = {
|
|
3346
|
+
doctrine: "one_activation_engine_multiple_entry_points",
|
|
3347
|
+
engine: "create-snipara",
|
|
3348
|
+
firstSuccessState: "Hosted MCP connected, local workspace context seeded, and a First Work Brief ready for the next agent session.",
|
|
3349
|
+
mustNotDuplicate: [
|
|
3350
|
+
"Local source scan heuristics",
|
|
3351
|
+
"First Work Brief generation",
|
|
3352
|
+
"memory-candidate extraction",
|
|
3353
|
+
"Hosted MCP config contract"
|
|
3354
|
+
]
|
|
3355
|
+
};
|
|
3356
|
+
if (client === "cursor") {
|
|
3357
|
+
return {
|
|
3358
|
+
...shared,
|
|
3359
|
+
entryPoint: "Cursor extension or Cursor agent instructions call create-snipara",
|
|
3360
|
+
clientRole: "Lightweight editor surface: expose rules, skills, and the canonical bootstrap path; do not fork activation logic.",
|
|
3361
|
+
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."
|
|
3362
|
+
};
|
|
3363
|
+
}
|
|
3364
|
+
if (client === "vscode") {
|
|
3365
|
+
return {
|
|
3366
|
+
...shared,
|
|
3367
|
+
entryPoint: "VS Code extension command or create-snipara bootstrap",
|
|
3368
|
+
clientRole: "Native editor UX surface: provide SecretStorage, progress, panels, status, and Copilot handoff while keeping activation semantics aligned with create-snipara.",
|
|
3369
|
+
nextSurfaceAction: "In VS Code, run `Snipara: Activate Workspace` when the extension is installed, or keep using this generated pack when bootstrapping from the terminal."
|
|
3370
|
+
};
|
|
3371
|
+
}
|
|
3372
|
+
if (client === "claude-code") {
|
|
3373
|
+
return {
|
|
3374
|
+
...shared,
|
|
3375
|
+
entryPoint: "Claude Code plugin or create-snipara bootstrap",
|
|
3376
|
+
clientRole: "Agent-first surface: load Hosted MCP and project instructions, then use Companion only for explicit local continuity workflows.",
|
|
3377
|
+
nextSurfaceAction: "Start a new Claude Code session and validate Snipara tools before enabling hooks or managed workflows."
|
|
3378
|
+
};
|
|
3379
|
+
}
|
|
3380
|
+
return {
|
|
3381
|
+
...shared,
|
|
3382
|
+
entryPoint: `${getClientDisplayName(client)} setup generated by create-snipara`,
|
|
3383
|
+
clientRole: "MCP-compatible surface: consume the generated Hosted MCP reference and AGENTS.md rather than owning a separate activation model.",
|
|
3384
|
+
nextSurfaceAction: "Restart or reload the client, verify Snipara tools, then ask the first grounded project question from the generated First Work Brief."
|
|
3385
|
+
};
|
|
3386
|
+
}
|
|
3158
3387
|
function getClientGuidance(client) {
|
|
3159
3388
|
if (client === "claude-code") {
|
|
3160
3389
|
return [
|
|
@@ -3164,6 +3393,7 @@ function getClientGuidance(client) {
|
|
|
3164
3393
|
}
|
|
3165
3394
|
if (client === "cursor") {
|
|
3166
3395
|
return [
|
|
3396
|
+
"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.",
|
|
3167
3397
|
"Cursor reads the generated .mcp.json directly, so the hosted Snipara MCP surface is available after restart.",
|
|
3168
3398
|
"Use the companion CLI only for explicit upload, planning, chunk lookup, doctor, and task commit workflows outside the editor UI."
|
|
3169
3399
|
];
|
|
@@ -3199,6 +3429,7 @@ function getClientGuidance(client) {
|
|
|
3199
3429
|
}
|
|
3200
3430
|
if (client === "vscode") {
|
|
3201
3431
|
return [
|
|
3432
|
+
"VS Code can provide native activation UX, but create-snipara remains the canonical activation contract for generated files and local briefing semantics.",
|
|
3202
3433
|
"VS Code and Copilot-style clients should use Hosted MCP plus AGENTS.md for project workflow rules.",
|
|
3203
3434
|
"Use .snipara/templates/vscode-mcp-reference.json as the Snipara server reference when adding an MCP server."
|
|
3204
3435
|
];
|
|
@@ -3464,11 +3695,24 @@ function buildClientPackMarkdown(answers, commands, guidance) {
|
|
|
3464
3695
|
const bootstrapCommand = commands.find(
|
|
3465
3696
|
(command) => command.title === "Bootstrap local companion"
|
|
3466
3697
|
);
|
|
3698
|
+
const surfaceContract = buildActivationSurfaceContract(answers.aiClient);
|
|
3467
3699
|
return `# Snipara Pack: ${clientName}
|
|
3468
3700
|
|
|
3469
3701
|
This pack is the client-specific overlay for the generated Snipara project setup.
|
|
3470
3702
|
Use \`AGENTS.md\` as the shared source of agent behavior, then apply the client-specific files below.
|
|
3471
3703
|
|
|
3704
|
+
## Activation Contract
|
|
3705
|
+
|
|
3706
|
+
- Doctrine: one activation engine, multiple entry points
|
|
3707
|
+
- Canonical engine: \`${surfaceContract.engine}\`
|
|
3708
|
+
- Entry point: ${surfaceContract.entryPoint}
|
|
3709
|
+
- Client role: ${surfaceContract.clientRole}
|
|
3710
|
+
- First success state: ${surfaceContract.firstSuccessState}
|
|
3711
|
+
- Next surface action: ${surfaceContract.nextSurfaceAction}
|
|
3712
|
+
|
|
3713
|
+
The client-specific files in this pack should not reimplement local source scanning,
|
|
3714
|
+
First Work Brief generation, memory-candidate extraction, or Hosted MCP config semantics.
|
|
3715
|
+
|
|
3472
3716
|
## Hosted MCP
|
|
3473
3717
|
|
|
3474
3718
|
- Endpoint: \`${buildHostedMcpEndpoint(answers)}\`
|
|
@@ -3517,6 +3761,8 @@ async function createCompanionPack(answers) {
|
|
|
3517
3761
|
const readme = `# Snipara Companion Pack
|
|
3518
3762
|
|
|
3519
3763
|
This project uses Snipara as a hosted-first project intelligence layer with source-backed context, reviewed memory, and local companion workflow helpers.
|
|
3764
|
+
The activation doctrine is: one shared activation engine, multiple entry points.
|
|
3765
|
+
\`create-snipara\` is the canonical bootstrap; editor extensions and plugins should provide UI, rules, or handoff affordances without forking the activation engine.
|
|
3520
3766
|
|
|
3521
3767
|
## Install Profile
|
|
3522
3768
|
|
|
@@ -3546,6 +3792,18 @@ This project uses Snipara as a hosted-first project intelligence layer with sour
|
|
|
3546
3792
|
|
|
3547
3793
|
${guidance.map((line) => `- ${line}`).join("\n")}
|
|
3548
3794
|
|
|
3795
|
+
## Activation Continuity Loop
|
|
3796
|
+
|
|
3797
|
+
After the First Work Brief, use Companion when local continuity matters:
|
|
3798
|
+
|
|
3799
|
+
1. Start or resume with \`${COMPANION_NPX_COMMAND} session-bootstrap --include-session-context --max-context-tokens 1000\`.
|
|
3800
|
+
2. Refresh local source context with \`${COMPANION_NPX_COMMAND} source sync --json\` after meaningful doc or code movement.
|
|
3801
|
+
3. Before risky edits, use \`${COMPANION_NPX_COMMAND} code impact --changed-files <files> --diff-summary "<change>"\`.
|
|
3802
|
+
4. End durable work with \`${COMPANION_NPX_COMMAND} task-commit --summary "<what changed>" --files <files>\`.
|
|
3803
|
+
|
|
3804
|
+
Keep quick editor usage in the editor. Use Companion for explicit continuity, source refresh,
|
|
3805
|
+
workflow phase state, guards, impact checks, business-folder onboarding, and durable task memory.
|
|
3806
|
+
|
|
3549
3807
|
## Business Folder Onboarding
|
|
3550
3808
|
|
|
3551
3809
|
Use this when Claude, ChatGPT, Codex, or another LLM client has already materialized Drive, Notion, Gmail, or local business files into a folder.
|
|
@@ -4331,6 +4589,16 @@ function printActivationSummary(manifest) {
|
|
|
4331
4589
|
` Target: ${manifest.activationMetric.targetMinutes} minutes to a true, non-obvious own-repo answer.`
|
|
4332
4590
|
)
|
|
4333
4591
|
);
|
|
4592
|
+
console.log(
|
|
4593
|
+
chalk.dim(
|
|
4594
|
+
` Day-zero corpus: ${manifest.dayZeroCorpus.status} - ${manifest.dayZeroCorpus.detail}`
|
|
4595
|
+
)
|
|
4596
|
+
);
|
|
4597
|
+
console.log(chalk.bold("\nActivation surface:\n"));
|
|
4598
|
+
console.log(` Engine: ${manifest.surfaceContract.engine}`);
|
|
4599
|
+
console.log(` Entry point: ${manifest.surfaceContract.entryPoint}`);
|
|
4600
|
+
console.log(chalk.dim(` Role: ${manifest.surfaceContract.clientRole}`));
|
|
4601
|
+
console.log(chalk.dim(` Next: ${manifest.surfaceContract.nextSurfaceAction}`));
|
|
4334
4602
|
console.log(chalk.bold("\nAgent readiness:\n"));
|
|
4335
4603
|
console.log(` ${manifest.agentReadiness.summary}`);
|
|
4336
4604
|
for (const finding of manifest.agentReadiness.stalenessFindings.slice(0, 3)) {
|
package/package.json
CHANGED