@a-company/paradigm 3.5.0 → 3.7.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/dist/assessment-loader-T4GPBHLB.js +24 -0
- package/dist/{chunk-CRICL4FQ.js → chunk-ADOBV4PH.js} +385 -2
- package/dist/{chunk-IRVA7NKV.js → chunk-BC6XKMUA.js} +2 -0
- package/dist/chunk-CSD7IHSN.js +152 -0
- package/dist/chunk-DSXS42FY.js +283 -0
- package/dist/{chunk-2E2RTBSM.js → chunk-GY5KO3YZ.js} +147 -2
- package/dist/{chunk-4G54C4VM.js → chunk-YT3QWWKP.js} +15 -39
- package/dist/{dist-YP2CO4TG.js → dist-OLFOTUHS.js} +4 -2
- package/dist/{habits-CHP4EW5H.js → habits-ZJBAL4HD.js} +2 -2
- package/dist/index.js +31 -31
- package/dist/mcp.js +651 -23
- package/dist/{plugin-update-checker-EWT7YMDF.js → plugin-update-checker-TWBWUSAG.js} +2 -1
- package/dist/{sentinel-ZTL224IG.js → sentinel-KDIGZWKT.js} +1 -1
- package/dist/{server-MZBYDXJY.js → server-NN7WDAZJ.js} +222 -2
- package/dist/{shift-KDVYB6CR.js → shift-KJWSJLWN.js} +1 -1
- package/dist/task-loader-GUX4KS6N.js +20 -0
- package/dist/{triage-PXMU3RWV.js → triage-B5W6GZLT.js} +2 -2
- package/dist/university-content/courses/para-501.json +110 -0
- package/dist/university-content/plsat/v3.0.json +87 -3
- package/package.json +1 -1
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
closeArc,
|
|
4
|
+
createArc,
|
|
5
|
+
loadArc,
|
|
6
|
+
loadArcs,
|
|
7
|
+
loadEntries,
|
|
8
|
+
loadEntry,
|
|
9
|
+
rebuildAssessmentIndex,
|
|
10
|
+
recordEntry,
|
|
11
|
+
searchEntries
|
|
12
|
+
} from "./chunk-DSXS42FY.js";
|
|
13
|
+
import "./chunk-MO4EEYFW.js";
|
|
14
|
+
export {
|
|
15
|
+
closeArc,
|
|
16
|
+
createArc,
|
|
17
|
+
loadArc,
|
|
18
|
+
loadArcs,
|
|
19
|
+
loadEntries,
|
|
20
|
+
loadEntry,
|
|
21
|
+
rebuildAssessmentIndex,
|
|
22
|
+
recordEntry,
|
|
23
|
+
searchEntries
|
|
24
|
+
};
|
|
@@ -2168,13 +2168,13 @@ function v4(options, buf, offset) {
|
|
|
2168
2168
|
}
|
|
2169
2169
|
var v4_default = v4;
|
|
2170
2170
|
|
|
2171
|
-
// ../sentinel/dist/chunk-
|
|
2171
|
+
// ../sentinel/dist/chunk-NTX74ZPM.js
|
|
2172
2172
|
var import_sql = __toESM(require_sql_wasm(), 1);
|
|
2173
2173
|
import * as path from "path";
|
|
2174
2174
|
import * as fs from "fs";
|
|
2175
2175
|
import * as fs2 from "fs";
|
|
2176
2176
|
import * as path2 from "path";
|
|
2177
|
-
var SCHEMA_VERSION =
|
|
2177
|
+
var SCHEMA_VERSION = 5;
|
|
2178
2178
|
var DEFAULT_CONFIDENCE = {
|
|
2179
2179
|
score: 50,
|
|
2180
2180
|
timesMatched: 0,
|
|
@@ -2605,6 +2605,54 @@ var SentinelStorage = class {
|
|
|
2605
2605
|
this.db.run(
|
|
2606
2606
|
"INSERT OR REPLACE INTO metadata (key, value) VALUES ('schema_version', '4')"
|
|
2607
2607
|
);
|
|
2608
|
+
currentVersion = 4;
|
|
2609
|
+
}
|
|
2610
|
+
if (currentVersion < 5) {
|
|
2611
|
+
try {
|
|
2612
|
+
this.db.run(`
|
|
2613
|
+
CREATE TABLE IF NOT EXISTS schemas (
|
|
2614
|
+
id TEXT PRIMARY KEY,
|
|
2615
|
+
version TEXT NOT NULL,
|
|
2616
|
+
name TEXT NOT NULL,
|
|
2617
|
+
description TEXT,
|
|
2618
|
+
scope_json TEXT NOT NULL,
|
|
2619
|
+
event_types_json TEXT NOT NULL,
|
|
2620
|
+
causality_json TEXT,
|
|
2621
|
+
visualization_json TEXT,
|
|
2622
|
+
tags_json TEXT DEFAULT '[]',
|
|
2623
|
+
registered_at TEXT NOT NULL,
|
|
2624
|
+
updated_at TEXT NOT NULL
|
|
2625
|
+
);
|
|
2626
|
+
|
|
2627
|
+
CREATE TABLE IF NOT EXISTS events (
|
|
2628
|
+
id TEXT PRIMARY KEY,
|
|
2629
|
+
schema_id TEXT NOT NULL,
|
|
2630
|
+
event_type TEXT NOT NULL,
|
|
2631
|
+
category TEXT NOT NULL,
|
|
2632
|
+
timestamp TEXT NOT NULL,
|
|
2633
|
+
scope_value TEXT,
|
|
2634
|
+
scope_ordinal INTEGER,
|
|
2635
|
+
session_id TEXT,
|
|
2636
|
+
service TEXT NOT NULL,
|
|
2637
|
+
data_json TEXT,
|
|
2638
|
+
severity TEXT DEFAULT 'info',
|
|
2639
|
+
parent_event_id TEXT,
|
|
2640
|
+
depth INTEGER DEFAULT 0
|
|
2641
|
+
);
|
|
2642
|
+
|
|
2643
|
+
CREATE INDEX IF NOT EXISTS idx_events_schema ON events(schema_id);
|
|
2644
|
+
CREATE INDEX IF NOT EXISTS idx_events_type ON events(event_type);
|
|
2645
|
+
CREATE INDEX IF NOT EXISTS idx_events_scope ON events(schema_id, scope_value);
|
|
2646
|
+
CREATE INDEX IF NOT EXISTS idx_events_scope_ord ON events(schema_id, scope_ordinal);
|
|
2647
|
+
CREATE INDEX IF NOT EXISTS idx_events_session ON events(session_id);
|
|
2648
|
+
CREATE INDEX IF NOT EXISTS idx_events_timestamp ON events(timestamp);
|
|
2649
|
+
CREATE INDEX IF NOT EXISTS idx_events_service ON events(service);
|
|
2650
|
+
`);
|
|
2651
|
+
} catch {
|
|
2652
|
+
}
|
|
2653
|
+
this.db.run(
|
|
2654
|
+
"INSERT OR REPLACE INTO metadata (key, value) VALUES ('schema_version', '5')"
|
|
2655
|
+
);
|
|
2608
2656
|
}
|
|
2609
2657
|
}
|
|
2610
2658
|
/**
|
|
@@ -4193,6 +4241,341 @@ var SentinelStorage = class {
|
|
|
4193
4241
|
logs: obj.log_ids_json ? JSON.parse(obj.log_ids_json) : []
|
|
4194
4242
|
};
|
|
4195
4243
|
}
|
|
4244
|
+
// ─── Schema Registry ─────────────────────────────────────────────
|
|
4245
|
+
registerSchema(schema) {
|
|
4246
|
+
this.initializeSync();
|
|
4247
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
4248
|
+
this.db.run(
|
|
4249
|
+
`INSERT INTO schemas (
|
|
4250
|
+
id, version, name, description, scope_json, event_types_json,
|
|
4251
|
+
causality_json, visualization_json, tags_json, registered_at, updated_at
|
|
4252
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
4253
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
4254
|
+
version = excluded.version,
|
|
4255
|
+
name = excluded.name,
|
|
4256
|
+
description = excluded.description,
|
|
4257
|
+
scope_json = excluded.scope_json,
|
|
4258
|
+
event_types_json = excluded.event_types_json,
|
|
4259
|
+
causality_json = excluded.causality_json,
|
|
4260
|
+
visualization_json = excluded.visualization_json,
|
|
4261
|
+
tags_json = excluded.tags_json,
|
|
4262
|
+
updated_at = excluded.updated_at`,
|
|
4263
|
+
[
|
|
4264
|
+
schema.id,
|
|
4265
|
+
schema.version,
|
|
4266
|
+
schema.name,
|
|
4267
|
+
schema.description || null,
|
|
4268
|
+
JSON.stringify(schema.scope),
|
|
4269
|
+
JSON.stringify(schema.eventTypes),
|
|
4270
|
+
schema.causality ? JSON.stringify(schema.causality) : null,
|
|
4271
|
+
schema.visualization ? JSON.stringify(schema.visualization) : null,
|
|
4272
|
+
JSON.stringify(schema.tags || []),
|
|
4273
|
+
now,
|
|
4274
|
+
now
|
|
4275
|
+
]
|
|
4276
|
+
);
|
|
4277
|
+
this.save();
|
|
4278
|
+
return {
|
|
4279
|
+
id: schema.id,
|
|
4280
|
+
version: schema.version,
|
|
4281
|
+
name: schema.name,
|
|
4282
|
+
description: schema.description,
|
|
4283
|
+
scope: schema.scope,
|
|
4284
|
+
eventTypes: schema.eventTypes,
|
|
4285
|
+
causality: schema.causality,
|
|
4286
|
+
visualization: schema.visualization,
|
|
4287
|
+
tags: schema.tags || [],
|
|
4288
|
+
registeredAt: now,
|
|
4289
|
+
updatedAt: now
|
|
4290
|
+
};
|
|
4291
|
+
}
|
|
4292
|
+
getSchema(id) {
|
|
4293
|
+
this.initializeSync();
|
|
4294
|
+
const result = this.db.exec("SELECT * FROM schemas WHERE id = ?", [id]);
|
|
4295
|
+
if (result.length === 0 || result[0].values.length === 0) return null;
|
|
4296
|
+
return this.rowToSchema(result[0].columns, result[0].values[0]);
|
|
4297
|
+
}
|
|
4298
|
+
listSchemas() {
|
|
4299
|
+
this.initializeSync();
|
|
4300
|
+
const result = this.db.exec("SELECT * FROM schemas ORDER BY name ASC");
|
|
4301
|
+
if (result.length === 0) return [];
|
|
4302
|
+
return result[0].values.map(
|
|
4303
|
+
(row) => this.rowToSchema(result[0].columns, row)
|
|
4304
|
+
);
|
|
4305
|
+
}
|
|
4306
|
+
rowToSchema(columns, row) {
|
|
4307
|
+
const obj = {};
|
|
4308
|
+
columns.forEach((col, i) => {
|
|
4309
|
+
obj[col] = row[i];
|
|
4310
|
+
});
|
|
4311
|
+
return {
|
|
4312
|
+
id: obj.id,
|
|
4313
|
+
version: obj.version,
|
|
4314
|
+
name: obj.name,
|
|
4315
|
+
description: obj.description || void 0,
|
|
4316
|
+
scope: JSON.parse(obj.scope_json),
|
|
4317
|
+
eventTypes: JSON.parse(obj.event_types_json),
|
|
4318
|
+
causality: obj.causality_json ? JSON.parse(obj.causality_json) : void 0,
|
|
4319
|
+
visualization: obj.visualization_json ? JSON.parse(obj.visualization_json) : void 0,
|
|
4320
|
+
tags: JSON.parse(obj.tags_json || "[]"),
|
|
4321
|
+
registeredAt: obj.registered_at,
|
|
4322
|
+
updatedAt: obj.updated_at
|
|
4323
|
+
};
|
|
4324
|
+
}
|
|
4325
|
+
// ─── Generic Events ────────────────────────────────────────────
|
|
4326
|
+
insertEventBatch(schemaId, service, inputs) {
|
|
4327
|
+
this.initializeSync();
|
|
4328
|
+
const schema = this.getSchema(schemaId);
|
|
4329
|
+
const typeMap = /* @__PURE__ */ new Map();
|
|
4330
|
+
if (schema) {
|
|
4331
|
+
for (const et of schema.eventTypes) {
|
|
4332
|
+
typeMap.set(et.type, {
|
|
4333
|
+
category: et.category,
|
|
4334
|
+
severity: et.severity || "info"
|
|
4335
|
+
});
|
|
4336
|
+
}
|
|
4337
|
+
}
|
|
4338
|
+
let accepted = 0;
|
|
4339
|
+
const errors = [];
|
|
4340
|
+
for (const input of inputs) {
|
|
4341
|
+
try {
|
|
4342
|
+
const id = input.id || v4_default();
|
|
4343
|
+
const timestamp = input.timestamp || (/* @__PURE__ */ new Date()).toISOString();
|
|
4344
|
+
const resolved = typeMap.get(input.type);
|
|
4345
|
+
const category = resolved?.category || "unknown";
|
|
4346
|
+
const severity = input.severity || resolved?.severity || "info";
|
|
4347
|
+
const scopeValue = input.scopeValue != null ? String(input.scopeValue) : null;
|
|
4348
|
+
const scopeOrdinal = typeof input.scopeValue === "number" ? input.scopeValue : null;
|
|
4349
|
+
this.db.run(
|
|
4350
|
+
`INSERT INTO events (
|
|
4351
|
+
id, schema_id, event_type, category, timestamp, scope_value,
|
|
4352
|
+
scope_ordinal, session_id, service, data_json, severity,
|
|
4353
|
+
parent_event_id, depth
|
|
4354
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
4355
|
+
[
|
|
4356
|
+
id,
|
|
4357
|
+
schemaId,
|
|
4358
|
+
input.type,
|
|
4359
|
+
category,
|
|
4360
|
+
timestamp,
|
|
4361
|
+
scopeValue,
|
|
4362
|
+
scopeOrdinal,
|
|
4363
|
+
input.sessionId || null,
|
|
4364
|
+
service,
|
|
4365
|
+
input.data ? JSON.stringify(input.data) : null,
|
|
4366
|
+
severity,
|
|
4367
|
+
input.parentEventId || null,
|
|
4368
|
+
input.depth ?? 0
|
|
4369
|
+
]
|
|
4370
|
+
);
|
|
4371
|
+
accepted++;
|
|
4372
|
+
} catch (err) {
|
|
4373
|
+
errors.push(err instanceof Error ? err.message : String(err));
|
|
4374
|
+
}
|
|
4375
|
+
}
|
|
4376
|
+
this.save();
|
|
4377
|
+
return { accepted, errors };
|
|
4378
|
+
}
|
|
4379
|
+
queryEvents(options = {}) {
|
|
4380
|
+
this.initializeSync();
|
|
4381
|
+
const { limit = 100, offset = 0 } = options;
|
|
4382
|
+
const conditions = [];
|
|
4383
|
+
const params = [];
|
|
4384
|
+
if (options.schemaId) {
|
|
4385
|
+
conditions.push("schema_id = ?");
|
|
4386
|
+
params.push(options.schemaId);
|
|
4387
|
+
}
|
|
4388
|
+
if (options.eventType) {
|
|
4389
|
+
conditions.push("event_type = ?");
|
|
4390
|
+
params.push(options.eventType);
|
|
4391
|
+
}
|
|
4392
|
+
if (options.category) {
|
|
4393
|
+
conditions.push("category = ?");
|
|
4394
|
+
params.push(options.category);
|
|
4395
|
+
}
|
|
4396
|
+
if (options.service) {
|
|
4397
|
+
conditions.push("service = ?");
|
|
4398
|
+
params.push(options.service);
|
|
4399
|
+
}
|
|
4400
|
+
if (options.sessionId) {
|
|
4401
|
+
conditions.push("session_id = ?");
|
|
4402
|
+
params.push(options.sessionId);
|
|
4403
|
+
}
|
|
4404
|
+
if (options.scopeValue) {
|
|
4405
|
+
conditions.push("scope_value = ?");
|
|
4406
|
+
params.push(options.scopeValue);
|
|
4407
|
+
}
|
|
4408
|
+
if (options.scopeFrom) {
|
|
4409
|
+
conditions.push("scope_value >= ?");
|
|
4410
|
+
params.push(options.scopeFrom);
|
|
4411
|
+
}
|
|
4412
|
+
if (options.scopeTo) {
|
|
4413
|
+
conditions.push("scope_value <= ?");
|
|
4414
|
+
params.push(options.scopeTo);
|
|
4415
|
+
}
|
|
4416
|
+
if (options.severity) {
|
|
4417
|
+
conditions.push("severity = ?");
|
|
4418
|
+
params.push(options.severity);
|
|
4419
|
+
}
|
|
4420
|
+
if (options.since) {
|
|
4421
|
+
conditions.push("timestamp >= ?");
|
|
4422
|
+
params.push(options.since);
|
|
4423
|
+
}
|
|
4424
|
+
if (options.until) {
|
|
4425
|
+
conditions.push("timestamp <= ?");
|
|
4426
|
+
params.push(options.until);
|
|
4427
|
+
}
|
|
4428
|
+
if (options.search) {
|
|
4429
|
+
conditions.push("data_json LIKE ?");
|
|
4430
|
+
params.push(`%${options.search}%`);
|
|
4431
|
+
}
|
|
4432
|
+
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
4433
|
+
const result = this.db.exec(
|
|
4434
|
+
`SELECT * FROM events ${whereClause} ORDER BY timestamp DESC LIMIT ? OFFSET ?`,
|
|
4435
|
+
[...params, limit, offset]
|
|
4436
|
+
);
|
|
4437
|
+
if (result.length === 0) return [];
|
|
4438
|
+
return result[0].values.map(
|
|
4439
|
+
(row) => this.rowToGenericEvent(result[0].columns, row)
|
|
4440
|
+
);
|
|
4441
|
+
}
|
|
4442
|
+
queryEventsByScope(schemaId, scopeValue) {
|
|
4443
|
+
this.initializeSync();
|
|
4444
|
+
const result = this.db.exec(
|
|
4445
|
+
`SELECT * FROM events
|
|
4446
|
+
WHERE schema_id = ? AND scope_value = ?
|
|
4447
|
+
ORDER BY timestamp ASC`,
|
|
4448
|
+
[schemaId, scopeValue]
|
|
4449
|
+
);
|
|
4450
|
+
if (result.length === 0) return [];
|
|
4451
|
+
return result[0].values.map(
|
|
4452
|
+
(row) => this.rowToGenericEvent(result[0].columns, row)
|
|
4453
|
+
);
|
|
4454
|
+
}
|
|
4455
|
+
getEventScopes(schemaId, options = {}) {
|
|
4456
|
+
this.initializeSync();
|
|
4457
|
+
const { limit = 100, offset = 0 } = options;
|
|
4458
|
+
const conditions = ["schema_id = ?"];
|
|
4459
|
+
const params = [schemaId];
|
|
4460
|
+
if (options.sessionId) {
|
|
4461
|
+
conditions.push("session_id = ?");
|
|
4462
|
+
params.push(options.sessionId);
|
|
4463
|
+
}
|
|
4464
|
+
const whereClause = `WHERE ${conditions.join(" AND ")}`;
|
|
4465
|
+
const result = this.db.exec(
|
|
4466
|
+
`SELECT
|
|
4467
|
+
scope_value,
|
|
4468
|
+
MIN(scope_ordinal) as scope_ordinal,
|
|
4469
|
+
COUNT(*) as event_count,
|
|
4470
|
+
MIN(timestamp) as first_timestamp,
|
|
4471
|
+
MAX(timestamp) as last_timestamp
|
|
4472
|
+
FROM events
|
|
4473
|
+
${whereClause}
|
|
4474
|
+
AND scope_value IS NOT NULL
|
|
4475
|
+
GROUP BY scope_value
|
|
4476
|
+
ORDER BY MIN(COALESCE(scope_ordinal, 0)) DESC, MIN(timestamp) DESC
|
|
4477
|
+
LIMIT ? OFFSET ?`,
|
|
4478
|
+
[...params, limit, offset]
|
|
4479
|
+
);
|
|
4480
|
+
if (result.length === 0) return [];
|
|
4481
|
+
const scopes = [];
|
|
4482
|
+
for (const row of result[0].values) {
|
|
4483
|
+
const scopeValue = row[0];
|
|
4484
|
+
const scopeOrdinal = row[1] != null ? row[1] : void 0;
|
|
4485
|
+
const eventCount = row[2];
|
|
4486
|
+
const firstTimestamp = row[3];
|
|
4487
|
+
const lastTimestamp = row[4];
|
|
4488
|
+
const catResult = this.db.exec(
|
|
4489
|
+
`SELECT category, COUNT(*) as count FROM events
|
|
4490
|
+
WHERE schema_id = ? AND scope_value = ?
|
|
4491
|
+
GROUP BY category`,
|
|
4492
|
+
[schemaId, scopeValue]
|
|
4493
|
+
);
|
|
4494
|
+
const categories = {};
|
|
4495
|
+
if (catResult.length > 0) {
|
|
4496
|
+
for (const catRow of catResult[0].values) {
|
|
4497
|
+
categories[catRow[0]] = catRow[1];
|
|
4498
|
+
}
|
|
4499
|
+
}
|
|
4500
|
+
scopes.push({
|
|
4501
|
+
scopeValue,
|
|
4502
|
+
scopeOrdinal,
|
|
4503
|
+
eventCount,
|
|
4504
|
+
categories,
|
|
4505
|
+
firstTimestamp,
|
|
4506
|
+
lastTimestamp
|
|
4507
|
+
});
|
|
4508
|
+
}
|
|
4509
|
+
return scopes;
|
|
4510
|
+
}
|
|
4511
|
+
getEventCount(options = {}) {
|
|
4512
|
+
this.initializeSync();
|
|
4513
|
+
const conditions = [];
|
|
4514
|
+
const params = [];
|
|
4515
|
+
if (options.schemaId) {
|
|
4516
|
+
conditions.push("schema_id = ?");
|
|
4517
|
+
params.push(options.schemaId);
|
|
4518
|
+
}
|
|
4519
|
+
if (options.eventType) {
|
|
4520
|
+
conditions.push("event_type = ?");
|
|
4521
|
+
params.push(options.eventType);
|
|
4522
|
+
}
|
|
4523
|
+
if (options.service) {
|
|
4524
|
+
conditions.push("service = ?");
|
|
4525
|
+
params.push(options.service);
|
|
4526
|
+
}
|
|
4527
|
+
if (options.since) {
|
|
4528
|
+
conditions.push("timestamp >= ?");
|
|
4529
|
+
params.push(options.since);
|
|
4530
|
+
}
|
|
4531
|
+
if (options.until) {
|
|
4532
|
+
conditions.push("timestamp <= ?");
|
|
4533
|
+
params.push(options.until);
|
|
4534
|
+
}
|
|
4535
|
+
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
4536
|
+
const result = this.db.exec(
|
|
4537
|
+
`SELECT COUNT(*) as count FROM events ${whereClause}`,
|
|
4538
|
+
params
|
|
4539
|
+
);
|
|
4540
|
+
if (result.length === 0 || result[0].values.length === 0) return 0;
|
|
4541
|
+
return result[0].values[0][0];
|
|
4542
|
+
}
|
|
4543
|
+
pruneEvents(maxCount) {
|
|
4544
|
+
this.initializeSync();
|
|
4545
|
+
if (maxCount <= 0) return 0;
|
|
4546
|
+
const currentCount = this.getEventCount();
|
|
4547
|
+
if (currentCount <= maxCount) return 0;
|
|
4548
|
+
const deleteCount = currentCount - maxCount;
|
|
4549
|
+
this.db.run(
|
|
4550
|
+
`DELETE FROM events WHERE id IN (
|
|
4551
|
+
SELECT id FROM events ORDER BY timestamp ASC LIMIT ?
|
|
4552
|
+
)`,
|
|
4553
|
+
[deleteCount]
|
|
4554
|
+
);
|
|
4555
|
+
this.save();
|
|
4556
|
+
return deleteCount;
|
|
4557
|
+
}
|
|
4558
|
+
rowToGenericEvent(columns, row) {
|
|
4559
|
+
const obj = {};
|
|
4560
|
+
columns.forEach((col, i) => {
|
|
4561
|
+
obj[col] = row[i];
|
|
4562
|
+
});
|
|
4563
|
+
return {
|
|
4564
|
+
id: obj.id,
|
|
4565
|
+
schemaId: obj.schema_id,
|
|
4566
|
+
eventType: obj.event_type,
|
|
4567
|
+
category: obj.category,
|
|
4568
|
+
timestamp: obj.timestamp,
|
|
4569
|
+
scopeValue: obj.scope_value || void 0,
|
|
4570
|
+
scopeOrdinal: obj.scope_ordinal != null ? obj.scope_ordinal : void 0,
|
|
4571
|
+
sessionId: obj.session_id || void 0,
|
|
4572
|
+
service: obj.service,
|
|
4573
|
+
data: obj.data_json ? JSON.parse(obj.data_json) : void 0,
|
|
4574
|
+
severity: obj.severity || "info",
|
|
4575
|
+
parentEventId: obj.parent_event_id || void 0,
|
|
4576
|
+
depth: obj.depth || 0
|
|
4577
|
+
};
|
|
4578
|
+
}
|
|
4196
4579
|
close() {
|
|
4197
4580
|
if (this.db) {
|
|
4198
4581
|
this.save();
|
|
@@ -548,6 +548,8 @@ ${purposeLines}
|
|
|
548
548
|
function createMinimalStructure(paradigmDir, projectName) {
|
|
549
549
|
fs.mkdirSync(path.join(paradigmDir, "specs"), { recursive: true });
|
|
550
550
|
fs.mkdirSync(path.join(paradigmDir, "docs"), { recursive: true });
|
|
551
|
+
fs.mkdirSync(path.join(paradigmDir, "tasks"), { recursive: true });
|
|
552
|
+
fs.mkdirSync(path.join(paradigmDir, "assessments"), { recursive: true });
|
|
551
553
|
const minimalConfig = `# Paradigm Configuration
|
|
552
554
|
version: "1.0"
|
|
553
555
|
project: "${projectName}"
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// ../paradigm-mcp/src/utils/task-loader.ts
|
|
4
|
+
import * as fs from "fs";
|
|
5
|
+
import * as path from "path";
|
|
6
|
+
import * as yaml from "js-yaml";
|
|
7
|
+
var TASKS_ROOT = ".paradigm/tasks";
|
|
8
|
+
var ENTRIES_DIR = "entries";
|
|
9
|
+
var INDEX_FILE = "index.yaml";
|
|
10
|
+
function generateTaskId(rootDir, dateStr) {
|
|
11
|
+
const datePath = path.join(rootDir, TASKS_ROOT, ENTRIES_DIR, dateStr);
|
|
12
|
+
if (!fs.existsSync(datePath)) {
|
|
13
|
+
return `T-${dateStr}-001`;
|
|
14
|
+
}
|
|
15
|
+
const existing = fs.readdirSync(datePath).filter((f) => f.startsWith("T-") && f.endsWith(".yaml")).map((f) => {
|
|
16
|
+
const match = f.match(/T-\d{4}-\d{2}-\d{2}-(\d+)\.yaml/);
|
|
17
|
+
return match ? parseInt(match[1], 10) : 0;
|
|
18
|
+
});
|
|
19
|
+
const next = existing.length > 0 ? Math.max(...existing) + 1 : 1;
|
|
20
|
+
return `T-${dateStr}-${String(next).padStart(3, "0")}`;
|
|
21
|
+
}
|
|
22
|
+
var PRIORITY_ORDER = { high: 0, medium: 1, low: 2 };
|
|
23
|
+
function applyFilter(tasks, filter) {
|
|
24
|
+
let result = tasks;
|
|
25
|
+
if (filter.status && filter.status !== "all") {
|
|
26
|
+
result = result.filter((t) => t.status === filter.status);
|
|
27
|
+
}
|
|
28
|
+
if (filter.priority) {
|
|
29
|
+
result = result.filter((t) => t.priority === filter.priority);
|
|
30
|
+
}
|
|
31
|
+
if (filter.tag) {
|
|
32
|
+
result = result.filter((t) => t.tags.includes(filter.tag));
|
|
33
|
+
}
|
|
34
|
+
result.sort((a, b) => {
|
|
35
|
+
const priDiff = (PRIORITY_ORDER[a.priority] ?? 1) - (PRIORITY_ORDER[b.priority] ?? 1);
|
|
36
|
+
if (priDiff !== 0) return priDiff;
|
|
37
|
+
return new Date(b.created).getTime() - new Date(a.created).getTime();
|
|
38
|
+
});
|
|
39
|
+
if (filter.limit) {
|
|
40
|
+
result = result.slice(0, filter.limit);
|
|
41
|
+
}
|
|
42
|
+
return result;
|
|
43
|
+
}
|
|
44
|
+
async function loadTasks(rootDir, filter) {
|
|
45
|
+
const entriesPath = path.join(rootDir, TASKS_ROOT, ENTRIES_DIR);
|
|
46
|
+
if (!fs.existsSync(entriesPath)) return [];
|
|
47
|
+
const effectiveFilter = { status: "open", limit: 20, ...filter };
|
|
48
|
+
const tasks = [];
|
|
49
|
+
const dateDirs = fs.readdirSync(entriesPath).filter((d) => /^\d{4}-\d{2}-\d{2}$/.test(d)).sort().reverse();
|
|
50
|
+
for (const dateDir of dateDirs) {
|
|
51
|
+
const dirPath = path.join(entriesPath, dateDir);
|
|
52
|
+
const files = fs.readdirSync(dirPath).filter((f) => f.endsWith(".yaml")).sort();
|
|
53
|
+
for (const file of files) {
|
|
54
|
+
try {
|
|
55
|
+
const content = fs.readFileSync(path.join(dirPath, file), "utf8");
|
|
56
|
+
const task = yaml.load(content);
|
|
57
|
+
tasks.push(task);
|
|
58
|
+
} catch {
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return applyFilter(tasks, effectiveFilter);
|
|
63
|
+
}
|
|
64
|
+
async function loadTask(rootDir, taskId) {
|
|
65
|
+
const dateMatch = taskId.match(/^T-(\d{4}-\d{2}-\d{2})-/);
|
|
66
|
+
if (dateMatch) {
|
|
67
|
+
const filePath = path.join(rootDir, TASKS_ROOT, ENTRIES_DIR, dateMatch[1], `${taskId}.yaml`);
|
|
68
|
+
if (fs.existsSync(filePath)) {
|
|
69
|
+
try {
|
|
70
|
+
return yaml.load(fs.readFileSync(filePath, "utf8"));
|
|
71
|
+
} catch {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const tasks = await loadTasks(rootDir, { status: "all", limit: 9999 });
|
|
77
|
+
return tasks.find((t) => t.id === taskId) || null;
|
|
78
|
+
}
|
|
79
|
+
async function createTask(rootDir, task) {
|
|
80
|
+
const now = /* @__PURE__ */ new Date();
|
|
81
|
+
const dateStr = now.toISOString().slice(0, 10);
|
|
82
|
+
const datePath = path.join(rootDir, TASKS_ROOT, ENTRIES_DIR, dateStr);
|
|
83
|
+
fs.mkdirSync(datePath, { recursive: true });
|
|
84
|
+
const id = generateTaskId(rootDir, dateStr);
|
|
85
|
+
const entry = {
|
|
86
|
+
id,
|
|
87
|
+
blurb: task.blurb,
|
|
88
|
+
priority: task.priority || "medium",
|
|
89
|
+
status: "open",
|
|
90
|
+
tags: task.tags || [],
|
|
91
|
+
created: now.toISOString(),
|
|
92
|
+
session_link: task.session_link,
|
|
93
|
+
related_lore: task.related_lore
|
|
94
|
+
};
|
|
95
|
+
fs.writeFileSync(path.join(datePath, `${id}.yaml`), yaml.dump(entry, { lineWidth: -1, noRefs: true }));
|
|
96
|
+
await rebuildTaskIndex(rootDir);
|
|
97
|
+
return id;
|
|
98
|
+
}
|
|
99
|
+
async function updateTask(rootDir, taskId, partial) {
|
|
100
|
+
const task = await loadTask(rootDir, taskId);
|
|
101
|
+
if (!task) return false;
|
|
102
|
+
const dateStr = task.created.slice(0, 10);
|
|
103
|
+
const taskPath = path.join(rootDir, TASKS_ROOT, ENTRIES_DIR, dateStr, `${taskId}.yaml`);
|
|
104
|
+
if (!fs.existsSync(taskPath)) return false;
|
|
105
|
+
const { id: _id, created: _created, ...safePartial } = partial;
|
|
106
|
+
const updated = { ...task, ...safePartial };
|
|
107
|
+
fs.writeFileSync(taskPath, yaml.dump(updated, { lineWidth: -1, noRefs: true }));
|
|
108
|
+
await rebuildTaskIndex(rootDir);
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
async function completeTask(rootDir, taskId) {
|
|
112
|
+
return updateTask(rootDir, taskId, { status: "done", completed: (/* @__PURE__ */ new Date()).toISOString() });
|
|
113
|
+
}
|
|
114
|
+
async function shelveTask(rootDir, taskId) {
|
|
115
|
+
return updateTask(rootDir, taskId, { status: "shelved", shelved: (/* @__PURE__ */ new Date()).toISOString() });
|
|
116
|
+
}
|
|
117
|
+
async function rebuildTaskIndex(rootDir) {
|
|
118
|
+
const entriesPath = path.join(rootDir, TASKS_ROOT, ENTRIES_DIR);
|
|
119
|
+
const tasksRootPath = path.join(rootDir, TASKS_ROOT);
|
|
120
|
+
let total = 0, open = 0, done = 0, shelved = 0;
|
|
121
|
+
if (fs.existsSync(entriesPath)) {
|
|
122
|
+
const dateDirs = fs.readdirSync(entriesPath).filter((d) => /^\d{4}-\d{2}-\d{2}$/.test(d));
|
|
123
|
+
for (const dateDir of dateDirs) {
|
|
124
|
+
const dirPath = path.join(entriesPath, dateDir);
|
|
125
|
+
const files = fs.readdirSync(dirPath).filter((f) => f.endsWith(".yaml"));
|
|
126
|
+
for (const file of files) {
|
|
127
|
+
try {
|
|
128
|
+
const task = yaml.load(fs.readFileSync(path.join(dirPath, file), "utf8"));
|
|
129
|
+
total++;
|
|
130
|
+
if (task.status === "open") open++;
|
|
131
|
+
else if (task.status === "done") done++;
|
|
132
|
+
else if (task.status === "shelved") shelved++;
|
|
133
|
+
} catch {
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
const index = { version: "1.0", total, open, done, shelved, last_updated: (/* @__PURE__ */ new Date()).toISOString() };
|
|
139
|
+
fs.mkdirSync(tasksRootPath, { recursive: true });
|
|
140
|
+
fs.writeFileSync(path.join(tasksRootPath, INDEX_FILE), yaml.dump(index, { lineWidth: -1, noRefs: true }));
|
|
141
|
+
return index;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export {
|
|
145
|
+
loadTasks,
|
|
146
|
+
loadTask,
|
|
147
|
+
createTask,
|
|
148
|
+
updateTask,
|
|
149
|
+
completeTask,
|
|
150
|
+
shelveTask,
|
|
151
|
+
rebuildTaskIndex
|
|
152
|
+
};
|