getprismo 0.1.60 → 0.1.62
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.
|
@@ -187,6 +187,44 @@ module.exports = function createCloudSync(deps) {
|
|
|
187
187
|
};
|
|
188
188
|
}
|
|
189
189
|
|
|
190
|
+
// Read generated context-pack receipts so the dashboard can show each pack's
|
|
191
|
+
// provenance (included/excluded roots, git state, staleness). Receipts carry
|
|
192
|
+
// no source or prompts — only the trust-boundary metadata.
|
|
193
|
+
function readContextPackReceipts(root) {
|
|
194
|
+
const dir = path.join(root, ".prismo");
|
|
195
|
+
let names;
|
|
196
|
+
try {
|
|
197
|
+
names = fs.readdirSync(dir).filter((name) => name.endsWith(".receipt.json"));
|
|
198
|
+
} catch {
|
|
199
|
+
return [];
|
|
200
|
+
}
|
|
201
|
+
const packs = [];
|
|
202
|
+
for (const name of names.slice(0, 50)) {
|
|
203
|
+
try {
|
|
204
|
+
const r = JSON.parse(fs.readFileSync(path.join(dir, name), "utf8"));
|
|
205
|
+
if (!r || !r.pack_id) continue;
|
|
206
|
+
packs.push({
|
|
207
|
+
pack_id: r.pack_id,
|
|
208
|
+
pack_path: r.pack_path || null,
|
|
209
|
+
included_source_roots: Array.isArray(r.included_source_roots) ? r.included_source_roots : [],
|
|
210
|
+
excluded_roots: Array.isArray(r.excluded_roots) ? r.excluded_roots : [],
|
|
211
|
+
repo_ref: r.repo_ref || null,
|
|
212
|
+
target_agents: Array.isArray(r.target_agents) ? r.target_agents : [],
|
|
213
|
+
estimated_pack_tokens: typeof r.estimated_pack_tokens === "number" ? r.estimated_pack_tokens : null,
|
|
214
|
+
token_budget: typeof r.token_budget === "number" ? r.token_budget : null,
|
|
215
|
+
stale_if_older_than_ms: typeof r.stale_if_older_than_ms === "number" ? r.stale_if_older_than_ms : null,
|
|
216
|
+
source_globs_digest: r.source_globs_digest || null,
|
|
217
|
+
verify_command: r.verify_command || null,
|
|
218
|
+
prismo_version: r.prismo_version || null,
|
|
219
|
+
generated_at: r.generated_at || null,
|
|
220
|
+
});
|
|
221
|
+
} catch {
|
|
222
|
+
// skip an unreadable receipt
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return packs;
|
|
226
|
+
}
|
|
227
|
+
|
|
190
228
|
function buildSyncPayload(rootDir = process.cwd(), options = {}) {
|
|
191
229
|
const root = path.resolve(rootDir);
|
|
192
230
|
const allRepos = Boolean(options.allRepos);
|
|
@@ -269,6 +307,7 @@ module.exports = function createCloudSync(deps) {
|
|
|
269
307
|
} : null,
|
|
270
308
|
aggregate,
|
|
271
309
|
sessions,
|
|
310
|
+
contextPacks: readContextPackReceipts(root),
|
|
272
311
|
privacy: {
|
|
273
312
|
rawPrompts: false,
|
|
274
313
|
rawCode: false,
|
|
@@ -5,12 +5,13 @@ module.exports = function createContextOptimize(deps) {
|
|
|
5
5
|
fs,
|
|
6
6
|
path,
|
|
7
7
|
NPX_COMMAND,
|
|
8
|
+
PACKAGE_VERSION,
|
|
9
|
+
estimateTokens,
|
|
8
10
|
scanRepo,
|
|
9
11
|
safeReadJson,
|
|
10
12
|
readIfText,
|
|
11
13
|
formatBytes,
|
|
12
14
|
color,
|
|
13
|
-
writeGeneratedFile,
|
|
14
15
|
} = deps;
|
|
15
16
|
|
|
16
17
|
const {
|
|
@@ -127,10 +128,6 @@ function proseList(items, empty = "none detected") {
|
|
|
127
128
|
return items && items.length ? items.join(", ") : empty;
|
|
128
129
|
}
|
|
129
130
|
|
|
130
|
-
function estimateTokens(text) {
|
|
131
|
-
return Math.ceil(String(text || "").length / 4);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
131
|
function sha256(value) {
|
|
135
132
|
return `sha256:${crypto.createHash("sha256").update(String(value)).digest("hex")}`;
|
|
136
133
|
}
|
|
@@ -144,13 +141,45 @@ function gitValue(root, args) {
|
|
|
144
141
|
}
|
|
145
142
|
}
|
|
146
143
|
|
|
144
|
+
function workingTreeDirty(root) {
|
|
145
|
+
try {
|
|
146
|
+
const result = spawnSync("git", ["status", "--porcelain"], { cwd: root, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] });
|
|
147
|
+
if (result.status !== 0) return null;
|
|
148
|
+
return result.stdout.trim().length > 0;
|
|
149
|
+
} catch {
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
147
154
|
function repoRef(root) {
|
|
155
|
+
const branch = gitValue(root, ["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
156
|
+
const commit = gitValue(root, ["rev-parse", "--short=12", "HEAD"]);
|
|
157
|
+
// A pack derived from uncommitted files has a different staleness boundary
|
|
158
|
+
// than one derived from a clean commit, so record the working-tree state.
|
|
159
|
+
// null when this is not a git repo.
|
|
160
|
+
const inRepo = Boolean(branch || commit);
|
|
148
161
|
return {
|
|
149
|
-
branch
|
|
150
|
-
commit
|
|
162
|
+
branch,
|
|
163
|
+
commit,
|
|
164
|
+
working_tree_dirty: inRepo ? workingTreeDirty(root) : null,
|
|
151
165
|
};
|
|
152
166
|
}
|
|
153
167
|
|
|
168
|
+
// Directory roots that are intentionally kept out of context grounding (they
|
|
169
|
+
// map to the receipt's omitted_classes). Used to separate roots that actually
|
|
170
|
+
// grounded the pack from roots that were merely present and avoided.
|
|
171
|
+
const EXCLUDED_ROOT_DIRS = new Set([
|
|
172
|
+
"node_modules", "vendor", ".venv", "venv",
|
|
173
|
+
"dist", "build", "out", "target", ".next", ".nuxt", ".output", ".svelte-kit",
|
|
174
|
+
"coverage", ".nyc_output",
|
|
175
|
+
"logs", "log",
|
|
176
|
+
".cache", "__pycache__", ".git",
|
|
177
|
+
]);
|
|
178
|
+
|
|
179
|
+
function isExcludedRoot(root) {
|
|
180
|
+
return String(root || "").split("/").some((seg) => EXCLUDED_ROOT_DIRS.has(seg.toLowerCase()));
|
|
181
|
+
}
|
|
182
|
+
|
|
154
183
|
function isContextPackFile(name) {
|
|
155
184
|
return name === "architecture-summary.md" ||
|
|
156
185
|
name === "backend-summary.md" ||
|
|
@@ -199,8 +228,13 @@ function matchingSourceFiles(ctx, roots) {
|
|
|
199
228
|
function renderPackReceipt(ctx, name, contents) {
|
|
200
229
|
const packPath = `.prismo/${name}`;
|
|
201
230
|
const packId = name.replace(/\.md$/, "");
|
|
202
|
-
const
|
|
203
|
-
|
|
231
|
+
const candidateRoots = sourceRootsForPack(ctx, name);
|
|
232
|
+
// Separate roots that actually grounded the pack from roots that were present
|
|
233
|
+
// but deliberately kept out (build output, logs, vendored deps). Without this,
|
|
234
|
+
// a later reader could assume the pack was grounded in e.g. dist/ or logs/.
|
|
235
|
+
const includedSourceRoots = candidateRoots.filter((root) => !isExcludedRoot(root));
|
|
236
|
+
const excludedRoots = candidateRoots.filter((root) => isExcludedRoot(root));
|
|
237
|
+
const sourceFiles = matchingSourceFiles(ctx, includedSourceRoots)
|
|
204
238
|
.filter((file) => file.kind !== "binary")
|
|
205
239
|
.map((file) => ({
|
|
206
240
|
path: file.path,
|
|
@@ -215,13 +249,14 @@ function renderPackReceipt(ctx, name, contents) {
|
|
|
215
249
|
pack_path: packPath,
|
|
216
250
|
receipt_path: `.prismo/${packId}.receipt.json`,
|
|
217
251
|
generated_at: ctx.generatedAt,
|
|
218
|
-
prismo_version:
|
|
252
|
+
prismo_version: PACKAGE_VERSION,
|
|
219
253
|
repo_ref: repoRef(ctx.root),
|
|
220
254
|
target_agents: ["claude-code", "cursor", "codex", "mcp"],
|
|
221
|
-
|
|
255
|
+
included_source_roots: includedSourceRoots,
|
|
256
|
+
excluded_roots: excludedRoots,
|
|
222
257
|
source_globs_digest: sha256(JSON.stringify({
|
|
223
258
|
pack_id: packId,
|
|
224
|
-
source_roots:
|
|
259
|
+
source_roots: includedSourceRoots,
|
|
225
260
|
files: sourceFiles,
|
|
226
261
|
})),
|
|
227
262
|
omitted_classes: ["lockfiles", "build-output", "large-logs", "coverage", "dependency-vendor", "binary-media"],
|
package/lib/prismo-dev-scan.js
CHANGED
|
@@ -53,12 +53,13 @@ const {
|
|
|
53
53
|
fs,
|
|
54
54
|
path,
|
|
55
55
|
NPX_COMMAND,
|
|
56
|
+
PACKAGE_VERSION,
|
|
57
|
+
estimateTokens,
|
|
56
58
|
scanRepo: (...args) => scanRepo(...args),
|
|
57
59
|
safeReadJson,
|
|
58
60
|
readIfText,
|
|
59
61
|
formatBytes: (...args) => formatBytes(...args),
|
|
60
62
|
color,
|
|
61
|
-
writeGeneratedFile: (...args) => writeGeneratedFile(...args),
|
|
62
63
|
});
|
|
63
64
|
|
|
64
65
|
const {
|
package/package.json
CHANGED