agentsys 5.8.6 → 5.9.0
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/.claude-plugin/marketplace.json +13 -2
- package/.claude-plugin/plugin.json +1 -1
- package/AGENTS.md +1 -1
- package/CHANGELOG.md +6 -0
- package/README.md +2 -2
- package/lib/binary/version.js +1 -1
- package/lib/collectors/analyzer-queries.js +341 -0
- package/lib/collectors/documentation.js +1 -2
- package/lib/collectors/github.js +3 -5
- package/lib/collectors/index.js +12 -1
- package/lib/cross-platform/index.js +6 -5
- package/lib/enhance/cross-file-analyzer.js +2 -3
- package/lib/enhance/cross-file-patterns.js +2 -3
- package/lib/enhance/docs-patterns.js +4 -6
- package/lib/index.js +0 -2
- package/lib/package.json +0 -34
- package/lib/patterns/cli-enhancers.js +2 -6
- package/lib/patterns/pipeline.js +3 -7
- package/lib/patterns/slop-analyzers.js +1 -3
- package/lib/platform/detect-platform.js +1 -2
- package/lib/repo-intel/queries.js +186 -337
- package/lib/sources/policy-questions.js +3 -4
- package/lib/state/workflow-state.js +106 -173
- package/package.json +1 -1
- package/scripts/generate-docs.js +23 -11
- package/scripts/plugins.txt +1 -0
- package/site/content.json +3 -3
- package/site/index.html +5 -5
- package/site/ux-spec.md +7 -7
- package/lib/repo-intel/index.js +0 -21
|
@@ -116,216 +116,136 @@ function getTasksPath(projectPath = process.cwd()) {
|
|
|
116
116
|
return tasksPath;
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
+
/**
|
|
120
|
+
* Build the canonical default tasks schema.
|
|
121
|
+
*/
|
|
122
|
+
function defaultTasksSchema() {
|
|
123
|
+
return { active: null, tasks: [], _version: 0 };
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Normalize on-disk data to the canonical schema.
|
|
128
|
+
* Handles two legacy formats:
|
|
129
|
+
* - { active } only (pre-v5.8.4)
|
|
130
|
+
* - { version, tasks[] } (worktree-manager format)
|
|
131
|
+
*/
|
|
132
|
+
function normalizeTasksData(data) {
|
|
133
|
+
const out = Object.assign(defaultTasksSchema(), {});
|
|
134
|
+
// active field
|
|
135
|
+
if (Object.prototype.hasOwnProperty.call(data, 'active')) {
|
|
136
|
+
out.active = data.active;
|
|
137
|
+
}
|
|
138
|
+
// tasks array
|
|
139
|
+
if (Array.isArray(data.tasks)) {
|
|
140
|
+
out.tasks = data.tasks;
|
|
141
|
+
}
|
|
142
|
+
// _version
|
|
143
|
+
if (typeof data._version === 'number') {
|
|
144
|
+
out._version = data._version;
|
|
145
|
+
}
|
|
146
|
+
// _writerId (preserve if present)
|
|
147
|
+
if (typeof data._writerId === 'string') {
|
|
148
|
+
out._writerId = data._writerId;
|
|
149
|
+
}
|
|
150
|
+
return out;
|
|
151
|
+
}
|
|
152
|
+
|
|
119
153
|
/**
|
|
120
154
|
* Read tasks.json from main project.
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
* { active: null|Object, tasks: [], _version: number }
|
|
124
|
-
*
|
|
125
|
-
* - active: single active workflow entry (set by createFlow / cleared by completeWorkflow)
|
|
126
|
-
* - tasks: worktree claim registry (set by worktree-manager / cleared by ship or --abort)
|
|
127
|
-
* - _version: monotonic counter for optimistic locking (managed by writeTasks)
|
|
128
|
-
* - _writerId: per-write unique token used by updateTasks to detect concurrent wins
|
|
129
|
-
*
|
|
130
|
-
* Legacy formats are normalized on read — no migration script needed.
|
|
131
|
-
* Throws on corruption so callers can decide whether to abort or recover,
|
|
132
|
-
* rather than silently overwriting potentially recoverable data.
|
|
133
|
-
*
|
|
134
|
-
* @param {string} projectPath
|
|
135
|
-
* @returns {{ active: null|Object, tasks: Array, _version: number, _writerId?: string }}
|
|
136
|
-
* @throws {Error} If tasks.json exists but cannot be parsed
|
|
155
|
+
* Returns default schema when file does not exist.
|
|
156
|
+
* Throws on corrupted JSON to prevent silent data loss.
|
|
137
157
|
*/
|
|
138
158
|
function readTasks(projectPath = process.cwd()) {
|
|
139
159
|
const tasksPath = getTasksPath(projectPath);
|
|
140
160
|
if (!fs.existsSync(tasksPath)) {
|
|
141
|
-
return
|
|
161
|
+
return defaultTasksSchema();
|
|
142
162
|
}
|
|
143
|
-
const raw = fs.readFileSync(tasksPath, 'utf8');
|
|
144
163
|
let data;
|
|
145
164
|
try {
|
|
146
|
-
data = JSON.parse(
|
|
165
|
+
data = JSON.parse(fs.readFileSync(tasksPath, 'utf8'));
|
|
147
166
|
} catch (e) {
|
|
148
|
-
throw new Error(`
|
|
167
|
+
throw new Error(`Corrupted tasks.json at ${tasksPath}: ${e.message}`);
|
|
149
168
|
}
|
|
150
|
-
|
|
151
|
-
return {
|
|
152
|
-
active: Object.prototype.hasOwnProperty.call(data, 'active') ? data.active : null,
|
|
153
|
-
tasks: Array.isArray(data.tasks) ? data.tasks : [],
|
|
154
|
-
_version: typeof data._version === 'number' ? data._version : 0,
|
|
155
|
-
_writerId: typeof data._writerId === 'string' ? data._writerId : undefined
|
|
156
|
-
};
|
|
169
|
+
return normalizeTasksData(data);
|
|
157
170
|
}
|
|
158
171
|
|
|
159
172
|
/**
|
|
160
|
-
* Write tasks.json
|
|
161
|
-
* Increments _version and stamps
|
|
162
|
-
*
|
|
163
|
-
* Both fields are used by updateTasks to verify it was the winning writer:
|
|
164
|
-
* if two processes both read _version N, both write _version N+1 (last
|
|
165
|
-
* renameSync wins), the loser re-reads and finds a _writerId that does not
|
|
166
|
-
* match its own — it knows it lost and retries.
|
|
167
|
-
*
|
|
168
|
-
* @returns {string} The _writerId stamped into this write
|
|
173
|
+
* Write tasks.json to main project.
|
|
174
|
+
* Increments _version and stamps _writerId.
|
|
175
|
+
* Returns the writerId that was stamped (string).
|
|
169
176
|
*/
|
|
170
177
|
function writeTasks(tasks, projectPath = process.cwd()) {
|
|
171
178
|
ensureStateDir(projectPath);
|
|
172
|
-
const copy = structuredClone(tasks);
|
|
173
|
-
copy._version = (copy._version || 0) + 1;
|
|
174
|
-
copy._writerId = crypto.randomBytes(8).toString('hex');
|
|
175
179
|
const tasksPath = getTasksPath(projectPath);
|
|
176
|
-
|
|
177
|
-
|
|
180
|
+
const writerId = crypto.randomBytes(8).toString('hex');
|
|
181
|
+
const toWrite = Object.assign({}, tasks, {
|
|
182
|
+
_version: (tasks._version || 0) + 1,
|
|
183
|
+
_writerId: writerId
|
|
184
|
+
});
|
|
185
|
+
writeJsonAtomic(tasksPath, toWrite);
|
|
186
|
+
return writerId;
|
|
178
187
|
}
|
|
179
188
|
|
|
180
189
|
/**
|
|
181
190
|
* Apply a mutation to tasks.json with optimistic locking.
|
|
191
|
+
* Retries up to 5 times on concurrent-writer conflict.
|
|
192
|
+
* Returns true on success, false if tasks.json is corrupted.
|
|
182
193
|
*
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
*
|
|
186
|
-
* 3. Stamp a unique writerId, write atomically (increments _version)
|
|
187
|
-
* 4. Re-read: if _version === initialVersion + 1 AND _writerId matches → we won
|
|
188
|
-
* 5. Otherwise another writer raced us → back off with jitter, retry
|
|
189
|
-
*
|
|
190
|
-
* @param {function(Object): Object} mutatorFn - Pure function that receives a
|
|
191
|
-
* deep clone of current tasks state and returns the desired new state.
|
|
192
|
-
* Must not have side effects; may be called multiple times on retry.
|
|
193
|
-
* @param {string} projectPath
|
|
194
|
-
* @returns {boolean} true on success, false after MAX_RETRIES exhausted or on corruption
|
|
194
|
+
* @param {function(Object): Object} mutatorFn - Receives current tasks, must return updated tasks.
|
|
195
|
+
* @param {string} [projectPath]
|
|
196
|
+
* @returns {boolean}
|
|
195
197
|
*/
|
|
196
198
|
function updateTasks(mutatorFn, projectPath = process.cwd()) {
|
|
197
199
|
const MAX_RETRIES = 5;
|
|
198
|
-
|
|
199
|
-
let current;
|
|
200
|
-
try {
|
|
201
|
-
current = readTasks(projectPath);
|
|
202
|
-
} catch (e) {
|
|
203
|
-
console.error(`[ERROR] updateTasks: cannot read tasks.json — ${e.message}`);
|
|
204
|
-
return false;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
200
|
for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
let updated;
|
|
201
|
+
let current;
|
|
211
202
|
try {
|
|
212
|
-
|
|
203
|
+
current = readTasks(projectPath);
|
|
213
204
|
} catch (e) {
|
|
214
|
-
|
|
205
|
+
// Corrupted — do not overwrite
|
|
215
206
|
return false;
|
|
216
207
|
}
|
|
217
|
-
|
|
218
|
-
// Skip write if mutatorFn made no changes — avoids spurious version bumps
|
|
219
|
-
if (JSON.stringify(updated) === JSON.stringify(current)) {
|
|
220
|
-
return true;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// Carry forward the pre-write version so writeTasks increments it by exactly 1
|
|
224
|
-
updated._version = initialVersion;
|
|
225
|
-
|
|
208
|
+
const updated = mutatorFn(Object.assign({}, current));
|
|
226
209
|
const writerId = writeTasks(updated, projectPath);
|
|
227
|
-
|
|
228
|
-
// Verify we won: version must be exactly initialVersion + 1 AND writerId must match ours.
|
|
229
|
-
// If another process also wrote _version: initialVersion + 1, only one writerId survives.
|
|
210
|
+
// Verify our write won (optimistic lock check)
|
|
230
211
|
let afterWrite;
|
|
231
212
|
try {
|
|
232
213
|
afterWrite = readTasks(projectPath);
|
|
233
214
|
} catch (e) {
|
|
234
|
-
console.error(`[ERROR] updateTasks: tasks.json corrupted after write on attempt ${attempt + 1}: ${e.message}`);
|
|
235
215
|
return false;
|
|
236
216
|
}
|
|
237
|
-
|
|
238
|
-
if (afterWrite._version === initialVersion + 1 && afterWrite._writerId === writerId) {
|
|
217
|
+
if (afterWrite._writerId === writerId) {
|
|
239
218
|
return true;
|
|
240
219
|
}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
sleepForRetry(delay);
|
|
246
|
-
try {
|
|
247
|
-
current = readTasks(projectPath);
|
|
248
|
-
} catch (e) {
|
|
249
|
-
console.error(`[ERROR] updateTasks: tasks.json corrupted during retry ${attempt + 1}: ${e.message}`);
|
|
250
|
-
return false;
|
|
251
|
-
}
|
|
252
|
-
}
|
|
220
|
+
// Another writer won — retry with jitter
|
|
221
|
+
const jitter = Math.floor(Math.random() * 20);
|
|
222
|
+
const start = Date.now();
|
|
223
|
+
while (Date.now() - start < jitter) { /* busy-wait for short jitter */ }
|
|
253
224
|
}
|
|
254
|
-
|
|
255
|
-
const tasksPath = getTasksPath(projectPath);
|
|
256
|
-
let lastVersion = '(unreadable)';
|
|
257
|
-
try { lastVersion = readTasks(projectPath)._version; } catch {}
|
|
258
|
-
|
|
259
|
-
// Final fallback: if a concurrent writer happened to apply the exact same
|
|
260
|
-
// mutation (idempotent operations like releaseTask on an already-absent entry),
|
|
261
|
-
// treat the outcome as a success rather than reporting a spurious failure.
|
|
262
|
-
let latest;
|
|
263
|
-
try { latest = readTasks(projectPath); } catch {}
|
|
264
|
-
if (latest) {
|
|
265
|
-
// Re-run the mutator on what's on disk; if the result is identical to
|
|
266
|
-
// what's already there, our desired state is already achieved.
|
|
267
|
-
try {
|
|
268
|
-
const wouldBe = mutatorFn(structuredClone(latest));
|
|
269
|
-
// Normalize _version/_writerId before comparing content
|
|
270
|
-
wouldBe._version = latest._version;
|
|
271
|
-
wouldBe._writerId = latest._writerId;
|
|
272
|
-
if (JSON.stringify(wouldBe) === JSON.stringify(latest)) {
|
|
273
|
-
return true;
|
|
274
|
-
}
|
|
275
|
-
} catch {}
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
console.error(
|
|
279
|
-
`[ERROR] updateTasks: all ${MAX_RETRIES} attempts failed due to concurrent writers on ${tasksPath}. ` +
|
|
280
|
-
`Another agent process is modifying the registry simultaneously. ` +
|
|
281
|
-
`Last known _version: ${lastVersion}. ` +
|
|
282
|
-
`Suggested recovery: wait for the competing process to finish, then retry the operation.`
|
|
283
|
-
);
|
|
284
225
|
return false;
|
|
285
226
|
}
|
|
286
227
|
|
|
287
228
|
/**
|
|
288
|
-
*
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
return updateTasks(tasks => {
|
|
292
|
-
tasks.active = { ...task, startedAt: new Date().toISOString() };
|
|
293
|
-
return tasks;
|
|
294
|
-
}, projectPath);
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
/**
|
|
298
|
-
* Clear active task (uses optimistic locking)
|
|
299
|
-
*/
|
|
300
|
-
function clearActiveTask(projectPath = process.cwd()) {
|
|
301
|
-
return updateTasks(tasks => {
|
|
302
|
-
tasks.active = null;
|
|
303
|
-
return tasks;
|
|
304
|
-
}, projectPath);
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
/**
|
|
308
|
-
* Claim a task in the registry (uses optimistic locking).
|
|
309
|
-
* Used by worktree-manager; replaces the raw fs.writeFileSync inline in agent prompts.
|
|
229
|
+
* Claim (upsert) a task entry in tasks[].
|
|
230
|
+
* Entry must have an `id` field.
|
|
231
|
+
* Returns false if entry.id is missing.
|
|
310
232
|
*
|
|
311
|
-
* @param {
|
|
312
|
-
* @param {string} projectPath
|
|
233
|
+
* @param {{ id: string, [key: string]: * }} entry
|
|
234
|
+
* @param {string} [projectPath]
|
|
235
|
+
* @returns {boolean}
|
|
313
236
|
*/
|
|
314
237
|
function claimTask(entry, projectPath = process.cwd()) {
|
|
315
|
-
if (!entry ||
|
|
316
|
-
console.error('[ERROR] claimTask: entry.id is required');
|
|
238
|
+
if (!entry || typeof entry.id !== 'string' || entry.id.length === 0) {
|
|
317
239
|
return false;
|
|
318
240
|
}
|
|
319
241
|
return updateTasks(tasks => {
|
|
320
|
-
const
|
|
321
|
-
const record = {
|
|
322
|
-
...entry,
|
|
242
|
+
const existing = tasks.tasks.findIndex(t => t.id === entry.id);
|
|
243
|
+
const record = Object.assign({}, entry, {
|
|
323
244
|
status: 'claimed',
|
|
324
|
-
claimedAt: entry.claimedAt || new Date().toISOString(),
|
|
325
245
|
lastActivityAt: new Date().toISOString()
|
|
326
|
-
};
|
|
327
|
-
if (
|
|
328
|
-
tasks.tasks[
|
|
246
|
+
});
|
|
247
|
+
if (existing >= 0) {
|
|
248
|
+
tasks.tasks[existing] = record;
|
|
329
249
|
} else {
|
|
330
250
|
tasks.tasks.push(record);
|
|
331
251
|
}
|
|
@@ -334,31 +254,44 @@ function claimTask(entry, projectPath = process.cwd()) {
|
|
|
334
254
|
}
|
|
335
255
|
|
|
336
256
|
/**
|
|
337
|
-
* Release a
|
|
338
|
-
*
|
|
257
|
+
* Release (remove) a task from tasks[] by id.
|
|
258
|
+
* Idempotent — returns true even if task was not found.
|
|
339
259
|
*
|
|
340
260
|
* @param {string} taskId
|
|
341
|
-
* @param {string} projectPath
|
|
261
|
+
* @param {string} [projectPath]
|
|
262
|
+
* @returns {boolean}
|
|
342
263
|
*/
|
|
343
264
|
function releaseTask(taskId, projectPath = process.cwd()) {
|
|
344
|
-
if (!taskId) {
|
|
345
|
-
console.error('[ERROR] releaseTask: taskId is required');
|
|
346
|
-
return false;
|
|
347
|
-
}
|
|
348
265
|
return updateTasks(tasks => {
|
|
349
|
-
const before = tasks.tasks.length;
|
|
350
266
|
tasks.tasks = tasks.tasks.filter(t => t.id !== taskId);
|
|
351
|
-
if (tasks.tasks.length === before) {
|
|
352
|
-
// Not found — that's fine, idempotent
|
|
353
|
-
console.error(`[WARN] releaseTask: task ${taskId} was not found in tasks.json registry. It may have already been released or never claimed.`);
|
|
354
|
-
}
|
|
355
267
|
return tasks;
|
|
356
268
|
}, projectPath);
|
|
357
269
|
}
|
|
358
270
|
|
|
359
271
|
/**
|
|
360
|
-
*
|
|
361
|
-
|
|
272
|
+
* Set active task in main project
|
|
273
|
+
*/
|
|
274
|
+
function setActiveTask(task, projectPath = process.cwd()) {
|
|
275
|
+
const tasks = readTasks(projectPath);
|
|
276
|
+
tasks.active = {
|
|
277
|
+
...task,
|
|
278
|
+
startedAt: new Date().toISOString()
|
|
279
|
+
};
|
|
280
|
+
return writeTasks(tasks, projectPath);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Clear active task
|
|
285
|
+
*/
|
|
286
|
+
function clearActiveTask(projectPath = process.cwd()) {
|
|
287
|
+
const tasks = readTasks(projectPath);
|
|
288
|
+
tasks.active = null;
|
|
289
|
+
return writeTasks(tasks, projectPath);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Check if there's an active task
|
|
294
|
+
* Uses != null to catch both null and undefined (legacy format safety)
|
|
362
295
|
*/
|
|
363
296
|
function hasActiveTask(projectPath = process.cwd()) {
|
|
364
297
|
const tasks = readTasks(projectPath);
|
|
@@ -735,10 +668,10 @@ module.exports = {
|
|
|
735
668
|
readTasks,
|
|
736
669
|
writeTasks,
|
|
737
670
|
updateTasks,
|
|
738
|
-
setActiveTask,
|
|
739
|
-
clearActiveTask,
|
|
740
671
|
claimTask,
|
|
741
672
|
releaseTask,
|
|
673
|
+
setActiveTask,
|
|
674
|
+
clearActiveTask,
|
|
742
675
|
hasActiveTask,
|
|
743
676
|
|
|
744
677
|
// Flow (worktree)
|
package/package.json
CHANGED
package/scripts/generate-docs.js
CHANGED
|
@@ -373,20 +373,31 @@ function generateAgentNavTable(agents, plugins) {
|
|
|
373
373
|
|
|
374
374
|
/**
|
|
375
375
|
* Generate the agents count summary line for docs/reference/AGENTS.md.
|
|
376
|
+
*
|
|
377
|
+
* Uses static fallbacks when local discovery returns nothing — the agentsys
|
|
378
|
+
* monorepo no longer contains plugins/, so discovery is empty in CI. Static
|
|
379
|
+
* counts are derived from STATIC_PLUGIN_AGENT_COUNTS so they stay in sync as
|
|
380
|
+
* plugins are added.
|
|
376
381
|
*/
|
|
377
382
|
function generateAgentCounts(agents, plugins) {
|
|
378
|
-
const
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
383
|
+
const totalAgents = agents.length > 0
|
|
384
|
+
? agents.length + ROLE_BASED_AGENT_COUNT
|
|
385
|
+
: STATIC_AGENT_COUNT;
|
|
386
|
+
const totalPlugins = plugins.length > 0 ? plugins.length : STATIC_PLUGIN_COUNT;
|
|
387
|
+
|
|
388
|
+
let pluginsWithAgentsCount;
|
|
389
|
+
if (agents.length > 0) {
|
|
390
|
+
const pluginsWithAgents = new Set(agents.map(a => a.plugin));
|
|
391
|
+
pluginsWithAgents.add('audit-project'); // role-based
|
|
392
|
+
pluginsWithAgentsCount = pluginsWithAgents.size;
|
|
393
|
+
} else {
|
|
394
|
+
// Static fallback: file-based plugins (count > 0 in static map) plus
|
|
395
|
+
// audit-project (role-based, count is 0 in the map but still has agents).
|
|
396
|
+
const fileBasedPluginsWithAgents = Object.values(STATIC_PLUGIN_AGENT_COUNTS).filter(c => c > 0).length;
|
|
397
|
+
pluginsWithAgentsCount = fileBasedPluginsWithAgents + 1;
|
|
385
398
|
}
|
|
386
|
-
pluginsWithAgents.add('audit-project'); // role-based
|
|
387
|
-
const pluginCount = pluginsWithAgents.size;
|
|
388
399
|
|
|
389
|
-
return `**TL;DR:** ${totalAgents} agents across ${
|
|
400
|
+
return `**TL;DR:** ${totalAgents} agents across ${totalPlugins} plugins (${pluginsWithAgentsCount} have agents). opus for reasoning, sonnet for patterns, haiku for execution. Each agent does one thing well. <!-- AGENT_COUNT_TOTAL: ${totalAgents} -->`;
|
|
390
401
|
}
|
|
391
402
|
|
|
392
403
|
// ---------------------------------------------------------------------------
|
|
@@ -418,7 +429,8 @@ const STATIC_PLUGIN_AGENT_COUNTS = {
|
|
|
418
429
|
'web-ctl': 1,
|
|
419
430
|
'skillers': 2,
|
|
420
431
|
'onboard': 1,
|
|
421
|
-
'can-i-help': 1
|
|
432
|
+
'can-i-help': 1,
|
|
433
|
+
'zig-lsp': 0
|
|
422
434
|
};
|
|
423
435
|
const STATIC_PLUGIN_COUNT = Object.keys(STATIC_PLUGIN_AGENT_COUNTS).length;
|
|
424
436
|
const STATIC_FILE_BASED_AGENT_COUNT = Object.values(STATIC_PLUGIN_AGENT_COUNTS).reduce((sum, count) => sum + count, 0);
|
package/scripts/plugins.txt
CHANGED
package/site/content.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"meta": {
|
|
3
3
|
"title": "agentsys",
|
|
4
|
-
"description": "A modular runtime and orchestration system for AI agents.
|
|
4
|
+
"description": "A modular runtime and orchestration system for AI agents. 20 plugins, 49 agents, 41 skills - structured pipelines for Claude Code, OpenCode, Codex CLI, Cursor, and Kiro.",
|
|
5
5
|
"url": "https://agent-sh.github.io/agentsys",
|
|
6
6
|
"repo": "https://github.com/agent-sh/agentsys",
|
|
7
7
|
"npm": "https://www.npmjs.com/package/agentsys",
|
|
8
|
-
"version": "5.
|
|
8
|
+
"version": "5.9.0",
|
|
9
9
|
"author": "Avi Fenesh",
|
|
10
10
|
"author_url": "https://github.com/avifenesh"
|
|
11
11
|
},
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
},
|
|
24
24
|
"stats": [
|
|
25
25
|
{
|
|
26
|
-
"value": "
|
|
26
|
+
"value": "20",
|
|
27
27
|
"label": "Plugins",
|
|
28
28
|
"suffix": ""
|
|
29
29
|
},
|
package/site/index.html
CHANGED
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
6
|
<title>AgentSys - Agent Runtime & Orchestration System</title>
|
|
7
|
-
<meta name="description" content="A modular runtime and orchestration system for AI agents.
|
|
7
|
+
<meta name="description" content="A modular runtime and orchestration system for AI agents. 20 plugins, 49 agents, 41 skills - structured pipelines for Claude Code, OpenCode, Codex CLI, Cursor, and Kiro.">
|
|
8
8
|
<meta name="theme-color" content="#09090b">
|
|
9
9
|
|
|
10
10
|
<!-- Open Graph -->
|
|
11
11
|
<meta property="og:title" content="AgentSys">
|
|
12
|
-
<meta property="og:description" content="A modular runtime and orchestration system for AI agents.
|
|
12
|
+
<meta property="og:description" content="A modular runtime and orchestration system for AI agents. 20 plugins, 49 agents, 41 skills.">
|
|
13
13
|
<meta property="og:image" content="https://agent-sh.github.io/agentsys/assets/logo.png">
|
|
14
14
|
<meta property="og:url" content="https://agent-sh.github.io/agentsys/">
|
|
15
15
|
<meta property="og:type" content="website">
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
<!-- Twitter Card -->
|
|
18
18
|
<meta name="twitter:card" content="summary_large_image">
|
|
19
19
|
<meta name="twitter:title" content="AgentSys">
|
|
20
|
-
<meta name="twitter:description" content="AI workflow automation.
|
|
20
|
+
<meta name="twitter:description" content="AI workflow automation. 20 plugins, 49 agents, 41 skills.">
|
|
21
21
|
<meta name="twitter:image" content="https://agent-sh.github.io/agentsys/assets/logo.png">
|
|
22
22
|
|
|
23
23
|
<!-- Content Security Policy -->
|
|
@@ -107,7 +107,7 @@
|
|
|
107
107
|
<div class="hero__inner">
|
|
108
108
|
<div class="hero__content">
|
|
109
109
|
<div class="hero__badge anim-fade-in" data-delay="100">
|
|
110
|
-
|
|
110
|
+
20 plugins · 49 agents · 41 skills
|
|
111
111
|
</div>
|
|
112
112
|
<h1 class="hero__title anim-fade-up" id="hero-title" data-delay="200">
|
|
113
113
|
A modular <span class="text-gradient">runtime and orchestration system</span><br>
|
|
@@ -156,7 +156,7 @@
|
|
|
156
156
|
<section class="stats" id="stats" aria-label="Project statistics">
|
|
157
157
|
<div class="stats__inner">
|
|
158
158
|
<div class="stats__item">
|
|
159
|
-
<span class="stats__number" aria-live="polite" data-target="
|
|
159
|
+
<span class="stats__number" aria-live="polite" data-target="20">0</span>
|
|
160
160
|
<span class="stats__label">Plugins</span>
|
|
161
161
|
</div>
|
|
162
162
|
<div class="stats__item">
|
package/site/ux-spec.md
CHANGED
|
@@ -94,7 +94,7 @@ Scroll order with rationale for each section. All sections are full-width, alter
|
|
|
94
94
|
- **Single column on mobile:** Text above, terminal below. Stack with 48px gap.
|
|
95
95
|
|
|
96
96
|
### Left Column Content
|
|
97
|
-
1. **Badge** (top, above title): Small pill showing version or "
|
|
97
|
+
1. **Badge** (top, above title): Small pill showing version or "20 plugins . 49 agents . 41 skills"
|
|
98
98
|
- Background: `rgba(99, 102, 241, 0.12)`, border: `1px solid rgba(99, 102, 241, 0.25)`, border-radius: 9999px
|
|
99
99
|
- Font: 13px, font-weight 500, primary accent color
|
|
100
100
|
- Padding: 4px 14px
|
|
@@ -104,7 +104,7 @@ Scroll order with rationale for each section. All sections are full-width, alter
|
|
|
104
104
|
- Color: white
|
|
105
105
|
- "entire dev workflow" portion highlighted with a subtle gradient text (primary-to-secondary accent via `background-clip: text`)
|
|
106
106
|
|
|
107
|
-
3. **Subtitle:** "
|
|
107
|
+
3. **Subtitle:** "20 plugins, 49 agents, 41 skills. From task selection to merged PR. Works with Claude Code, OpenCode, Codex CLI, Cursor, and Kiro."
|
|
108
108
|
- Font: 18px on desktop, 16px on mobile, font-weight 400, line-height 1.6
|
|
109
109
|
- Color: `rgba(255, 255, 255, 0.6)`
|
|
110
110
|
- Max-width: 520px
|
|
@@ -226,9 +226,9 @@ Done. Task to merged PR in 12 minutes.
|
|
|
226
226
|
### Stats (left to right)
|
|
227
227
|
| Stat | Value | Label |
|
|
228
228
|
|------|-------|-------|
|
|
229
|
-
| 1 |
|
|
229
|
+
| 1 | 20 | Plugins |
|
|
230
230
|
| 2 | 49 | Agents |
|
|
231
|
-
| 3 |
|
|
231
|
+
| 3 | 41 | Skills |
|
|
232
232
|
| 4 | 3,507 | Tests Passing |
|
|
233
233
|
|
|
234
234
|
### Styling
|
|
@@ -650,13 +650,13 @@ This disables:
|
|
|
650
650
|
### Head Content
|
|
651
651
|
```html
|
|
652
652
|
<title>AgentSys - Agent Runtime & Orchestration System</title>
|
|
653
|
-
<meta name="description" content="A modular runtime and orchestration system for AI agents.
|
|
653
|
+
<meta name="description" content="A modular runtime and orchestration system for AI agents. 20 plugins, 49 agents, 41 skills - structured pipelines for Claude Code, OpenCode, Codex CLI, Cursor, and Kiro.">
|
|
654
654
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
655
655
|
<meta name="theme-color" content="#0a0a0f">
|
|
656
656
|
|
|
657
657
|
<!-- Open Graph -->
|
|
658
658
|
<meta property="og:title" content="AgentSys">
|
|
659
|
-
<meta property="og:description" content="AI workflow automation.
|
|
659
|
+
<meta property="og:description" content="AI workflow automation. 20 plugins, 49 agents, 41 skills. Task to merged PR.">
|
|
660
660
|
<meta property="og:image" content="https://agent-sh.github.io/agentsys/assets/og-image.png">
|
|
661
661
|
<meta property="og:url" content="https://agent-sh.github.io/agentsys/">
|
|
662
662
|
<meta property="og:type" content="website">
|
|
@@ -664,7 +664,7 @@ This disables:
|
|
|
664
664
|
<!-- Twitter Card -->
|
|
665
665
|
<meta name="twitter:card" content="summary_large_image">
|
|
666
666
|
<meta name="twitter:title" content="AgentSys">
|
|
667
|
-
<meta name="twitter:description" content="AI workflow automation.
|
|
667
|
+
<meta name="twitter:description" content="AI workflow automation. 20 plugins, 49 agents, 41 skills.">
|
|
668
668
|
<meta name="twitter:image" content="https://agent-sh.github.io/agentsys/assets/og-image.png">
|
|
669
669
|
```
|
|
670
670
|
|
package/lib/repo-intel/index.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Repo intel module - typed wrappers over agent-analyzer's repo-intel
|
|
3
|
-
* subcommands. Consumers can import via:
|
|
4
|
-
*
|
|
5
|
-
* const { repoIntel } = require('@agentsys/lib');
|
|
6
|
-
* const hot = repoIntel.queries.hotspots(cwd, { limit: 20 });
|
|
7
|
-
* const communities = repoIntel.queries.communities(cwd);
|
|
8
|
-
*
|
|
9
|
-
* The Rust binary is downloaded lazily on first call by lib/binary; this
|
|
10
|
-
* module just constructs the right argv and parses the JSON output.
|
|
11
|
-
*
|
|
12
|
-
* @module lib/repo-intel
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
'use strict';
|
|
16
|
-
|
|
17
|
-
const queries = require('./queries');
|
|
18
|
-
|
|
19
|
-
module.exports = {
|
|
20
|
-
queries,
|
|
21
|
-
};
|