Sign In

gspec

Package Overview
Dependencies
Maintainers
1
Versions
39
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

gspec - npm Package Compare versions

Comparing version
2.2.1
to
2.2.2
+30
-7
lib/build.js

@@ -54,3 +54,8 @@ // gspec build — deterministic orchestration runtime.

// can't spawn unbounded feature-writer agents. Drops are logged, not silent.
const MAX_FEATURES = 12;
// The ceiling is decoupled from concurrency: writers run at most
// FEATURE_WRITER_CONCURRENCY at a time (each is a real headless engine
// subprocess), so a large but legitimate breakdown gets all its PRDs without a
// thundering herd of simultaneous agents / API calls.
const MAX_FEATURES = 24;
const FEATURE_WRITER_CONCURRENCY = 5;

@@ -121,2 +126,19 @@ // The build stage graph (design §8). Foundation stages are skip-if-present.

// Map `fn` over `items` with at most `limit` calls in flight, preserving input
// order in the result. A worker pool (not fixed batches) so a slow item doesn't
// stall the ones behind it. Used to bound how many headless writer subprocesses
// the features stage spawns at once — see FEATURE_WRITER_CONCURRENCY.
async function mapLimit(items, limit, fn) {
const results = new Array(items.length);
let next = 0;
async function worker() {
while (next < items.length) {
const i = next++;
results[i] = await fn(items[i], i);
}
}
await Promise.all(Array.from({ length: Math.max(1, Math.min(limit, items.length)) }, worker));
return results;
}
// --- learnings capture (the learning loop's build channel) -----------------

@@ -497,7 +519,8 @@ //

log(chalk.dim(` decomposed into ${plan.length} feature(s): ${plan.map((f) => f.slug).join(', ')}`));
// File-disjoint slugs (dedup guarantees it) → fan out in parallel, like
// the research stage. The planner already resolved overlap and named
// dependencies, so each writer cross-links siblings by slug without
// needing to read a not-yet-written sibling file.
const runs = await Promise.all(plan.map((f) => {
// File-disjoint slugs (dedup guarantees it) → fan out, at most
// FEATURE_WRITER_CONCURRENCY writers in flight so a big breakdown doesn't
// spawn a thundering herd of headless agents. The planner already
// resolved overlap and named dependencies, so each writer cross-links
// siblings by slug without needing to read a not-yet-written sibling file.
const runs = await mapLimit(plan, FEATURE_WRITER_CONCURRENCY, (f) => {
const deps = f.dependencies.filter((d) => d !== f.slug);

@@ -512,3 +535,3 @@ const scope = [

return runAgent(stage.writer, stageBrief(stage, brief, scope), ctx);
}));
});
const bad = runs.findIndex((r) => r.code !== 0);

@@ -515,0 +538,0 @@ if (bad >= 0) return { status: 'failed', reason: `${stage.writer} ("${plan[bad].slug}") exited ${runs[bad].code}` };

+1
-1
{
"name": "gspec",
"version": "2.2.1",
"version": "2.2.2",
"description": "Install gspec specification commands for Claude Code, Cursor, and other AI tools",

@@ -5,0 +5,0 @@ "main": "bin/gspec.js",