@hasna/todos 0.11.52 → 0.11.54
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/README.md +14 -1
- package/dashboard/dist/assets/{index-C3fBxEWP.js → index-aJefI7kh.js} +1 -1
- package/dashboard/dist/index.html +1 -1
- package/dist/cli/commands/config-serve-commands.d.ts.map +1 -1
- package/dist/cli/commands/machines.d.ts.map +1 -1
- package/dist/cli/commands/storage-commands.d.ts +3 -0
- package/dist/cli/commands/storage-commands.d.ts.map +1 -0
- package/dist/cli/commands/task-commands.d.ts.map +1 -1
- package/dist/cli/helpers.d.ts +6 -0
- package/dist/cli/helpers.d.ts.map +1 -1
- package/dist/cli/index.js +4419 -877
- package/dist/contracts.js +289 -8
- package/dist/db/artifacts.d.ts.map +1 -1
- package/dist/db/builtin-templates.d.ts +0 -1
- package/dist/db/builtin-templates.d.ts.map +1 -1
- package/dist/db/database.d.ts.map +1 -1
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/db/tags.d.ts +26 -0
- package/dist/db/tags.d.ts.map +1 -0
- package/dist/db/task-commits.d.ts +14 -6
- package/dist/db/task-commits.d.ts.map +1 -1
- package/dist/db/tasks.d.ts +1 -1
- package/dist/db/tasks.d.ts.map +1 -1
- package/dist/index.d.ts +32 -60
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2473 -200
- package/dist/lib/agent-adapter-docs.d.ts +1 -1
- package/dist/lib/agent-adapter-docs.d.ts.map +1 -1
- package/dist/lib/agent-coordination.d.ts.map +1 -1
- package/dist/lib/agent-run-dispatcher.d.ts +5 -2
- package/dist/lib/agent-run-dispatcher.d.ts.map +1 -1
- package/dist/lib/agent-workflow-demo.d.ts +1 -1
- package/dist/lib/agent-workflow-demo.d.ts.map +1 -1
- package/dist/lib/db-backup.d.ts.map +1 -1
- package/dist/lib/headless-boundaries.d.ts +2 -2
- package/dist/lib/headless-boundaries.d.ts.map +1 -1
- package/dist/lib/import-export-bridge.d.ts.map +1 -1
- package/dist/lib/inbox-intake.d.ts.map +1 -1
- package/dist/lib/issue-importers.d.ts.map +1 -1
- package/dist/lib/machine-topology.d.ts +1 -1
- package/dist/lib/machine-topology.d.ts.map +1 -1
- package/dist/lib/native-storage-status.d.ts +65 -0
- package/dist/lib/native-storage-status.d.ts.map +1 -0
- package/dist/lib/nl-intake.d.ts.map +1 -1
- package/dist/lib/notification-reminders.d.ts.map +1 -1
- package/dist/lib/plan-execution.d.ts +1 -0
- package/dist/lib/plan-execution.d.ts.map +1 -1
- package/dist/lib/release-checks.d.ts.map +1 -1
- package/dist/lib/resource-snapshots.d.ts.map +1 -1
- package/dist/lib/saved-views.d.ts.map +1 -1
- package/dist/lib/secret-redaction.d.ts +1 -1
- package/dist/lib/secret-redaction.d.ts.map +1 -1
- package/dist/lib/task-scheduling.d.ts +1 -1
- package/dist/lib/task-scheduling.d.ts.map +1 -1
- package/dist/lib/template-library.d.ts +1 -1
- package/dist/lib/template-library.d.ts.map +1 -1
- package/dist/lib/user-scaffolds.d.ts.map +1 -1
- package/dist/lib/verification-evidence.d.ts +4 -4
- package/dist/lib/verification-evidence.d.ts.map +1 -1
- package/dist/lib/verification-providers.d.ts +3 -3
- package/dist/lib/verification-providers.d.ts.map +1 -1
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +526 -50
- package/dist/mcp/tools/task-crud.d.ts.map +1 -1
- package/dist/mcp/tools/task-project-tools.d.ts.map +1 -1
- package/dist/registry.js +289 -8
- package/dist/release-provenance.json +7 -0
- package/dist/server/index.js +554 -54
- package/dist/server/serve.d.ts.map +1 -1
- package/dist/storage/config.d.ts +86 -0
- package/dist/storage/config.d.ts.map +1 -0
- package/dist/storage/factory.d.ts +17 -0
- package/dist/storage/factory.d.ts.map +1 -0
- package/dist/storage/hybrid.d.ts +26 -0
- package/dist/storage/hybrid.d.ts.map +1 -0
- package/dist/storage/index.d.ts +15 -0
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/local-sqlite.d.ts.map +1 -1
- package/dist/storage/postgres-adapter.d.ts +11 -0
- package/dist/storage/postgres-adapter.d.ts.map +1 -0
- package/dist/storage/postgres-sync.d.ts +44 -0
- package/dist/storage/postgres-sync.d.ts.map +1 -0
- package/dist/storage/s3-artifact-sync.d.ts +75 -0
- package/dist/storage/s3-artifact-sync.d.ts.map +1 -0
- package/dist/storage/s3-artifacts.d.ts +51 -0
- package/dist/storage/s3-artifacts.d.ts.map +1 -0
- package/dist/storage/sqlite-snapshot.d.ts +5 -0
- package/dist/storage/sqlite-snapshot.d.ts.map +1 -0
- package/dist/storage.d.ts +2 -1
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +2053 -10
- package/package.json +2 -1
- package/dist/cli/brains.d.ts +0 -3
- package/dist/cli/brains.d.ts.map +0 -1
- package/dist/db/file-locks.d.ts +0 -43
- package/dist/db/file-locks.d.ts.map +0 -1
- package/dist/db/project-agent-roles.d.ts +0 -34
- package/dist/db/project-agent-roles.d.ts.map +0 -1
- package/dist/db/task-claim.d.ts +0 -7
- package/dist/db/task-claim.d.ts.map +0 -1
- package/dist/db/task-workflow.d.ts +0 -7
- package/dist/db/task-workflow.d.ts.map +0 -1
- package/dist/lib/north-star.d.ts +0 -33
- package/dist/lib/north-star.d.ts.map +0 -1
- package/dist/lib/public-release-gate.d.ts +0 -57
- package/dist/lib/public-release-gate.d.ts.map +0 -1
- package/dist/lib/task-runner.d.ts +0 -101
- package/dist/lib/task-runner.d.ts.map +0 -1
- package/dist/mcp/tools/access-profiles.d.ts +0 -8
- package/dist/mcp/tools/access-profiles.d.ts.map +0 -1
- package/dist/mcp/tools/activity-audit.d.ts +0 -9
- package/dist/mcp/tools/activity-audit.d.ts.map +0 -1
- package/dist/mcp/tools/agent-adapter-docs.d.ts +0 -8
- package/dist/mcp/tools/agent-adapter-docs.d.ts.map +0 -1
- package/dist/mcp/tools/agent-coordination.d.ts +0 -9
- package/dist/mcp/tools/agent-coordination.d.ts.map +0 -1
- package/dist/mcp/tools/agent-runs.d.ts +0 -9
- package/dist/mcp/tools/agent-runs.d.ts.map +0 -1
- package/dist/mcp/tools/agent-workflow-demo.d.ts +0 -8
- package/dist/mcp/tools/agent-workflow-demo.d.ts.map +0 -1
- package/dist/mcp/tools/approval-gates.d.ts +0 -9
- package/dist/mcp/tools/approval-gates.d.ts.map +0 -1
- package/dist/mcp/tools/artifacts.d.ts +0 -9
- package/dist/mcp/tools/artifacts.d.ts.map +0 -1
- package/dist/mcp/tools/branch-work-plans.d.ts +0 -8
- package/dist/mcp/tools/branch-work-plans.d.ts.map +0 -1
- package/dist/mcp/tools/cli-docs.d.ts +0 -8
- package/dist/mcp/tools/cli-docs.d.ts.map +0 -1
- package/dist/mcp/tools/command-aliases.d.ts +0 -8
- package/dist/mcp/tools/command-aliases.d.ts.map +0 -1
- package/dist/mcp/tools/context-packs.d.ts +0 -9
- package/dist/mcp/tools/context-packs.d.ts.map +0 -1
- package/dist/mcp/tools/crypto.d.ts +0 -8
- package/dist/mcp/tools/crypto.d.ts.map +0 -1
- package/dist/mcp/tools/db-backup.d.ts +0 -8
- package/dist/mcp/tools/db-backup.d.ts.map +0 -1
- package/dist/mcp/tools/decision-records.d.ts +0 -9
- package/dist/mcp/tools/decision-records.d.ts.map +0 -1
- package/dist/mcp/tools/dependency-graph.d.ts +0 -9
- package/dist/mcp/tools/dependency-graph.d.ts.map +0 -1
- package/dist/mcp/tools/failure-triage.d.ts +0 -9
- package/dist/mcp/tools/failure-triage.d.ts.map +0 -1
- package/dist/mcp/tools/feature-manifest.d.ts +0 -8
- package/dist/mcp/tools/feature-manifest.d.ts.map +0 -1
- package/dist/mcp/tools/git-traceability.d.ts +0 -9
- package/dist/mcp/tools/git-traceability.d.ts.map +0 -1
- package/dist/mcp/tools/goal.d.ts +0 -9
- package/dist/mcp/tools/goal.d.ts.map +0 -1
- package/dist/mcp/tools/handoff-packets.d.ts +0 -9
- package/dist/mcp/tools/handoff-packets.d.ts.map +0 -1
- package/dist/mcp/tools/import-export-bridge.d.ts +0 -9
- package/dist/mcp/tools/import-export-bridge.d.ts.map +0 -1
- package/dist/mcp/tools/inbox-intake.d.ts +0 -9
- package/dist/mcp/tools/inbox-intake.d.ts.map +0 -1
- package/dist/mcp/tools/issue-importers.d.ts +0 -9
- package/dist/mcp/tools/issue-importers.d.ts.map +0 -1
- package/dist/mcp/tools/json-schemas.d.ts +0 -8
- package/dist/mcp/tools/json-schemas.d.ts.map +0 -1
- package/dist/mcp/tools/machine-topology.d.ts +0 -8
- package/dist/mcp/tools/machine-topology.d.ts.map +0 -1
- package/dist/mcp/tools/mention-resolver.d.ts +0 -9
- package/dist/mcp/tools/mention-resolver.d.ts.map +0 -1
- package/dist/mcp/tools/nl-intake.d.ts +0 -9
- package/dist/mcp/tools/nl-intake.d.ts.map +0 -1
- package/dist/mcp/tools/notification-reminders.d.ts +0 -9
- package/dist/mcp/tools/notification-reminders.d.ts.map +0 -1
- package/dist/mcp/tools/parity.d.ts +0 -8
- package/dist/mcp/tools/parity.d.ts.map +0 -1
- package/dist/mcp/tools/plan-execution.d.ts +0 -9
- package/dist/mcp/tools/plan-execution.d.ts.map +0 -1
- package/dist/mcp/tools/policy-packs.d.ts +0 -9
- package/dist/mcp/tools/policy-packs.d.ts.map +0 -1
- package/dist/mcp/tools/project-bootstrap.d.ts +0 -8
- package/dist/mcp/tools/project-bootstrap.d.ts.map +0 -1
- package/dist/mcp/tools/release-checks.d.ts +0 -8
- package/dist/mcp/tools/release-checks.d.ts.map +0 -1
- package/dist/mcp/tools/release-notes.d.ts +0 -9
- package/dist/mcp/tools/release-notes.d.ts.map +0 -1
- package/dist/mcp/tools/report-exports.d.ts +0 -9
- package/dist/mcp/tools/report-exports.d.ts.map +0 -1
- package/dist/mcp/tools/resource-subscriptions.d.ts +0 -8
- package/dist/mcp/tools/resource-subscriptions.d.ts.map +0 -1
- package/dist/mcp/tools/run-records.d.ts +0 -9
- package/dist/mcp/tools/run-records.d.ts.map +0 -1
- package/dist/mcp/tools/sandbox.d.ts +0 -8
- package/dist/mcp/tools/sandbox.d.ts.map +0 -1
- package/dist/mcp/tools/saved-views.d.ts +0 -9
- package/dist/mcp/tools/saved-views.d.ts.map +0 -1
- package/dist/mcp/tools/secret-redaction.d.ts +0 -8
- package/dist/mcp/tools/secret-redaction.d.ts.map +0 -1
- package/dist/mcp/tools/task-dedupe.d.ts +0 -9
- package/dist/mcp/tools/task-dedupe.d.ts.map +0 -1
- package/dist/mcp/tools/task-scheduling.d.ts +0 -9
- package/dist/mcp/tools/task-scheduling.d.ts.map +0 -1
- package/dist/mcp/tools/template-library.d.ts +0 -8
- package/dist/mcp/tools/template-library.d.ts.map +0 -1
- package/dist/mcp/tools/terminal-notifications.d.ts +0 -9
- package/dist/mcp/tools/terminal-notifications.d.ts.map +0 -1
- package/dist/mcp/tools/todos-md.d.ts +0 -8
- package/dist/mcp/tools/todos-md.d.ts.map +0 -1
- package/dist/mcp/tools/user-scaffolds.d.ts +0 -8
- package/dist/mcp/tools/user-scaffolds.d.ts.map +0 -1
- package/dist/mcp/tools/verification.d.ts +0 -9
- package/dist/mcp/tools/verification.d.ts.map +0 -1
- package/dist/mcp/tools/webhooks.d.ts +0 -8
- package/dist/mcp/tools/webhooks.d.ts.map +0 -1
- package/dist/mcp/tools/workspace-trust.d.ts +0 -8
- package/dist/mcp/tools/workspace-trust.d.ts.map +0 -1
- package/dist/test/no-network.d.ts +0 -7
- package/dist/test/no-network.d.ts.map +0 -1
package/dist/mcp/index.js
CHANGED
|
@@ -1224,6 +1224,15 @@ function ensureSchema(db) {
|
|
|
1224
1224
|
task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
1225
1225
|
tag TEXT NOT NULL, PRIMARY KEY (task_id, tag)
|
|
1226
1226
|
)`);
|
|
1227
|
+
ensureTable("tags", `
|
|
1228
|
+
CREATE TABLE tags (
|
|
1229
|
+
id TEXT PRIMARY KEY,
|
|
1230
|
+
name TEXT NOT NULL UNIQUE,
|
|
1231
|
+
color TEXT,
|
|
1232
|
+
description TEXT,
|
|
1233
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
1234
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
1235
|
+
)`);
|
|
1227
1236
|
ensureTable("task_dependencies", `
|
|
1228
1237
|
CREATE TABLE task_dependencies (
|
|
1229
1238
|
task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
@@ -1437,6 +1446,36 @@ function ensureSchema(db) {
|
|
|
1437
1446
|
ensureIndex("CREATE INDEX IF NOT EXISTS idx_task_git_refs_task ON task_git_refs(task_id)");
|
|
1438
1447
|
ensureIndex("CREATE INDEX IF NOT EXISTS idx_task_git_refs_lookup ON task_git_refs(ref_type, name)");
|
|
1439
1448
|
ensureIndex("CREATE INDEX IF NOT EXISTS idx_task_git_refs_url ON task_git_refs(url)");
|
|
1449
|
+
ensureTable("task_commits", `
|
|
1450
|
+
CREATE TABLE task_commits (
|
|
1451
|
+
id TEXT PRIMARY KEY,
|
|
1452
|
+
task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
1453
|
+
sha TEXT NOT NULL,
|
|
1454
|
+
message TEXT,
|
|
1455
|
+
author TEXT,
|
|
1456
|
+
files_changed TEXT,
|
|
1457
|
+
committed_at TEXT,
|
|
1458
|
+
branch TEXT,
|
|
1459
|
+
pr_url TEXT,
|
|
1460
|
+
pr_number INTEGER,
|
|
1461
|
+
pr_state TEXT,
|
|
1462
|
+
ci_snapshot TEXT,
|
|
1463
|
+
release_tag TEXT,
|
|
1464
|
+
repo_path TEXT,
|
|
1465
|
+
traceability TEXT DEFAULT '{}',
|
|
1466
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
1467
|
+
UNIQUE(task_id, sha)
|
|
1468
|
+
)`);
|
|
1469
|
+
ensureColumn("task_commits", "branch", "TEXT");
|
|
1470
|
+
ensureColumn("task_commits", "pr_url", "TEXT");
|
|
1471
|
+
ensureColumn("task_commits", "pr_number", "INTEGER");
|
|
1472
|
+
ensureColumn("task_commits", "pr_state", "TEXT");
|
|
1473
|
+
ensureColumn("task_commits", "ci_snapshot", "TEXT");
|
|
1474
|
+
ensureColumn("task_commits", "release_tag", "TEXT");
|
|
1475
|
+
ensureColumn("task_commits", "repo_path", "TEXT");
|
|
1476
|
+
ensureColumn("task_commits", "traceability", "TEXT DEFAULT '{}'");
|
|
1477
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_task_commits_task ON task_commits(task_id)");
|
|
1478
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_task_commits_sha ON task_commits(sha)");
|
|
1440
1479
|
ensureTable("task_verifications", `
|
|
1441
1480
|
CREATE TABLE task_verifications (
|
|
1442
1481
|
id TEXT PRIMARY KEY,
|
|
@@ -1621,6 +1660,9 @@ function ensureSchema(db) {
|
|
|
1621
1660
|
ensureColumn("tasks", "max_retries", "INTEGER DEFAULT 3");
|
|
1622
1661
|
ensureColumn("tasks", "retry_after", "TEXT");
|
|
1623
1662
|
ensureColumn("tasks", "sla_minutes", "INTEGER");
|
|
1663
|
+
ensureColumn("tasks", "scheduled_start_at", "TEXT");
|
|
1664
|
+
ensureColumn("tasks", "priority_score", "INTEGER");
|
|
1665
|
+
ensureColumn("tasks", "priority_reason", "TEXT");
|
|
1624
1666
|
ensureColumn("tasks", "archived_at", "TEXT");
|
|
1625
1667
|
ensureColumn("agents", "role", "TEXT DEFAULT 'agent'");
|
|
1626
1668
|
ensureColumn("agents", "permissions", `TEXT DEFAULT '["*"]'`);
|
|
@@ -1743,6 +1785,7 @@ function ensureSchema(db) {
|
|
|
1743
1785
|
ensureIndex("CREATE INDEX IF NOT EXISTS idx_task_lists_slug ON task_lists(slug)");
|
|
1744
1786
|
ensureIndex("CREATE INDEX IF NOT EXISTS idx_task_tags_tag ON task_tags(tag)");
|
|
1745
1787
|
ensureIndex("CREATE INDEX IF NOT EXISTS idx_task_tags_task ON task_tags(task_id)");
|
|
1788
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_tags_name ON tags(name)");
|
|
1746
1789
|
ensureIndex("CREATE INDEX IF NOT EXISTS idx_plans_project ON plans(project_id)");
|
|
1747
1790
|
ensureIndex("CREATE INDEX IF NOT EXISTS idx_plans_status ON plans(status)");
|
|
1748
1791
|
ensureIndex("CREATE INDEX IF NOT EXISTS idx_plans_task_list ON plans(task_list_id)");
|
|
@@ -1880,6 +1923,217 @@ function ensureSchema(db) {
|
|
|
1880
1923
|
ensureIndex("CREATE INDEX IF NOT EXISTS idx_cycles_dates ON cycles(start_date, end_date)");
|
|
1881
1924
|
ensureColumn("tasks", "cycle_id", "TEXT REFERENCES cycles(id) ON DELETE SET NULL");
|
|
1882
1925
|
ensureIndex("CREATE INDEX IF NOT EXISTS idx_tasks_cycle ON tasks(cycle_id) WHERE cycle_id IS NOT NULL");
|
|
1926
|
+
ensureTable("labels", `
|
|
1927
|
+
CREATE TABLE labels (
|
|
1928
|
+
id TEXT PRIMARY KEY,
|
|
1929
|
+
project_id TEXT REFERENCES projects(id) ON DELETE CASCADE,
|
|
1930
|
+
name TEXT NOT NULL,
|
|
1931
|
+
color TEXT,
|
|
1932
|
+
description TEXT,
|
|
1933
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
1934
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
1935
|
+
UNIQUE(project_id, name)
|
|
1936
|
+
)`);
|
|
1937
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_labels_project ON labels(project_id)");
|
|
1938
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_labels_name ON labels(name)");
|
|
1939
|
+
ensureTable("task_labels", `
|
|
1940
|
+
CREATE TABLE task_labels (
|
|
1941
|
+
task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
1942
|
+
label_id TEXT NOT NULL REFERENCES labels(id) ON DELETE CASCADE,
|
|
1943
|
+
PRIMARY KEY (task_id, label_id)
|
|
1944
|
+
)`);
|
|
1945
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_task_labels_task ON task_labels(task_id)");
|
|
1946
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_task_labels_label ON task_labels(label_id)");
|
|
1947
|
+
ensureTable("custom_field_definitions", `
|
|
1948
|
+
CREATE TABLE custom_field_definitions (
|
|
1949
|
+
id TEXT PRIMARY KEY,
|
|
1950
|
+
project_id TEXT REFERENCES projects(id) ON DELETE CASCADE,
|
|
1951
|
+
name TEXT NOT NULL,
|
|
1952
|
+
slug TEXT NOT NULL,
|
|
1953
|
+
field_type TEXT NOT NULL CHECK(field_type IN ('text', 'number', 'boolean', 'date', 'enum')),
|
|
1954
|
+
options TEXT DEFAULT '[]',
|
|
1955
|
+
required INTEGER NOT NULL DEFAULT 0,
|
|
1956
|
+
default_value TEXT,
|
|
1957
|
+
sort_order INTEGER NOT NULL DEFAULT 0,
|
|
1958
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
1959
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
1960
|
+
UNIQUE(project_id, slug)
|
|
1961
|
+
)`);
|
|
1962
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_custom_fields_project ON custom_field_definitions(project_id)");
|
|
1963
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_custom_fields_slug ON custom_field_definitions(slug)");
|
|
1964
|
+
ensureTable("task_custom_field_values", `
|
|
1965
|
+
CREATE TABLE task_custom_field_values (
|
|
1966
|
+
task_id TEXT NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
1967
|
+
field_id TEXT NOT NULL REFERENCES custom_field_definitions(id) ON DELETE CASCADE,
|
|
1968
|
+
value TEXT,
|
|
1969
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
1970
|
+
PRIMARY KEY (task_id, field_id)
|
|
1971
|
+
)`);
|
|
1972
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_task_custom_values_task ON task_custom_field_values(task_id)");
|
|
1973
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_task_custom_values_field ON task_custom_field_values(field_id)");
|
|
1974
|
+
ensureTable("saved_views", `
|
|
1975
|
+
CREATE TABLE saved_views (
|
|
1976
|
+
id TEXT PRIMARY KEY,
|
|
1977
|
+
name TEXT NOT NULL UNIQUE,
|
|
1978
|
+
slug TEXT NOT NULL UNIQUE,
|
|
1979
|
+
entity_type TEXT NOT NULL DEFAULT 'task',
|
|
1980
|
+
filters TEXT NOT NULL DEFAULT '{}',
|
|
1981
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
1982
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
1983
|
+
)`);
|
|
1984
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_saved_views_slug ON saved_views(slug)");
|
|
1985
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_saved_views_entity ON saved_views(entity_type)");
|
|
1986
|
+
ensureTable("decision_records", `
|
|
1987
|
+
CREATE TABLE decision_records (
|
|
1988
|
+
id TEXT PRIMARY KEY,
|
|
1989
|
+
project_id TEXT REFERENCES projects(id) ON DELETE SET NULL,
|
|
1990
|
+
task_id TEXT REFERENCES tasks(id) ON DELETE SET NULL,
|
|
1991
|
+
plan_id TEXT REFERENCES plans(id) ON DELETE SET NULL,
|
|
1992
|
+
agent_id TEXT,
|
|
1993
|
+
sequence_num INTEGER NOT NULL,
|
|
1994
|
+
short_ref TEXT NOT NULL UNIQUE,
|
|
1995
|
+
title TEXT NOT NULL,
|
|
1996
|
+
status TEXT NOT NULL DEFAULT 'proposed' CHECK(status IN ('proposed', 'accepted', 'deprecated', 'superseded', 'rejected')),
|
|
1997
|
+
context TEXT,
|
|
1998
|
+
decision TEXT NOT NULL,
|
|
1999
|
+
consequences TEXT,
|
|
2000
|
+
alternatives TEXT DEFAULT '[]',
|
|
2001
|
+
tags TEXT DEFAULT '[]',
|
|
2002
|
+
supersedes_id TEXT REFERENCES decision_records(id) ON DELETE SET NULL,
|
|
2003
|
+
superseded_by_id TEXT REFERENCES decision_records(id) ON DELETE SET NULL,
|
|
2004
|
+
metadata TEXT DEFAULT '{}',
|
|
2005
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
2006
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
2007
|
+
)`);
|
|
2008
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_decision_records_project ON decision_records(project_id)");
|
|
2009
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_decision_records_task ON decision_records(task_id)");
|
|
2010
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_decision_records_plan ON decision_records(plan_id)");
|
|
2011
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_decision_records_status ON decision_records(status)");
|
|
2012
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_decision_records_short_ref ON decision_records(short_ref)");
|
|
2013
|
+
ensureTable("knowledge_snapshots", `
|
|
2014
|
+
CREATE TABLE knowledge_snapshots (
|
|
2015
|
+
id TEXT PRIMARY KEY,
|
|
2016
|
+
project_id TEXT REFERENCES projects(id) ON DELETE SET NULL,
|
|
2017
|
+
title TEXT NOT NULL,
|
|
2018
|
+
summary TEXT,
|
|
2019
|
+
content_hash TEXT NOT NULL,
|
|
2020
|
+
snapshot TEXT NOT NULL,
|
|
2021
|
+
decision_ids TEXT DEFAULT '[]',
|
|
2022
|
+
topics TEXT DEFAULT '[]',
|
|
2023
|
+
source TEXT NOT NULL DEFAULT 'auto' CHECK(source IN ('manual', 'auto', 'import')),
|
|
2024
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
2025
|
+
)`);
|
|
2026
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_knowledge_snapshots_project ON knowledge_snapshots(project_id)");
|
|
2027
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_knowledge_snapshots_hash ON knowledge_snapshots(content_hash)");
|
|
2028
|
+
ensureTable("verification_records", `
|
|
2029
|
+
CREATE TABLE verification_records (
|
|
2030
|
+
id TEXT PRIMARY KEY,
|
|
2031
|
+
task_id TEXT REFERENCES tasks(id) ON DELETE CASCADE,
|
|
2032
|
+
provider_name TEXT NOT NULL,
|
|
2033
|
+
provider_type TEXT NOT NULL,
|
|
2034
|
+
status TEXT NOT NULL DEFAULT 'unknown' CHECK(status IN ('passed', 'failed', 'unknown')),
|
|
2035
|
+
summary TEXT,
|
|
2036
|
+
evidence TEXT DEFAULT '{}',
|
|
2037
|
+
artifact_id TEXT,
|
|
2038
|
+
started_at TEXT,
|
|
2039
|
+
completed_at TEXT,
|
|
2040
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
2041
|
+
)`);
|
|
2042
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_verification_records_task ON verification_records(task_id)");
|
|
2043
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_verification_records_status ON verification_records(status)");
|
|
2044
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_verification_records_created ON verification_records(created_at)");
|
|
2045
|
+
ensureTable("task_leases", `
|
|
2046
|
+
CREATE TABLE task_leases (
|
|
2047
|
+
task_id TEXT PRIMARY KEY REFERENCES tasks(id) ON DELETE CASCADE,
|
|
2048
|
+
agent_id TEXT NOT NULL,
|
|
2049
|
+
acquired_at TEXT NOT NULL,
|
|
2050
|
+
expires_at TEXT NOT NULL,
|
|
2051
|
+
heartbeat_at TEXT,
|
|
2052
|
+
steal_count INTEGER NOT NULL DEFAULT 0,
|
|
2053
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
2054
|
+
)`);
|
|
2055
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_task_leases_agent ON task_leases(agent_id)");
|
|
2056
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_task_leases_expires ON task_leases(expires_at)");
|
|
2057
|
+
ensureTable("reminder_preferences", `
|
|
2058
|
+
CREATE TABLE reminder_preferences (
|
|
2059
|
+
id TEXT PRIMARY KEY,
|
|
2060
|
+
due_soon_hours INTEGER NOT NULL DEFAULT 24,
|
|
2061
|
+
sla_warning_minutes INTEGER NOT NULL DEFAULT 30,
|
|
2062
|
+
enabled INTEGER NOT NULL DEFAULT 1,
|
|
2063
|
+
desktop_notify INTEGER NOT NULL DEFAULT 0,
|
|
2064
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
2065
|
+
)`);
|
|
2066
|
+
ensureTable("notification_reminders", `
|
|
2067
|
+
CREATE TABLE notification_reminders (
|
|
2068
|
+
id TEXT PRIMARY KEY,
|
|
2069
|
+
task_id TEXT REFERENCES tasks(id) ON DELETE CASCADE,
|
|
2070
|
+
reminder_type TEXT NOT NULL CHECK(reminder_type IN ('due_soon', 'due_overdue', 'sla_warning', 'sla_breach', 'custom')),
|
|
2071
|
+
title TEXT NOT NULL,
|
|
2072
|
+
message TEXT,
|
|
2073
|
+
trigger_at TEXT NOT NULL,
|
|
2074
|
+
status TEXT NOT NULL DEFAULT 'pending' CHECK(status IN ('pending', 'fired', 'dismissed', 'snoozed')),
|
|
2075
|
+
snoozed_until TEXT,
|
|
2076
|
+
project_id TEXT REFERENCES projects(id) ON DELETE SET NULL,
|
|
2077
|
+
agent_id TEXT,
|
|
2078
|
+
priority TEXT NOT NULL DEFAULT 'medium',
|
|
2079
|
+
metadata TEXT DEFAULT '{}',
|
|
2080
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
2081
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
2082
|
+
fired_at TEXT,
|
|
2083
|
+
dismissed_at TEXT
|
|
2084
|
+
)`);
|
|
2085
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_notification_reminders_task ON notification_reminders(task_id)");
|
|
2086
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_notification_reminders_status ON notification_reminders(status)");
|
|
2087
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_notification_reminders_trigger ON notification_reminders(trigger_at)");
|
|
2088
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_notification_reminders_project ON notification_reminders(project_id)");
|
|
2089
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_notification_reminders_agent ON notification_reminders(agent_id)");
|
|
2090
|
+
ensureTable("run_records", `
|
|
2091
|
+
CREATE TABLE run_records (
|
|
2092
|
+
id TEXT PRIMARY KEY,
|
|
2093
|
+
agent_run_id TEXT,
|
|
2094
|
+
agent_id TEXT,
|
|
2095
|
+
objective TEXT,
|
|
2096
|
+
plan_id TEXT REFERENCES plans(id) ON DELETE SET NULL,
|
|
2097
|
+
claimed_task_ids TEXT DEFAULT '[]',
|
|
2098
|
+
commands TEXT DEFAULT '[]',
|
|
2099
|
+
stdout_summary TEXT,
|
|
2100
|
+
stderr_summary TEXT,
|
|
2101
|
+
files_touched TEXT DEFAULT '[]',
|
|
2102
|
+
verification_results TEXT DEFAULT '[]',
|
|
2103
|
+
artifact_ids TEXT DEFAULT '[]',
|
|
2104
|
+
status_transitions TEXT DEFAULT '[]',
|
|
2105
|
+
status TEXT NOT NULL DEFAULT 'active' CHECK(status IN ('active', 'completed', 'failed', 'archived')),
|
|
2106
|
+
replay_bundle TEXT,
|
|
2107
|
+
metadata TEXT DEFAULT '{}',
|
|
2108
|
+
started_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
2109
|
+
completed_at TEXT,
|
|
2110
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
2111
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
2112
|
+
)`);
|
|
2113
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_run_records_agent_run ON run_records(agent_run_id)");
|
|
2114
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_run_records_agent ON run_records(agent_id)");
|
|
2115
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_run_records_plan ON run_records(plan_id)");
|
|
2116
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_run_records_status ON run_records(status)");
|
|
2117
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_run_records_started ON run_records(started_at)");
|
|
2118
|
+
ensureTable("activity_log", `
|
|
2119
|
+
CREATE TABLE activity_log (
|
|
2120
|
+
id TEXT PRIMARY KEY,
|
|
2121
|
+
entity_type TEXT NOT NULL,
|
|
2122
|
+
entity_id TEXT NOT NULL,
|
|
2123
|
+
action TEXT NOT NULL,
|
|
2124
|
+
field TEXT,
|
|
2125
|
+
old_value TEXT,
|
|
2126
|
+
new_value TEXT,
|
|
2127
|
+
actor_id TEXT,
|
|
2128
|
+
session_id TEXT,
|
|
2129
|
+
machine_id TEXT,
|
|
2130
|
+
metadata TEXT DEFAULT '{}',
|
|
2131
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
2132
|
+
)`);
|
|
2133
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_activity_log_entity ON activity_log(entity_type, entity_id)");
|
|
2134
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_activity_log_actor ON activity_log(actor_id)");
|
|
2135
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_activity_log_action ON activity_log(action)");
|
|
2136
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_activity_log_created ON activity_log(created_at)");
|
|
1883
2137
|
ensureTable("api_keys", `
|
|
1884
2138
|
CREATE TABLE api_keys (
|
|
1885
2139
|
id TEXT PRIMARY KEY,
|
|
@@ -2331,11 +2585,17 @@ function ensureDir(filePath) {
|
|
|
2331
2585
|
}
|
|
2332
2586
|
}
|
|
2333
2587
|
function getDatabase(dbPath) {
|
|
2334
|
-
if (_db)
|
|
2335
|
-
return _db;
|
|
2336
2588
|
const path = dbPath || getDbPath();
|
|
2589
|
+
if (_db && _dbPath === path)
|
|
2590
|
+
return _db;
|
|
2591
|
+
if (_db && _dbPath !== path) {
|
|
2592
|
+
_db.close();
|
|
2593
|
+
_db = null;
|
|
2594
|
+
_dbPath = null;
|
|
2595
|
+
}
|
|
2337
2596
|
ensureDir(path);
|
|
2338
2597
|
_db = new Database(path);
|
|
2598
|
+
_dbPath = path;
|
|
2339
2599
|
_db.run("PRAGMA journal_mode = WAL");
|
|
2340
2600
|
_db.run("PRAGMA busy_timeout = 5000");
|
|
2341
2601
|
_db.run("PRAGMA foreign_keys = ON");
|
|
@@ -2348,10 +2608,12 @@ function closeDatabase() {
|
|
|
2348
2608
|
if (_db) {
|
|
2349
2609
|
_db.close();
|
|
2350
2610
|
_db = null;
|
|
2611
|
+
_dbPath = null;
|
|
2351
2612
|
}
|
|
2352
2613
|
}
|
|
2353
2614
|
function resetDatabase() {
|
|
2354
2615
|
_db = null;
|
|
2616
|
+
_dbPath = null;
|
|
2355
2617
|
}
|
|
2356
2618
|
function now() {
|
|
2357
2619
|
return new Date().toISOString();
|
|
@@ -2412,7 +2674,7 @@ function resolvePartialId(db, table, partialId) {
|
|
|
2412
2674
|
}
|
|
2413
2675
|
return null;
|
|
2414
2676
|
}
|
|
2415
|
-
var LOCK_EXPIRY_MINUTES = 30, _db = null, ALLOWED_TABLES;
|
|
2677
|
+
var LOCK_EXPIRY_MINUTES = 30, _db = null, _dbPath = null, ALLOWED_TABLES;
|
|
2416
2678
|
var init_database = __esm(() => {
|
|
2417
2679
|
init_schema();
|
|
2418
2680
|
init_machines();
|
|
@@ -8423,9 +8685,10 @@ function redactExportRecord(record) {
|
|
|
8423
8685
|
}
|
|
8424
8686
|
return base;
|
|
8425
8687
|
}
|
|
8426
|
-
var REDACTION_PLACEHOLDER = "[REDACTED]", DEFAULT_PATTERNS, DEFAULT_ALLOWLIST, customRedactors;
|
|
8688
|
+
var SECRET_REDACTION_SCHEMA, REDACTION_PLACEHOLDER = "[REDACTED]", DEFAULT_PATTERNS, DEFAULT_ALLOWLIST, customRedactors;
|
|
8427
8689
|
var init_secret_redaction = __esm(() => {
|
|
8428
8690
|
init_redaction();
|
|
8691
|
+
SECRET_REDACTION_SCHEMA = ["todos", "secret_redaction", "v1"].join(".");
|
|
8429
8692
|
DEFAULT_PATTERNS = [
|
|
8430
8693
|
{ name: "openai_sk", pattern: /\bsk-[a-zA-Z0-9]{10,}\b/g },
|
|
8431
8694
|
{ name: "github_pat", pattern: /\bghp_[a-zA-Z0-9]{20,}\b/g },
|
|
@@ -12293,11 +12556,19 @@ function getTaskVerifications(taskId, db) {
|
|
|
12293
12556
|
}
|
|
12294
12557
|
function getTaskTraceability(taskId, db) {
|
|
12295
12558
|
const d = db || getDatabase();
|
|
12559
|
+
const commits = getTaskCommits(taskId, d);
|
|
12560
|
+
const gitRefs = getTaskGitRefs(taskId, d);
|
|
12296
12561
|
return {
|
|
12297
12562
|
task_id: taskId,
|
|
12298
|
-
commits
|
|
12299
|
-
git_refs:
|
|
12300
|
-
verifications: getTaskVerifications(taskId, d)
|
|
12563
|
+
commits,
|
|
12564
|
+
git_refs: gitRefs,
|
|
12565
|
+
verifications: getTaskVerifications(taskId, d),
|
|
12566
|
+
branches: Array.from(new Set([
|
|
12567
|
+
...commits.map((commit) => commit.branch).filter((branch) => Boolean(branch)),
|
|
12568
|
+
...gitRefs.filter((ref) => ref.ref_type === "branch").map((ref) => ref.name)
|
|
12569
|
+
])).sort(),
|
|
12570
|
+
release_tags: Array.from(new Set(commits.map((commit) => commit.release_tag).filter((tag) => Boolean(tag)))).sort(),
|
|
12571
|
+
pull_requests: commits.filter((commit) => commit.pr_url).map((commit) => ({ url: commit.pr_url, state: commit.pr_state, number: commit.pr_number }))
|
|
12301
12572
|
};
|
|
12302
12573
|
}
|
|
12303
12574
|
var init_task_commits = __esm(() => {
|
|
@@ -14069,6 +14340,13 @@ function registerTaskCrudTools(server, ctx) {
|
|
|
14069
14340
|
}
|
|
14070
14341
|
return current.version;
|
|
14071
14342
|
}
|
|
14343
|
+
function resolveAssignee(value) {
|
|
14344
|
+
try {
|
|
14345
|
+
return resolveId(value, "agents");
|
|
14346
|
+
} catch {
|
|
14347
|
+
return value;
|
|
14348
|
+
}
|
|
14349
|
+
}
|
|
14072
14350
|
if (shouldRegisterTool("create_task")) {
|
|
14073
14351
|
server.tool("create_task", "Create a new task in a project. Pass short_id=null to auto-generate.", {
|
|
14074
14352
|
title: exports_external.string().describe("Task title"),
|
|
@@ -14091,7 +14369,7 @@ function registerTaskCrudTools(server, ctx) {
|
|
|
14091
14369
|
const { depends_on, assigned_to, project_id, task_list_id, tags, estimate, confidence, retry_count, deadline, ...rest } = params;
|
|
14092
14370
|
const resolved = { ...rest };
|
|
14093
14371
|
if (assigned_to)
|
|
14094
|
-
resolved.assigned_to =
|
|
14372
|
+
resolved.assigned_to = resolveAssignee(assigned_to);
|
|
14095
14373
|
if (project_id)
|
|
14096
14374
|
resolved.project_id = resolveId(project_id, "projects");
|
|
14097
14375
|
if (task_list_id)
|
|
@@ -14135,7 +14413,7 @@ function registerTaskCrudTools(server, ctx) {
|
|
|
14135
14413
|
if (params.task_list_id)
|
|
14136
14414
|
resolved.task_list_id = resolveId(params.task_list_id, "task_lists");
|
|
14137
14415
|
if (params.assigned_to)
|
|
14138
|
-
resolved.assigned_to =
|
|
14416
|
+
resolved.assigned_to = resolveAssignee(params.assigned_to);
|
|
14139
14417
|
const tasks = listTasks(resolved, undefined);
|
|
14140
14418
|
if (tasks.length === 0)
|
|
14141
14419
|
return { content: [{ type: "text", text: "No tasks found." }] };
|
|
@@ -14232,7 +14510,7 @@ ${task.description}` : null
|
|
|
14232
14510
|
if (resolved.assigned_to === "")
|
|
14233
14511
|
resolved.assigned_to = null;
|
|
14234
14512
|
if (resolved.assigned_to && typeof resolved.assigned_to === "string")
|
|
14235
|
-
resolved.assigned_to =
|
|
14513
|
+
resolved.assigned_to = resolveAssignee(resolved.assigned_to);
|
|
14236
14514
|
if (resolved.project_id && typeof resolved.project_id === "string")
|
|
14237
14515
|
resolved.project_id = resolveId(resolved.project_id, "projects");
|
|
14238
14516
|
if (resolved.task_list_id && typeof resolved.task_list_id === "string")
|
|
@@ -14446,6 +14724,25 @@ var init_project_bootstrap = __esm(() => {
|
|
|
14446
14724
|
function rowToLabel(row) {
|
|
14447
14725
|
return { ...row };
|
|
14448
14726
|
}
|
|
14727
|
+
function normalizeName(name) {
|
|
14728
|
+
return name.trim().toLowerCase();
|
|
14729
|
+
}
|
|
14730
|
+
function createLabel(input, db) {
|
|
14731
|
+
const d = db || getDatabase();
|
|
14732
|
+
const id = uuid();
|
|
14733
|
+
const ts = now();
|
|
14734
|
+
d.run(`INSERT INTO labels (id, project_id, name, color, description, created_at, updated_at)
|
|
14735
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`, [id, input.project_id ?? null, input.name.trim(), input.color ?? null, input.description ?? null, ts, ts]);
|
|
14736
|
+
return rowToLabel(d.query("SELECT * FROM labels WHERE id = ?").get(id));
|
|
14737
|
+
}
|
|
14738
|
+
function getLabel(idOrName, db) {
|
|
14739
|
+
const d = db || getDatabase();
|
|
14740
|
+
let row = d.query("SELECT * FROM labels WHERE id = ?").get(idOrName);
|
|
14741
|
+
if (!row) {
|
|
14742
|
+
row = d.query("SELECT * FROM labels WHERE lower(name) = ?").get(normalizeName(idOrName));
|
|
14743
|
+
}
|
|
14744
|
+
return row ? rowToLabel(row) : null;
|
|
14745
|
+
}
|
|
14449
14746
|
function listLabels(projectId, db) {
|
|
14450
14747
|
const d = db || getDatabase();
|
|
14451
14748
|
if (projectId) {
|
|
@@ -14453,10 +14750,164 @@ function listLabels(projectId, db) {
|
|
|
14453
14750
|
}
|
|
14454
14751
|
return d.query("SELECT * FROM labels ORDER BY name").all().map(rowToLabel);
|
|
14455
14752
|
}
|
|
14753
|
+
function updateLabel(idOrName, input, db) {
|
|
14754
|
+
const d = db || getDatabase();
|
|
14755
|
+
const existing = getLabel(idOrName, d);
|
|
14756
|
+
if (!existing)
|
|
14757
|
+
throw new Error(`Label not found: ${idOrName}`);
|
|
14758
|
+
const ts = now();
|
|
14759
|
+
d.run(`UPDATE labels SET
|
|
14760
|
+
name = COALESCE(?, name),
|
|
14761
|
+
color = COALESCE(?, color),
|
|
14762
|
+
description = COALESCE(?, description),
|
|
14763
|
+
updated_at = ?
|
|
14764
|
+
WHERE id = ?`, [input.name?.trim() ?? null, input.color ?? null, input.description ?? null, ts, existing.id]);
|
|
14765
|
+
return getLabel(existing.id, d);
|
|
14766
|
+
}
|
|
14767
|
+
function deleteLabel(idOrName, db) {
|
|
14768
|
+
const d = db || getDatabase();
|
|
14769
|
+
const existing = getLabel(idOrName, d);
|
|
14770
|
+
if (!existing)
|
|
14771
|
+
return false;
|
|
14772
|
+
d.run("DELETE FROM task_labels WHERE label_id = ?", [existing.id]);
|
|
14773
|
+
return d.run("DELETE FROM labels WHERE id = ?", [existing.id]).changes > 0;
|
|
14774
|
+
}
|
|
14775
|
+
function assignLabelToTask(taskId, labelIdOrName, db) {
|
|
14776
|
+
const d = db || getDatabase();
|
|
14777
|
+
const label = getLabel(labelIdOrName, d);
|
|
14778
|
+
if (!label)
|
|
14779
|
+
throw new Error(`Label not found: ${labelIdOrName}`);
|
|
14780
|
+
d.run("INSERT OR IGNORE INTO task_labels (task_id, label_id) VALUES (?, ?)", [taskId, label.id]);
|
|
14781
|
+
d.run("INSERT OR IGNORE INTO task_tags (task_id, tag) VALUES (?, ?)", [taskId, label.name]);
|
|
14782
|
+
return label;
|
|
14783
|
+
}
|
|
14456
14784
|
var init_labels = __esm(() => {
|
|
14457
14785
|
init_database();
|
|
14458
14786
|
});
|
|
14459
14787
|
|
|
14788
|
+
// src/db/tags.ts
|
|
14789
|
+
function normalizeName2(name) {
|
|
14790
|
+
return name.trim();
|
|
14791
|
+
}
|
|
14792
|
+
function taskCount(name, db) {
|
|
14793
|
+
const row = db.query("SELECT COUNT(*) AS count FROM task_tags WHERE tag = ?").get(name);
|
|
14794
|
+
return row?.count ?? 0;
|
|
14795
|
+
}
|
|
14796
|
+
function rowToTag(row, db) {
|
|
14797
|
+
return {
|
|
14798
|
+
...row,
|
|
14799
|
+
task_count: taskCount(row.name, db)
|
|
14800
|
+
};
|
|
14801
|
+
}
|
|
14802
|
+
function virtualTag(name, db) {
|
|
14803
|
+
return {
|
|
14804
|
+
id: name,
|
|
14805
|
+
name,
|
|
14806
|
+
color: null,
|
|
14807
|
+
description: null,
|
|
14808
|
+
task_count: taskCount(name, db),
|
|
14809
|
+
created_at: null,
|
|
14810
|
+
updated_at: null
|
|
14811
|
+
};
|
|
14812
|
+
}
|
|
14813
|
+
function getTagRow(idOrName, db) {
|
|
14814
|
+
return db.query("SELECT * FROM tags WHERE id = ?").get(idOrName) ?? db.query("SELECT * FROM tags WHERE lower(name) = lower(?)").get(idOrName);
|
|
14815
|
+
}
|
|
14816
|
+
function updateTaskTagJson(oldName, newName, db) {
|
|
14817
|
+
const rows = db.query("SELECT id, tags FROM tasks WHERE tags IS NOT NULL AND tags != '[]'").all();
|
|
14818
|
+
const update = db.prepare("UPDATE tasks SET tags = ?, updated_at = ? WHERE id = ?");
|
|
14819
|
+
const ts = now();
|
|
14820
|
+
for (const row of rows) {
|
|
14821
|
+
if (!row.tags)
|
|
14822
|
+
continue;
|
|
14823
|
+
let tags;
|
|
14824
|
+
try {
|
|
14825
|
+
tags = JSON.parse(row.tags);
|
|
14826
|
+
} catch {
|
|
14827
|
+
continue;
|
|
14828
|
+
}
|
|
14829
|
+
if (!tags.includes(oldName))
|
|
14830
|
+
continue;
|
|
14831
|
+
const next = newName ? Array.from(new Set(tags.map((tag) => tag === oldName ? newName : tag))) : tags.filter((tag) => tag !== oldName);
|
|
14832
|
+
update.run(JSON.stringify(next), ts, row.id);
|
|
14833
|
+
}
|
|
14834
|
+
}
|
|
14835
|
+
function renameTaskTagRows(oldName, newName, db) {
|
|
14836
|
+
const rows = db.query("SELECT task_id FROM task_tags WHERE tag = ?").all(oldName);
|
|
14837
|
+
const insert = db.prepare("INSERT OR IGNORE INTO task_tags (task_id, tag) VALUES (?, ?)");
|
|
14838
|
+
for (const row of rows)
|
|
14839
|
+
insert.run(row.task_id, newName);
|
|
14840
|
+
db.run("DELETE FROM task_tags WHERE tag = ?", [oldName]);
|
|
14841
|
+
}
|
|
14842
|
+
function createTag(input, db) {
|
|
14843
|
+
const d = db || getDatabase();
|
|
14844
|
+
const name = normalizeName2(input.name);
|
|
14845
|
+
if (!name)
|
|
14846
|
+
throw new Error("Tag name is required");
|
|
14847
|
+
const id = uuid();
|
|
14848
|
+
const ts = now();
|
|
14849
|
+
d.run(`INSERT INTO tags (id, name, color, description, created_at, updated_at)
|
|
14850
|
+
VALUES (?, ?, ?, ?, ?, ?)`, [id, name, input.color ?? null, input.description ?? null, ts, ts]);
|
|
14851
|
+
return rowToTag(d.query("SELECT * FROM tags WHERE id = ?").get(id), d);
|
|
14852
|
+
}
|
|
14853
|
+
function listTags(db) {
|
|
14854
|
+
const d = db || getDatabase();
|
|
14855
|
+
const rows = d.query("SELECT * FROM tags ORDER BY name").all();
|
|
14856
|
+
const tagsByName = new Map(rows.map((row) => [row.name.toLowerCase(), rowToTag(row, d)]));
|
|
14857
|
+
const taskTags = d.query("SELECT tag, COUNT(*) AS count FROM task_tags GROUP BY tag ORDER BY tag").all();
|
|
14858
|
+
for (const row of taskTags) {
|
|
14859
|
+
const key = row.tag.toLowerCase();
|
|
14860
|
+
if (!tagsByName.has(key))
|
|
14861
|
+
tagsByName.set(key, { ...virtualTag(row.tag, d), task_count: row.count });
|
|
14862
|
+
}
|
|
14863
|
+
return [...tagsByName.values()].sort((a, b) => a.name.localeCompare(b.name));
|
|
14864
|
+
}
|
|
14865
|
+
function getTag(idOrName, db) {
|
|
14866
|
+
const d = db || getDatabase();
|
|
14867
|
+
const row = getTagRow(idOrName, d);
|
|
14868
|
+
if (row)
|
|
14869
|
+
return rowToTag(row, d);
|
|
14870
|
+
const existing = d.query("SELECT tag FROM task_tags WHERE lower(tag) = lower(?) LIMIT 1").get(idOrName);
|
|
14871
|
+
return existing ? virtualTag(existing.tag, d) : null;
|
|
14872
|
+
}
|
|
14873
|
+
function updateTag(idOrName, input, db) {
|
|
14874
|
+
const d = db || getDatabase();
|
|
14875
|
+
const existing = getTag(idOrName, d);
|
|
14876
|
+
if (!existing)
|
|
14877
|
+
throw new Error(`Tag not found: ${idOrName}`);
|
|
14878
|
+
const row = getTagRow(existing.id, d);
|
|
14879
|
+
if (!row)
|
|
14880
|
+
createTag({ name: existing.name, color: existing.color ?? undefined, description: existing.description ?? undefined }, d);
|
|
14881
|
+
const stored = getTagRow(existing.id, d) ?? getTagRow(existing.name, d);
|
|
14882
|
+
if (!stored)
|
|
14883
|
+
throw new Error(`Tag not found: ${idOrName}`);
|
|
14884
|
+
const nextName = input.name !== undefined ? normalizeName2(input.name) : stored.name;
|
|
14885
|
+
if (!nextName)
|
|
14886
|
+
throw new Error("Tag name is required");
|
|
14887
|
+
const duplicate = getTagRow(nextName, d);
|
|
14888
|
+
if (duplicate && duplicate.id !== stored.id)
|
|
14889
|
+
throw new Error(`Tag already exists: ${nextName}`);
|
|
14890
|
+
if (nextName !== stored.name) {
|
|
14891
|
+
renameTaskTagRows(stored.name, nextName, d);
|
|
14892
|
+
updateTaskTagJson(stored.name, nextName, d);
|
|
14893
|
+
}
|
|
14894
|
+
d.run(`UPDATE tags SET name = ?, color = COALESCE(?, color), description = COALESCE(?, description), updated_at = ? WHERE id = ?`, [nextName, input.color ?? null, input.description ?? null, now(), stored.id]);
|
|
14895
|
+
return getTag(stored.id, d);
|
|
14896
|
+
}
|
|
14897
|
+
function deleteTag(idOrName, db) {
|
|
14898
|
+
const d = db || getDatabase();
|
|
14899
|
+
const existing = getTag(idOrName, d);
|
|
14900
|
+
if (!existing)
|
|
14901
|
+
return false;
|
|
14902
|
+
d.run("DELETE FROM tags WHERE id = ? OR lower(name) = lower(?)", [existing.id, existing.name]);
|
|
14903
|
+
d.run("DELETE FROM task_tags WHERE tag = ?", [existing.name]);
|
|
14904
|
+
updateTaskTagJson(existing.name, null, d);
|
|
14905
|
+
return true;
|
|
14906
|
+
}
|
|
14907
|
+
var init_tags = __esm(() => {
|
|
14908
|
+
init_database();
|
|
14909
|
+
});
|
|
14910
|
+
|
|
14460
14911
|
// src/lib/retention-cleanup.ts
|
|
14461
14912
|
import { existsSync as existsSync7, unlinkSync } from "fs";
|
|
14462
14913
|
function normalizeScopes(scopes) {
|
|
@@ -16691,18 +17142,18 @@ var init_local_fields = __esm(() => {
|
|
|
16691
17142
|
});
|
|
16692
17143
|
|
|
16693
17144
|
// src/lib/workflow-states.ts
|
|
16694
|
-
function
|
|
17145
|
+
function normalizeName3(value) {
|
|
16695
17146
|
return value.trim().toLowerCase().replace(/[\s-]+/g, "_");
|
|
16696
17147
|
}
|
|
16697
17148
|
function isTaskStatus(value) {
|
|
16698
17149
|
return TASK_STATUSES.includes(value);
|
|
16699
17150
|
}
|
|
16700
17151
|
function normalizeState(input) {
|
|
16701
|
-
const name =
|
|
17152
|
+
const name = normalizeName3(input.name || "");
|
|
16702
17153
|
if (!name || !isTaskStatus(input.canonical_status))
|
|
16703
17154
|
return null;
|
|
16704
|
-
const aliases = [...new Set((input.aliases || []).map(
|
|
16705
|
-
const transitions = input.transitions ? [...new Set(input.transitions.map(
|
|
17155
|
+
const aliases = [...new Set((input.aliases || []).map(normalizeName3).filter((alias) => alias && alias !== name))].sort();
|
|
17156
|
+
const transitions = input.transitions ? [...new Set(input.transitions.map(normalizeName3).filter(Boolean))].sort() : null;
|
|
16706
17157
|
return {
|
|
16707
17158
|
name,
|
|
16708
17159
|
canonical_status: input.canonical_status,
|
|
@@ -16731,7 +17182,7 @@ function listWorkflowStates(projectPath) {
|
|
|
16731
17182
|
return mergeWorkflowConfig(workflowConfig);
|
|
16732
17183
|
}
|
|
16733
17184
|
function resolveWorkflowState(input, projectPath) {
|
|
16734
|
-
const normalized =
|
|
17185
|
+
const normalized = normalizeName3(input);
|
|
16735
17186
|
const states = listWorkflowStates(projectPath);
|
|
16736
17187
|
const byName = states.find((state) => state.name === normalized);
|
|
16737
17188
|
if (byName)
|
|
@@ -17721,10 +18172,10 @@ function summarizeTasks(taskIds, planIds, runIds, db) {
|
|
|
17721
18172
|
const completed = tasks.filter((task) => task.status === "completed");
|
|
17722
18173
|
const inProgress = tasks.filter((task) => task.status === "in_progress");
|
|
17723
18174
|
const pending = tasks.filter((task) => task.status === "pending");
|
|
17724
|
-
const
|
|
17725
|
-
const percent =
|
|
18175
|
+
const taskCount2 = tasks.length;
|
|
18176
|
+
const percent = taskCount2 === 0 ? 0 : Math.round(completed.length / taskCount2 * 100);
|
|
17726
18177
|
return {
|
|
17727
|
-
task_count:
|
|
18178
|
+
task_count: taskCount2,
|
|
17728
18179
|
completed_count: completed.length,
|
|
17729
18180
|
in_progress_count: inProgress.length,
|
|
17730
18181
|
pending_count: pending.length,
|
|
@@ -17732,7 +18183,7 @@ function summarizeTasks(taskIds, planIds, runIds, db) {
|
|
|
17732
18183
|
plan_count: planIds.length,
|
|
17733
18184
|
run_count: runIds.length,
|
|
17734
18185
|
percent_complete: percent,
|
|
17735
|
-
readiness:
|
|
18186
|
+
readiness: taskCount2 === 0 ? "empty" : blocked.length > 0 ? "blocked" : completed.length === taskCount2 ? "complete" : inProgress.length > 0 ? "in_progress" : "ready"
|
|
17736
18187
|
};
|
|
17737
18188
|
}
|
|
17738
18189
|
function createRoadmap(input) {
|
|
@@ -18911,7 +19362,7 @@ function normalizeScope(scope) {
|
|
|
18911
19362
|
}
|
|
18912
19363
|
return "tasks";
|
|
18913
19364
|
}
|
|
18914
|
-
function
|
|
19365
|
+
function normalizeName4(name) {
|
|
18915
19366
|
const normalized = name.trim();
|
|
18916
19367
|
if (!normalized)
|
|
18917
19368
|
throw new Error("Saved view name is required");
|
|
@@ -19161,7 +19612,7 @@ function runSavedSearch(filters = {}, scope = "tasks", db) {
|
|
|
19161
19612
|
}
|
|
19162
19613
|
function saveSearchView(input, db) {
|
|
19163
19614
|
const d = db || getDatabase();
|
|
19164
|
-
const name =
|
|
19615
|
+
const name = normalizeName4(input.name);
|
|
19165
19616
|
const timestamp3 = now();
|
|
19166
19617
|
const existing = getSearchView(name, d);
|
|
19167
19618
|
if (existing) {
|
|
@@ -20818,10 +21269,10 @@ Tasks:` : null,
|
|
|
20818
21269
|
if (shouldRegisterTool("list_tags")) {
|
|
20819
21270
|
server.tool("list_tags", "List all distinct task tags in use, with task counts.", async () => {
|
|
20820
21271
|
try {
|
|
20821
|
-
const rows =
|
|
21272
|
+
const rows = listTags();
|
|
20822
21273
|
if (rows.length === 0)
|
|
20823
21274
|
return { content: [{ type: "text", text: "No tags found." }] };
|
|
20824
|
-
const lines = rows.map((r) => `${r.
|
|
21275
|
+
const lines = rows.map((r) => `${r.color ? "[" + r.color + "] " : ""}${r.name} (${r.task_count})`);
|
|
20825
21276
|
return { content: [{ type: "text", text: lines.join(`
|
|
20826
21277
|
`) }] };
|
|
20827
21278
|
} catch (e) {
|
|
@@ -21390,8 +21841,8 @@ var init_task_project_tools = __esm(() => {
|
|
|
21390
21841
|
init_comments();
|
|
21391
21842
|
init_task_runs();
|
|
21392
21843
|
init_project_bootstrap();
|
|
21393
|
-
init_database();
|
|
21394
21844
|
init_labels();
|
|
21845
|
+
init_tags();
|
|
21395
21846
|
init_redaction();
|
|
21396
21847
|
init_retention_cleanup();
|
|
21397
21848
|
init_mention_resolver();
|
|
@@ -24537,7 +24988,7 @@ var init_agent_run_dispatcher = __esm(() => {
|
|
|
24537
24988
|
|
|
24538
24989
|
// src/lib/verification-providers.ts
|
|
24539
24990
|
import { existsSync as existsSync10, readFileSync as readFileSync6 } from "fs";
|
|
24540
|
-
function
|
|
24991
|
+
function normalizeName5(name) {
|
|
24541
24992
|
const normalized = name.trim().toLowerCase();
|
|
24542
24993
|
if (!/^[a-z0-9][a-z0-9_-]{0,63}$/.test(normalized)) {
|
|
24543
24994
|
throw new Error("verification provider name must use lowercase letters, numbers, dashes, or underscores");
|
|
@@ -24556,10 +25007,10 @@ function timeoutMs(value) {
|
|
|
24556
25007
|
return Math.max(1, Math.min(24 * 60 * 60000, Math.floor(value)));
|
|
24557
25008
|
}
|
|
24558
25009
|
function getProvider(name) {
|
|
24559
|
-
return loadConfig().verification_providers?.[
|
|
25010
|
+
return loadConfig().verification_providers?.[normalizeName5(name)] || null;
|
|
24560
25011
|
}
|
|
24561
25012
|
function upsertVerificationProvider(input) {
|
|
24562
|
-
const name =
|
|
25013
|
+
const name = normalizeName5(input.name);
|
|
24563
25014
|
const config = loadConfig();
|
|
24564
25015
|
const existing = config.verification_providers?.[name];
|
|
24565
25016
|
const timestamp3 = new Date().toISOString();
|
|
@@ -24589,7 +25040,7 @@ function listVerificationProviders() {
|
|
|
24589
25040
|
return Object.values(loadConfig().verification_providers || {}).sort((a, b) => a.name.localeCompare(b.name));
|
|
24590
25041
|
}
|
|
24591
25042
|
function removeVerificationProvider(name) {
|
|
24592
|
-
const normalized =
|
|
25043
|
+
const normalized = normalizeName5(name);
|
|
24593
25044
|
const config = loadConfig();
|
|
24594
25045
|
if (!config.verification_providers?.[normalized])
|
|
24595
25046
|
return false;
|
|
@@ -28949,7 +29400,7 @@ import { basename as basename5, join as join9, resolve as resolve12 } from "path
|
|
|
28949
29400
|
function isObject2(value) {
|
|
28950
29401
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
28951
29402
|
}
|
|
28952
|
-
function
|
|
29403
|
+
function normalizeName6(name) {
|
|
28953
29404
|
const normalized = name.trim().toLowerCase();
|
|
28954
29405
|
if (!/^[a-z0-9][a-z0-9_.-]{0,63}$/.test(normalized)) {
|
|
28955
29406
|
throw new Error("extension name must use lowercase letters, numbers, dots, dashes, or underscores");
|
|
@@ -28967,7 +29418,7 @@ function permissionList(value) {
|
|
|
28967
29418
|
function normalizeManifest(input) {
|
|
28968
29419
|
if (!isObject2(input))
|
|
28969
29420
|
throw new Error("extension manifest must be a JSON object");
|
|
28970
|
-
const name =
|
|
29421
|
+
const name = normalizeName6(String(input["name"] || ""));
|
|
28971
29422
|
const version = String(input["version"] || "").trim();
|
|
28972
29423
|
if (!version)
|
|
28973
29424
|
throw new Error("extension manifest requires version");
|
|
@@ -28975,7 +29426,7 @@ function normalizeManifest(input) {
|
|
|
28975
29426
|
todos: typeof input["compatibility"]["todos"] === "string" ? input["compatibility"]["todos"] : undefined
|
|
28976
29427
|
} : undefined;
|
|
28977
29428
|
const commands = Array.isArray(input["commands"]) ? input["commands"].filter(isObject2).map((command) => ({
|
|
28978
|
-
name:
|
|
29429
|
+
name: normalizeName6(String(command["name"] || "")),
|
|
28979
29430
|
command: typeof command["command"] === "string" ? command["command"] : undefined,
|
|
28980
29431
|
description: typeof command["description"] === "string" ? command["description"] : undefined,
|
|
28981
29432
|
permissions: permissionList(command["permissions"]),
|
|
@@ -28984,12 +29435,12 @@ function normalizeManifest(input) {
|
|
|
28984
29435
|
network: typeof command["network"] === "boolean" ? command["network"] : undefined
|
|
28985
29436
|
})) : [];
|
|
28986
29437
|
const mcpTools = Array.isArray(input["mcp_tools"]) ? input["mcp_tools"].filter(isObject2).map((tool) => ({
|
|
28987
|
-
name:
|
|
29438
|
+
name: normalizeName6(String(tool["name"] || "")),
|
|
28988
29439
|
description: typeof tool["description"] === "string" ? tool["description"] : undefined,
|
|
28989
29440
|
permissions: permissionList(tool["permissions"])
|
|
28990
29441
|
})) : [];
|
|
28991
29442
|
const templates = Array.isArray(input["templates"]) ? input["templates"].filter(isObject2).map((template) => ({
|
|
28992
|
-
name:
|
|
29443
|
+
name: normalizeName6(String(template["name"] || "")),
|
|
28993
29444
|
kind: typeof template["kind"] === "string" ? template["kind"] : undefined,
|
|
28994
29445
|
description: typeof template["description"] === "string" ? template["description"] : undefined,
|
|
28995
29446
|
path: typeof template["path"] === "string" ? template["path"] : undefined,
|
|
@@ -28998,7 +29449,7 @@ function normalizeManifest(input) {
|
|
|
28998
29449
|
permissions: permissionList(template["permissions"])
|
|
28999
29450
|
})) : [];
|
|
29000
29451
|
const renderers = Array.isArray(input["renderers"]) ? input["renderers"].filter(isObject2).map((renderer) => ({
|
|
29001
|
-
name:
|
|
29452
|
+
name: normalizeName6(String(renderer["name"] || "")),
|
|
29002
29453
|
target: typeof renderer["target"] === "string" ? renderer["target"] : "",
|
|
29003
29454
|
description: typeof renderer["description"] === "string" ? renderer["description"] : undefined,
|
|
29004
29455
|
command: typeof renderer["command"] === "string" ? renderer["command"] : undefined,
|
|
@@ -29397,10 +29848,10 @@ function listLocalExtensions() {
|
|
|
29397
29848
|
return Object.values(loadConfig().extension_registry || {}).sort((a, b) => a.name.localeCompare(b.name));
|
|
29398
29849
|
}
|
|
29399
29850
|
function getLocalExtension(name) {
|
|
29400
|
-
return loadConfig().extension_registry?.[
|
|
29851
|
+
return loadConfig().extension_registry?.[normalizeName6(name)] || null;
|
|
29401
29852
|
}
|
|
29402
29853
|
function removeLocalExtension(name) {
|
|
29403
|
-
const normalized =
|
|
29854
|
+
const normalized = normalizeName6(name);
|
|
29404
29855
|
const config = loadConfig();
|
|
29405
29856
|
if (!config.extension_registry?.[normalized])
|
|
29406
29857
|
return false;
|
|
@@ -34911,8 +35362,6 @@ var init_builtin_templates = __esm(() => {
|
|
|
34911
35362
|
},
|
|
34912
35363
|
{
|
|
34913
35364
|
name: "open-source-project",
|
|
34914
|
-
version: 1,
|
|
34915
|
-
category: "project",
|
|
34916
35365
|
description: "Full open-source project bootstrap \u2014 scaffold to publish",
|
|
34917
35366
|
category: "open-source",
|
|
34918
35367
|
version: BUILTIN_TEMPLATE_LIBRARY_VERSION,
|
|
@@ -34938,7 +35387,7 @@ var init_builtin_templates = __esm(() => {
|
|
|
34938
35387
|
},
|
|
34939
35388
|
{
|
|
34940
35389
|
name: "release",
|
|
34941
|
-
version:
|
|
35390
|
+
version: BUILTIN_TEMPLATE_LIBRARY_VERSION,
|
|
34942
35391
|
category: "ops",
|
|
34943
35392
|
description: "Version release workflow \u2014 test, changelog, publish, verify",
|
|
34944
35393
|
variables: [
|
|
@@ -34955,7 +35404,7 @@ var init_builtin_templates = __esm(() => {
|
|
|
34955
35404
|
},
|
|
34956
35405
|
{
|
|
34957
35406
|
name: "docs-refresh",
|
|
34958
|
-
version:
|
|
35407
|
+
version: BUILTIN_TEMPLATE_LIBRARY_VERSION,
|
|
34959
35408
|
category: "workflow",
|
|
34960
35409
|
description: "Documentation refresh \u2014 audit, update, verify links",
|
|
34961
35410
|
variables: [{ name: "scope", required: true, description: "Docs scope (README, API, AGENTS.md)" }],
|
|
@@ -34968,7 +35417,7 @@ var init_builtin_templates = __esm(() => {
|
|
|
34968
35417
|
},
|
|
34969
35418
|
{
|
|
34970
35419
|
name: "migration",
|
|
34971
|
-
version:
|
|
35420
|
+
version: BUILTIN_TEMPLATE_LIBRARY_VERSION,
|
|
34972
35421
|
category: "ops",
|
|
34973
35422
|
description: "Schema/data migration workflow",
|
|
34974
35423
|
variables: [
|
|
@@ -34985,7 +35434,7 @@ var init_builtin_templates = __esm(() => {
|
|
|
34985
35434
|
},
|
|
34986
35435
|
{
|
|
34987
35436
|
name: "incident-response",
|
|
34988
|
-
version:
|
|
35437
|
+
version: BUILTIN_TEMPLATE_LIBRARY_VERSION,
|
|
34989
35438
|
category: "ops",
|
|
34990
35439
|
description: "Incident triage, mitigation, postmortem",
|
|
34991
35440
|
variables: [{ name: "incident", required: true, description: "Incident summary" }],
|
|
@@ -35032,8 +35481,8 @@ function registerTemplateTools(server, { shouldRegisterTool, resolveId, formatEr
|
|
|
35032
35481
|
const { createTemplate: createTemplate2, getTemplateWithTasks: getTemplateWithTasks2 } = await Promise.resolve().then(() => (init_templates(), exports_templates));
|
|
35033
35482
|
const t = createTemplate2(params);
|
|
35034
35483
|
const withTasks = getTemplateWithTasks2(t.id);
|
|
35035
|
-
const
|
|
35036
|
-
const taskInfo =
|
|
35484
|
+
const taskCount2 = withTasks?.tasks.length ?? 0;
|
|
35485
|
+
const taskInfo = taskCount2 > 0 ? ` | ${taskCount2} task(s)` : "";
|
|
35037
35486
|
return { content: [{ type: "text", text: `Template created: ${t.id.slice(0, 8)} | ${t.name} | "${t.title_pattern}"${taskInfo}` }] };
|
|
35038
35487
|
} catch (e) {
|
|
35039
35488
|
return { content: [{ type: "text", text: formatError(e) }], isError: true };
|
|
@@ -35952,22 +36401,27 @@ function getHeadlessBoundaryManifest() {
|
|
|
35952
36401
|
notes: [
|
|
35953
36402
|
"Use todos CLI or todos-mcp for agent workflows.",
|
|
35954
36403
|
"todos serve exposes a local-only REST API on 127.0.0.1 \u2014 not a hosted SaaS.",
|
|
35955
|
-
"
|
|
36404
|
+
"Remote sync is explicit opt-in from CLI/MCP, never from the dashboard."
|
|
35956
36405
|
]
|
|
35957
36406
|
};
|
|
35958
36407
|
}
|
|
35959
|
-
var HEADLESS_BOUNDARY_VERSION = "todos.headless-boundary.v1", FORBIDDEN_HOSTED_HOSTS, FORBIDDEN_WEB_PATTERNS, LOCAL_HOSTS;
|
|
36408
|
+
var HEADLESS_BOUNDARY_VERSION = "todos.headless-boundary.v1", FORBIDDEN_HOSTED_HOSTS, PRIVATE_PLATFORM_ORG, HOSTED_TODOS_PACKAGE, FORBIDDEN_WEB_PATTERNS, LOCAL_HOSTS;
|
|
35960
36409
|
var init_headless_boundaries = __esm(() => {
|
|
35961
36410
|
FORBIDDEN_HOSTED_HOSTS = [
|
|
35962
36411
|
"todos.md",
|
|
35963
36412
|
"www.todos.md",
|
|
35964
36413
|
"preview.todos.md",
|
|
35965
36414
|
"pay.hasna.tools",
|
|
35966
|
-
"platform
|
|
36415
|
+
["platform", "todos"].join("-")
|
|
35967
36416
|
];
|
|
36417
|
+
PRIVATE_PLATFORM_ORG = ["hasna", "studio"].join("");
|
|
36418
|
+
HOSTED_TODOS_PACKAGE = ["platform", "todos"].join("-");
|
|
35968
36419
|
FORBIDDEN_WEB_PATTERNS = [
|
|
35969
36420
|
{ name: "hosted todos.md API", pattern: /https?:\/\/(?:www\.)?todos\.md/i },
|
|
35970
|
-
{
|
|
36421
|
+
{
|
|
36422
|
+
name: "hosted platform package",
|
|
36423
|
+
pattern: new RegExp(`@${PRIVATE_PLATFORM_ORG}/${HOSTED_TODOS_PACKAGE}|${PRIVATE_PLATFORM_ORG}/${HOSTED_TODOS_PACKAGE}`, "i")
|
|
36424
|
+
},
|
|
35971
36425
|
{ name: "browser sign-in flow", pattern: /\/sign-?in\b|\/login\b.*(?:oauth|session|auth)/i },
|
|
35972
36426
|
{ name: "Stripe billing UI", pattern: /\bstripe\.(?:com|js)\b|\bcheckout\.sessions?\b/i },
|
|
35973
36427
|
{ name: "hosted OAuth redirect", pattern: /oauth.*redirect.*todos\.md/i }
|
|
@@ -36912,8 +37366,6 @@ Dashboard not found at: ${dashboardDir}`);
|
|
|
36912
37366
|
return handleMcpHttpRequest2(req, buildServer2);
|
|
36913
37367
|
}
|
|
36914
37368
|
if (method === "OPTIONS") {
|
|
36915
|
-
const reqOrigin2 = req.headers.get("origin") || undefined;
|
|
36916
|
-
const allowed = reqOrigin2 && (reqOrigin2 === `http://localhost:${port}` || reqOrigin2 === "http://localhost:0");
|
|
36917
37369
|
return new Response(null, {
|
|
36918
37370
|
headers: corsHeaders || {
|
|
36919
37371
|
Vary: "Origin"
|
|
@@ -37194,6 +37646,26 @@ function getMcpVersion() {
|
|
|
37194
37646
|
function hasVersionFlag() {
|
|
37195
37647
|
return process.argv.includes("--version") || process.argv.includes("-V");
|
|
37196
37648
|
}
|
|
37649
|
+
function hasHelpFlag() {
|
|
37650
|
+
return process.argv.includes("--help") || process.argv.includes("-h");
|
|
37651
|
+
}
|
|
37652
|
+
function printHelp() {
|
|
37653
|
+
console.log(`Usage: todos-mcp [options]
|
|
37654
|
+
|
|
37655
|
+
Start the @hasna/todos MCP server.
|
|
37656
|
+
|
|
37657
|
+
Options:
|
|
37658
|
+
--stdio Use stdio transport
|
|
37659
|
+
--port <port> Use Streamable HTTP on the given port
|
|
37660
|
+
-V, --version output the version number
|
|
37661
|
+
-h, --help display help for command
|
|
37662
|
+
|
|
37663
|
+
Environment:
|
|
37664
|
+
TODOS_MCP_STDIO=true Force stdio transport
|
|
37665
|
+
TODOS_MCP_PORT=<port> HTTP port when not using stdio
|
|
37666
|
+
TODOS_PROFILE=<profile> Tool profile filter
|
|
37667
|
+
TODOS_TOOL_GROUPS=<list> Comma-separated tool group filter`);
|
|
37668
|
+
}
|
|
37197
37669
|
function shouldRegisterTool(name) {
|
|
37198
37670
|
return shouldRegisterToolForProfile(name);
|
|
37199
37671
|
}
|
|
@@ -37407,6 +37879,10 @@ var init_mcp2 = __esm(() => {
|
|
|
37407
37879
|
console.log(getMcpVersion());
|
|
37408
37880
|
process.exit(0);
|
|
37409
37881
|
}
|
|
37882
|
+
if (hasHelpFlag()) {
|
|
37883
|
+
printHelp();
|
|
37884
|
+
process.exit(0);
|
|
37885
|
+
}
|
|
37410
37886
|
agentFocusMap = new Map;
|
|
37411
37887
|
isDirectRun = import.meta.main || process.argv[1]?.endsWith("/mcp/index.ts") || process.argv[1]?.endsWith("/mcp/index.js");
|
|
37412
37888
|
if (isDirectRun) {
|