@hasna/todos 0.15.33 → 0.15.35
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/cli/cloud-router.d.ts +33 -47
- package/dist/cli/cloud-router.d.ts.map +1 -1
- package/dist/cli/commands/project-commands.d.ts.map +1 -1
- package/dist/cli/commands/task-commands.d.ts.map +1 -1
- package/dist/cli/index.js +344 -127
- package/dist/cli/stage-a.d.ts +3 -1
- package/dist/cli/stage-a.d.ts.map +1 -1
- package/dist/contracts.js +115 -27
- package/dist/db/migrations.d.ts.map +1 -1
- package/dist/db/projects.d.ts +23 -0
- package/dist/db/projects.d.ts.map +1 -1
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/index.js +275 -116
- package/dist/json-contracts.d.ts.map +1 -1
- package/dist/lib/assignee-validation.d.ts.map +1 -1
- package/dist/lib/import-export-bridge.d.ts.map +1 -1
- package/dist/lib/onboarding-fixtures.d.ts.map +1 -1
- package/dist/mcp/index.js +285 -113
- package/dist/mcp/tools/task-project-tools.d.ts.map +1 -1
- package/dist/mcp.js +3 -2
- package/dist/project-registration/authority.d.ts.map +1 -1
- package/dist/project-registration/sqlite.d.ts.map +1 -1
- package/dist/project-registration.js +185 -40
- package/dist/registry.js +115 -27
- package/dist/release-provenance.json +5 -5
- package/dist/sdk/v1.generated.d.ts +3 -0
- package/dist/sdk/v1.generated.d.ts.map +1 -1
- package/dist/server/index.js +1268 -7051
- package/dist/server/openapi.d.ts +13 -0
- package/dist/server/openapi.d.ts.map +1 -1
- package/dist/server/v1.d.ts.map +1 -1
- package/dist/storage/config.d.ts +24 -4
- package/dist/storage/config.d.ts.map +1 -1
- package/dist/storage/hybrid.d.ts +5 -3
- package/dist/storage/hybrid.d.ts.map +1 -1
- package/dist/storage.js +158 -34
- package/dist/task-manifest.js +3 -3
- package/dist/testing.d.ts +16 -7
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +10 -6
- package/dist/types/index.d.ts +5 -2
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +3 -2
package/dist/cli/stage-a.d.ts
CHANGED
|
@@ -18,7 +18,9 @@ export type TodosCliCommandOwner = "diagnostic" | "remote-http" | "local-only";
|
|
|
18
18
|
* mutating the caller's environment. The executable applies an admitted local
|
|
19
19
|
* redaction decision before importing command modules so any later
|
|
20
20
|
* `getTodosCloudClient()` call cannot reconstruct hosted routing from the
|
|
21
|
-
* ambient
|
|
21
|
+
* ambient API pair. The retired storage-mode variables are never written here —
|
|
22
|
+
* they are banned (owner directive 2026-08-15), and the HTTP selector is
|
|
23
|
+
* HASNA_TODOS_API_URL + HASNA_TODOS_API_KEY, which the redaction blanks.
|
|
22
24
|
*/
|
|
23
25
|
export declare function applyTodosCliAuthorityEnvironment(authority: TodosCliAuthorityInitialization, env?: Env): void;
|
|
24
26
|
export declare const TODOS_CLI_COMMAND_ALIASES: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stage-a.d.ts","sourceRoot":"","sources":["../../src/cli/stage-a.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAQ,MAAM,WAAW,CAAC;AAC1C,OAAO,
|
|
1
|
+
{"version":3,"file":"stage-a.d.ts","sourceRoot":"","sources":["../../src/cli/stage-a.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAQ,MAAM,WAAW,CAAC;AAC1C,OAAO,EAKL,KAAK,4BAA4B,EAClC,MAAM,mBAAmB,CAAC;AAE3B,KAAK,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AAE9C,MAAM,MAAM,+BAA+B,GACvC;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,WAAW,EAAE,IAAI,CAAC;IAAC,WAAW,CAAC,EAAE,oBAAoB,CAAA;CAAE,GACzE;IAAE,KAAK,EAAE,mBAAmB,CAAC;IAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAC1D;IAAE,KAAK,EAAE,aAAa,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC;AAElD,MAAM,MAAM,oBAAoB,GAAG,YAAY,GAAG,aAAa,GAAG,YAAY,CAAC;AAE/E;;;;;;;;GAQG;AACH,wBAAgB,iCAAiC,CAC/C,SAAS,EAAE,+BAA+B,EAC1C,GAAG,GAAE,GAAwB,GAC5B,IAAI,CAMN;AAyBD,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;CA8BgB,CAAC;AAkFvD,wBAAgB,kCAAkC,IAAI,WAAW,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAE9F;AAED;;;;;;;GAOG;AACH,wBAAgB,gCAAgC,CAC9C,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,+BAA+B,CAAC,OAAO,CAAC,EAC/C,kBAAkB,GAAE,WAAW,CAAC,4BAA4B,CAAa,GACxE,OAAO,CAOT;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,+BAA+B,CAAC,OAAO,CAAC,EAC/C,kBAAkB,GAAE,WAAW,CAAC,4BAA4B,CAAa,GACxE,IAAI,CAUN;AAED;;;;;;;;GAQG;AACH,wBAAgB,2CAA2C,CACzD,KAAK,EAAE,+BAA+B,CAAC,OAAO,CAAC,EAC/C,kBAAkB,GAAE,WAAW,CAAC,4BAA4B,CAAa,EACzE,IAAI,GAAE,SAAS,MAAM,EAAO,GAC3B,MAAM,GAAG,IAAI,CAYf;AA2XD;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CACzC,IAAI,GAAE,MAAM,EAA0B,EACtC,GAAG,GAAE,GAAwB,GAC5B,+BAA+B,CAsCjC"}
|
package/dist/contracts.js
CHANGED
|
@@ -1884,6 +1884,10 @@ var init_migrations = __esm(() => {
|
|
|
1884
1884
|
);
|
|
1885
1885
|
INSERT OR IGNORE INTO _migrations (id) VALUES (70);
|
|
1886
1886
|
COMMIT;
|
|
1887
|
+
`,
|
|
1888
|
+
`BEGIN;
|
|
1889
|
+
INSERT OR IGNORE INTO _migrations (id) VALUES (71);
|
|
1890
|
+
COMMIT;
|
|
1887
1891
|
`
|
|
1888
1892
|
];
|
|
1889
1893
|
});
|
|
@@ -2557,6 +2561,8 @@ function ensureSchema(db) {
|
|
|
2557
2561
|
ensureColumn("projects", "task_list_id", "TEXT");
|
|
2558
2562
|
ensureColumn("projects", "task_prefix", "TEXT");
|
|
2559
2563
|
ensureColumn("projects", "task_counter", "INTEGER NOT NULL DEFAULT 0");
|
|
2564
|
+
ensureColumn("projects", "parent_id", "TEXT REFERENCES projects(id) ON DELETE SET NULL");
|
|
2565
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_projects_parent_id ON projects(parent_id)");
|
|
2560
2566
|
ensureColumn("tasks", "plan_id", "TEXT REFERENCES plans(id) ON DELETE SET NULL");
|
|
2561
2567
|
ensureColumn("tasks", "task_list_id", "TEXT REFERENCES task_lists(id) ON DELETE SET NULL");
|
|
2562
2568
|
ensureColumn("tasks", "short_id", "TEXT");
|
|
@@ -4177,6 +4183,7 @@ __export(exports_config, {
|
|
|
4177
4183
|
TODOS_STORAGE_FALLBACK_ENV: () => TODOS_STORAGE_FALLBACK_ENV,
|
|
4178
4184
|
TODOS_STORAGE_ENV: () => TODOS_STORAGE_ENV,
|
|
4179
4185
|
STORAGE_TABLES: () => STORAGE_TABLES,
|
|
4186
|
+
REMOVED_STORAGE_MODE_ENV_KEYS: () => REMOVED_STORAGE_MODE_ENV_KEYS,
|
|
4180
4187
|
CANONICAL_TODOS_RDS_RUNTIME_PATH_ENV: () => CANONICAL_TODOS_RDS_RUNTIME_PATH_ENV,
|
|
4181
4188
|
CANONICAL_TODOS_RDS_DATABASE: () => CANONICAL_TODOS_RDS_DATABASE,
|
|
4182
4189
|
CANONICAL_TODOS_RDS_CLUSTER_ENV: () => CANONICAL_TODOS_RDS_CLUSTER_ENV
|
|
@@ -4238,25 +4245,36 @@ function assertTodosRemoteStorageConfig(config) {
|
|
|
4238
4245
|
if (!isTodosPostgresBackend(config))
|
|
4239
4246
|
return;
|
|
4240
4247
|
if (!config.database?.url) {
|
|
4241
|
-
throw new Error(`${TODOS_STORAGE_ENV.databaseUrl} is required when
|
|
4248
|
+
throw new Error(`${TODOS_STORAGE_ENV.databaseUrl} is required when the postgresql backend is selected`);
|
|
4242
4249
|
}
|
|
4243
4250
|
}
|
|
4244
4251
|
function parseStorageBackend(value) {
|
|
4245
4252
|
const normalized = clean(value)?.toLowerCase();
|
|
4246
4253
|
if (!normalized)
|
|
4247
4254
|
return "sqlite";
|
|
4248
|
-
if (normalized === "sqlite"
|
|
4249
|
-
return
|
|
4250
|
-
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
|
|
4255
|
+
if (normalized === "sqlite")
|
|
4256
|
+
return "sqlite";
|
|
4257
|
+
if (normalized === "postgres" || normalized === "postgresql")
|
|
4258
|
+
return "postgres";
|
|
4259
|
+
if (["local", "remote", "cloud", "hybrid", "self_hosted"].includes(normalized)) {
|
|
4260
|
+
throw new Error(`${TODOS_STORAGE_ENV.databaseUrl} selects the backend. Deployment modes no longer exist: ` + `delete the storage-mode variable and set ${TODOS_STORAGE_ENV.databaseUrl} to select the ` + `postgresql backend, or leave it unset for sqlite.`);
|
|
4261
|
+
}
|
|
4262
|
+
throw new Error(`Storage backend must be sqlite or postgres`);
|
|
4254
4263
|
}
|
|
4255
4264
|
function parseStorageMode(value) {
|
|
4256
4265
|
return parseStorageBackend(value);
|
|
4257
4266
|
}
|
|
4258
4267
|
function getTodosStorageBackend(env = process.env) {
|
|
4259
|
-
|
|
4268
|
+
for (const key of REMOVED_STORAGE_MODE_ENV_KEYS) {
|
|
4269
|
+
if (Object.hasOwn(env, key) && env[key] !== undefined) {
|
|
4270
|
+
throw new Error(`${key} was removed. Deployment modes no longer exist: delete the storage-mode variable. ` + `Set ${TODOS_STORAGE_ENV.databaseUrl} to select the postgresql backend, ` + `or leave it unset for sqlite.`);
|
|
4271
|
+
}
|
|
4272
|
+
}
|
|
4273
|
+
if (!getTodosStorageDatabaseUrl(env))
|
|
4274
|
+
return "sqlite";
|
|
4275
|
+
if (isTodosShadowEnabled(env))
|
|
4276
|
+
return "sqlite";
|
|
4277
|
+
return "postgres";
|
|
4260
4278
|
}
|
|
4261
4279
|
function getTodosStorageMode(env = process.env) {
|
|
4262
4280
|
return getTodosStorageBackend(env);
|
|
@@ -4330,7 +4348,7 @@ function parsePositiveInteger(value, fallback) {
|
|
|
4330
4348
|
}
|
|
4331
4349
|
return parsed;
|
|
4332
4350
|
}
|
|
4333
|
-
var TODOS_STORAGE_TABLES, STORAGE_TABLES, TODOS_STORAGE_ENV, TODOS_STORAGE_FALLBACK_ENV, CANONICAL_TODOS_RDS_CLUSTER_ENV = "HASNA_TODOS_RDS_CLUSTER", CANONICAL_TODOS_RDS_RUNTIME_PATH_ENV = "HASNA_TODOS_RDS_RUNTIME_PATH", CANONICAL_TODOS_RDS_DATABASE = "todos"
|
|
4351
|
+
var TODOS_STORAGE_TABLES, STORAGE_TABLES, TODOS_STORAGE_ENV, TODOS_STORAGE_FALLBACK_ENV, REMOVED_STORAGE_MODE_ENV_KEYS, CANONICAL_TODOS_RDS_CLUSTER_ENV = "HASNA_TODOS_RDS_CLUSTER", CANONICAL_TODOS_RDS_RUNTIME_PATH_ENV = "HASNA_TODOS_RDS_RUNTIME_PATH", CANONICAL_TODOS_RDS_DATABASE = "todos";
|
|
4334
4352
|
var init_config = __esm(() => {
|
|
4335
4353
|
TODOS_STORAGE_TABLES = [
|
|
4336
4354
|
"todos_sync_records",
|
|
@@ -4338,7 +4356,6 @@ var init_config = __esm(() => {
|
|
|
4338
4356
|
];
|
|
4339
4357
|
STORAGE_TABLES = TODOS_STORAGE_TABLES;
|
|
4340
4358
|
TODOS_STORAGE_ENV = {
|
|
4341
|
-
mode: "HASNA_TODOS_STORAGE_MODE",
|
|
4342
4359
|
shadow: "HASNA_TODOS_SHADOW",
|
|
4343
4360
|
databaseUrl: "HASNA_TODOS_DATABASE_URL",
|
|
4344
4361
|
databaseSsl: "HASNA_TODOS_DATABASE_SSL",
|
|
@@ -4355,7 +4372,6 @@ var init_config = __esm(() => {
|
|
|
4355
4372
|
syncDryRun: "HASNA_TODOS_SYNC_DRY_RUN"
|
|
4356
4373
|
};
|
|
4357
4374
|
TODOS_STORAGE_FALLBACK_ENV = {
|
|
4358
|
-
mode: "TODOS_STORAGE_MODE",
|
|
4359
4375
|
shadow: "TODOS_SHADOW",
|
|
4360
4376
|
databaseUrl: "TODOS_DATABASE_URL",
|
|
4361
4377
|
databaseSsl: "TODOS_DATABASE_SSL",
|
|
@@ -4371,14 +4387,12 @@ var init_config = __esm(() => {
|
|
|
4371
4387
|
syncBatchSize: "TODOS_SYNC_BATCH_SIZE",
|
|
4372
4388
|
syncDryRun: "TODOS_SYNC_DRY_RUN"
|
|
4373
4389
|
};
|
|
4374
|
-
|
|
4375
|
-
|
|
4376
|
-
|
|
4377
|
-
|
|
4378
|
-
|
|
4379
|
-
|
|
4380
|
-
cloud: "postgres"
|
|
4381
|
-
};
|
|
4390
|
+
REMOVED_STORAGE_MODE_ENV_KEYS = [
|
|
4391
|
+
"HASNA_TODOS_STORAGE_MODE",
|
|
4392
|
+
"HASNA_TODOS_MODE",
|
|
4393
|
+
"TODOS_STORAGE_MODE",
|
|
4394
|
+
"TODOS_MODE"
|
|
4395
|
+
];
|
|
4382
4396
|
});
|
|
4383
4397
|
|
|
4384
4398
|
// src/storage/shadow-outbox-schema.ts
|
|
@@ -5037,17 +5051,24 @@ function createProject(input, db) {
|
|
|
5037
5051
|
const id = uuid();
|
|
5038
5052
|
const timestamp2 = now();
|
|
5039
5053
|
const derivedSlug = slugify(input.name);
|
|
5040
|
-
const taskListId = input.task_list_id === undefined ?
|
|
5054
|
+
const taskListId = input.task_list_id === undefined ? derivedSlug : slugify(input.task_list_id);
|
|
5041
5055
|
if (!derivedSlug || !taskListId)
|
|
5042
5056
|
throw new Error("Project name and task-list slug must be non-empty");
|
|
5043
5057
|
const slugConflict = d.query("SELECT id FROM projects WHERE task_list_id = ? LIMIT 1").get(taskListId);
|
|
5044
5058
|
if (slugConflict || !claimCanonicalSlug("project", "global", taskListId, id, d)) {
|
|
5045
5059
|
throw new ResourceConflictError("PROJECT_SLUG_CONFLICT", `Project slug "${taskListId}" already exists`);
|
|
5046
5060
|
}
|
|
5061
|
+
const parentId = input.parent_id ?? null;
|
|
5062
|
+
if (parentId !== null) {
|
|
5063
|
+
const parent = getProject(parentId, d);
|
|
5064
|
+
if (!parent)
|
|
5065
|
+
throw new ProjectNotFoundError(parentId);
|
|
5066
|
+
assertNotProjectAncestor(id, parentId, d);
|
|
5067
|
+
}
|
|
5047
5068
|
const taskPrefix = input.task_prefix || generatePrefix(input.name, d);
|
|
5048
5069
|
const machineId = currentStorageMachineId(d);
|
|
5049
|
-
d.run(`INSERT INTO projects (id, name, path, description, task_list_id, task_prefix, task_counter, created_at, updated_at, machine_id)
|
|
5050
|
-
VALUES (?, ?, ?, ?, ?, ?, 0, ?, ?, ?)`, [id, input.name, input.path, input.description || null, taskListId, taskPrefix, timestamp2, timestamp2, machineId]);
|
|
5070
|
+
d.run(`INSERT INTO projects (id, name, path, description, task_list_id, task_prefix, task_counter, parent_id, created_at, updated_at, machine_id)
|
|
5071
|
+
VALUES (?, ?, ?, ?, ?, ?, 0, ?, ?, ?, ?)`, [id, input.name, input.path, input.description || null, taskListId, taskPrefix, parentId, timestamp2, timestamp2, machineId]);
|
|
5051
5072
|
return getProject(id, d);
|
|
5052
5073
|
})();
|
|
5053
5074
|
}
|
|
@@ -5072,6 +5093,60 @@ function listProjects(db) {
|
|
|
5072
5093
|
const d = db || getDatabase();
|
|
5073
5094
|
return d.query("SELECT * FROM projects ORDER BY name").all();
|
|
5074
5095
|
}
|
|
5096
|
+
function orderProjectsParentFirst(projects) {
|
|
5097
|
+
const projectId = (project) => {
|
|
5098
|
+
const id = project.id;
|
|
5099
|
+
return typeof id === "string" && id.length > 0 ? id : null;
|
|
5100
|
+
};
|
|
5101
|
+
const parentId = (project) => {
|
|
5102
|
+
const parent = project.parent_id;
|
|
5103
|
+
return parent == null ? null : String(parent);
|
|
5104
|
+
};
|
|
5105
|
+
const byId = new Set;
|
|
5106
|
+
for (const project of projects) {
|
|
5107
|
+
const id = projectId(project);
|
|
5108
|
+
if (id !== null)
|
|
5109
|
+
byId.add(id);
|
|
5110
|
+
}
|
|
5111
|
+
const ordered = [];
|
|
5112
|
+
const emitted = new Set;
|
|
5113
|
+
let remaining = [...projects];
|
|
5114
|
+
let progress = true;
|
|
5115
|
+
while (progress && remaining.length > 0) {
|
|
5116
|
+
progress = false;
|
|
5117
|
+
const deferred = [];
|
|
5118
|
+
for (const project of remaining) {
|
|
5119
|
+
const parent = parentId(project);
|
|
5120
|
+
if (parent === null || emitted.has(parent) || !byId.has(parent)) {
|
|
5121
|
+
ordered.push(project);
|
|
5122
|
+
const id = projectId(project);
|
|
5123
|
+
if (id !== null)
|
|
5124
|
+
emitted.add(id);
|
|
5125
|
+
progress = true;
|
|
5126
|
+
} else {
|
|
5127
|
+
deferred.push(project);
|
|
5128
|
+
}
|
|
5129
|
+
}
|
|
5130
|
+
remaining = deferred;
|
|
5131
|
+
}
|
|
5132
|
+
ordered.push(...remaining);
|
|
5133
|
+
return ordered;
|
|
5134
|
+
}
|
|
5135
|
+
function assertNotProjectAncestor(projectId, ancestorId, db) {
|
|
5136
|
+
const d = db || getDatabase();
|
|
5137
|
+
let cursor = ancestorId;
|
|
5138
|
+
const seen = new Set;
|
|
5139
|
+
while (cursor !== null) {
|
|
5140
|
+
if (cursor === projectId) {
|
|
5141
|
+
throw new ResourceConflictError("PROJECT_PARENT_CYCLE", `Project "${projectId}" cannot be placed under its own descendant`);
|
|
5142
|
+
}
|
|
5143
|
+
if (seen.has(cursor))
|
|
5144
|
+
break;
|
|
5145
|
+
seen.add(cursor);
|
|
5146
|
+
const row = d.query("SELECT parent_id FROM projects WHERE id = ?").get(cursor);
|
|
5147
|
+
cursor = row?.parent_id ?? null;
|
|
5148
|
+
}
|
|
5149
|
+
}
|
|
5075
5150
|
function updateProject(id, input, db) {
|
|
5076
5151
|
const d = db || getDatabase();
|
|
5077
5152
|
const project = getProject(id, d);
|
|
@@ -5094,6 +5169,16 @@ function updateProject(id, input, db) {
|
|
|
5094
5169
|
sets.push("path = ?");
|
|
5095
5170
|
params.push(input.path);
|
|
5096
5171
|
}
|
|
5172
|
+
if (input.parent_id !== undefined) {
|
|
5173
|
+
if (input.parent_id !== null) {
|
|
5174
|
+
const parent = getProject(input.parent_id, d);
|
|
5175
|
+
if (!parent)
|
|
5176
|
+
throw new ProjectNotFoundError(input.parent_id);
|
|
5177
|
+
assertNotProjectAncestor(id, input.parent_id, d);
|
|
5178
|
+
}
|
|
5179
|
+
sets.push("parent_id = ?");
|
|
5180
|
+
params.push(input.parent_id);
|
|
5181
|
+
}
|
|
5097
5182
|
params.push(id);
|
|
5098
5183
|
d.run(`UPDATE projects SET ${sets.join(", ")} WHERE id = ?`, params);
|
|
5099
5184
|
return getProject(id, d);
|
|
@@ -7227,8 +7312,8 @@ var init_secret_redaction = __esm(() => {
|
|
|
7227
7312
|
SECRET_REDACTION_SCHEMA = ["todos", "secret_redaction", "v1"].join(".");
|
|
7228
7313
|
DEFAULT_PATTERNS = [
|
|
7229
7314
|
{ name: "openai_sk", pattern: /\bsk-[a-zA-Z0-9]{10,}\b/g },
|
|
7230
|
-
{ name: "github_pat", pattern: /\
|
|
7231
|
-
{ name: "github_oauth", pattern: /\
|
|
7315
|
+
{ name: "github_pat", pattern: /\bgh[p]_[a-zA-Z0-9]{20,}\b/g },
|
|
7316
|
+
{ name: "github_oauth", pattern: /\bgh[o]_[a-zA-Z0-9]{20,}\b/g },
|
|
7232
7317
|
{ name: "aws_access_key", pattern: /\bAKIA[0-9A-Z]{16}\b/g },
|
|
7233
7318
|
{ name: "bearer_token", pattern: /\bBearer\s+[a-zA-Z0-9\-._~+/]+=*\b/gi },
|
|
7234
7319
|
{ name: "jwt", pattern: /\beyJ[a-zA-Z0-9_-]+\.eyJ[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+\b/g },
|
|
@@ -7240,7 +7325,7 @@ var init_secret_redaction = __esm(() => {
|
|
|
7240
7325
|
/example\.com/i,
|
|
7241
7326
|
/your-api-key-here/i,
|
|
7242
7327
|
/sk-test/i,
|
|
7243
|
-
/
|
|
7328
|
+
/gh[p]_xxx/i
|
|
7244
7329
|
];
|
|
7245
7330
|
customRedactors = [];
|
|
7246
7331
|
});
|
|
@@ -12720,7 +12805,7 @@ var init_tasks = __esm(() => {
|
|
|
12720
12805
|
// package.json
|
|
12721
12806
|
var package_default = {
|
|
12722
12807
|
name: "@hasna/todos",
|
|
12723
|
-
version: "0.15.
|
|
12808
|
+
version: "0.15.35",
|
|
12724
12809
|
description: "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
|
|
12725
12810
|
type: "module",
|
|
12726
12811
|
main: "dist/index.js",
|
|
@@ -12794,9 +12879,10 @@ var package_default = {
|
|
|
12794
12879
|
"verify:release": "bun run scripts/verify-public-release.ts --mode=review",
|
|
12795
12880
|
"verify:release-review": "bun run scripts/verify-npm-release-agent-review.ts",
|
|
12796
12881
|
"verify:attested-container-candidate": "bun run scripts/attested-container-candidate.ts verify",
|
|
12797
|
-
"test:attested-container-candidate": "bun test scripts/attested-container-candidate.test.ts
|
|
12882
|
+
"test:attested-container-candidate": "bun test scripts/attested-container-candidate.test.ts",
|
|
12798
12883
|
"emit:iapp-deployment-compatibility-vector": "bun run scripts/attested-container-compatibility-vector.ts emit",
|
|
12799
12884
|
"verify:iapp-deployment-compatibility-vector": "bun run scripts/attested-container-compatibility-vector.ts verify",
|
|
12885
|
+
"test:attested-container-compatibility-vector": "bun test scripts/attested-container-compatibility-vector.test.ts",
|
|
12800
12886
|
"issue:release-review": "bun run scripts/issue-npm-release-agent-review.ts",
|
|
12801
12887
|
prepublishOnly: "bun run scripts/verify-public-release.ts --mode=publish",
|
|
12802
12888
|
postinstall: "mkdir -p $HOME/.hasna/todos $HOME/.hasna/todos/training 2>/dev/null || true"
|
|
@@ -13485,6 +13571,7 @@ var TODOS_JSON_CONTRACTS = [
|
|
|
13485
13571
|
task_list_id: nullableIdField,
|
|
13486
13572
|
task_prefix: field(["string", "null"], "Optional task prefix.", true),
|
|
13487
13573
|
task_counter: field("integer", "Monotonic project task counter."),
|
|
13574
|
+
parent_id: field(["string", "null"], "Optional parent project id; null means top-level.", true),
|
|
13488
13575
|
created_at: isoDateField,
|
|
13489
13576
|
updated_at: isoDateField
|
|
13490
13577
|
},
|
|
@@ -16770,6 +16857,7 @@ function createAgentProjectDemoBundle() {
|
|
|
16770
16857
|
task_list_id: ids.list,
|
|
16771
16858
|
task_prefix: "DEMO",
|
|
16772
16859
|
task_counter: 4,
|
|
16860
|
+
parent_id: null,
|
|
16773
16861
|
created_at: createdAt,
|
|
16774
16862
|
updated_at: completedAt
|
|
16775
16863
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../../src/db/migrations.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"migrations.d.ts","sourceRoot":"","sources":["../../src/db/migrations.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,UAAU,UAwrDtB,CAAC"}
|
package/dist/db/projects.d.ts
CHANGED
|
@@ -5,6 +5,29 @@ export declare function createProject(input: CreateProjectInput, db?: Database):
|
|
|
5
5
|
export declare function getProject(id: string, db?: Database): Project | null;
|
|
6
6
|
export declare function getProjectByPath(path: string, db?: Database): Project | null;
|
|
7
7
|
export declare function listProjects(db?: Database): Project[];
|
|
8
|
+
export declare function listChildProjects(parentId: string, db?: Database): Project[];
|
|
9
|
+
/**
|
|
10
|
+
* Order projects so every parent precedes its children, regardless of name.
|
|
11
|
+
*
|
|
12
|
+
* projects.parent_id is an immediate foreign key, so importing a child before
|
|
13
|
+
* its parent fails the constraint and drops the child — and everything that
|
|
14
|
+
* points at it, such as its task rows — into the import's error list. Both
|
|
15
|
+
* round-trip import paths (SQLite snapshot restore and bundle import) rely on
|
|
16
|
+
* this ordering and must not depend on the export side's `ORDER BY name`.
|
|
17
|
+
*
|
|
18
|
+
* Stable and cycle-safe: rows whose parent is null, already emitted, or
|
|
19
|
+
* outside the given set keep their original relative order; a malformed input
|
|
20
|
+
* whose parent chain loops falls back to original order instead of hanging or
|
|
21
|
+
* dropping rows silently — the FK constraint then rejects the offending rows
|
|
22
|
+
* per-row and the import records the errors.
|
|
23
|
+
*/
|
|
24
|
+
export declare function orderProjectsParentFirst<T extends object>(projects: readonly T[]): T[];
|
|
25
|
+
/**
|
|
26
|
+
* Reject making `projectId` a descendant of `ancestorId`. Walks the ancestor
|
|
27
|
+
* chain of the candidate parent; if `projectId` appears anywhere in it, the
|
|
28
|
+
* new link would create a cycle (a project that is its own ancestor).
|
|
29
|
+
*/
|
|
30
|
+
export declare function assertNotProjectAncestor(projectId: string, ancestorId: string, db?: Database): void;
|
|
8
31
|
export declare function updateProject(id: string, input: UpdateProjectInput, db?: Database): Project;
|
|
9
32
|
/**
|
|
10
33
|
* Rename a project: update name and/or task_list_id (slug).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"projects.d.ts","sourceRoot":"","sources":["../../src/db/projects.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAoB,MAAM,YAAY,CAAC;AAC7D,OAAO,KAAK,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,OAAO,EAAE,aAAa,EAAoB,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAQpJ,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE5C;AAyBD,wBAAgB,aAAa,CAC3B,KAAK,EAAE,kBAAkB,EACzB,EAAE,CAAC,EAAE,QAAQ,GACZ,OAAO,
|
|
1
|
+
{"version":3,"file":"projects.d.ts","sourceRoot":"","sources":["../../src/db/projects.ts"],"names":[],"mappings":"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"}
|
package/dist/db/schema.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/db/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAItC,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,GAAG,IAAI,CAoChD;AA8BD,wBAAgB,YAAY,CAAC,EAAE,EAAE,QAAQ,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/db/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAItC,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,GAAG,IAAI,CAoChD;AA8BD,wBAAgB,YAAY,CAAC,EAAE,EAAE,QAAQ,GAAG,IAAI,CAw/C/C;AAED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,QAAQ,GAAG,IAAI,CA4BnD"}
|