@docyrus/docyrus 0.0.46 → 0.0.48

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@docyrus/docyrus",
3
- "version": "0.0.46",
3
+ "version": "0.0.48",
4
4
  "private": false,
5
5
  "description": "Docyrus API CLI",
6
6
  "main": "./main.js",
@@ -27,15 +27,16 @@ Docyrus concepts you should understand and use accurately:
27
27
 
28
28
  Project plan system:
29
29
 
30
- The project-plan is a repo-tracked work graph stored at `docyrus/project-plan/project-plan.json`. It organizes work into sections (standalone groupings like phases or feature areas), features, and tasks. A derived `PROJECT_PLAN.md` is always kept in sync. Features are also synced into the knowledge base features document when it exists.
30
+ The project-plan is a repo-tracked work graph stored at `docyrus/project-plan/project-plan.json`. It organizes work into sections (standalone groupings like phases or feature areas), features, and tasks. A derived `PROJECT_PLAN.md` is always kept in sync. Features are also synced into the knowledge base features document when it exists. Sections, features, and tasks each support an optional integer `order` field that controls display sequence (lower = first; entities without an order sort after ordered ones).
31
31
 
32
32
  - `docyrus project-plan show --json` — view the full hierarchy with statuses; returns `{ graph, hierarchy }`
33
33
  - `docyrus project-plan get-task --taskId <id> --json` — inspect a task and its linked local subtasks
34
34
  - `docyrus project-plan set-task-status --taskId <id> --status <status>` — advance task status (`planned` → `in_progress` → `done`, or `blocked`)
35
35
  - `docyrus project-plan create-linked-todo --taskId <id> [--title <title>] [--body <body>]` — create a local `.pi/todos` subtask linked to an agent-assigned canonical task
36
- - `docyrus project-plan upsert-section --title <title> [--id <id>] [--slug <slug>] [--summary <summary>]` — create or update a section
37
- - `docyrus project-plan upsert-feature --sectionId <id> --title <title> [--featureId <id>] [--slug <slug>] [--summary <summary>]` — create or update a feature
38
- - `docyrus project-plan upsert-task --featureId <id> --title <title> --type <type> --assignee <assignee> [--taskId <id>] [--status <status>] [--summary <summary>] [--acceptanceCriteria <json-array>]` — create or update a task
36
+ - `docyrus project-plan upsert-section --title <title> [--id <id>] [--slug <slug>] [--summary <summary>] [--order <n>]` — create or update a section
37
+ - `docyrus project-plan upsert-feature --sectionId <id> --title <title> [--featureId <id>] [--slug <slug>] [--summary <summary>] [--order <n>]` — create or update a feature
38
+ - `docyrus project-plan upsert-task --featureId <id> --title <title> --type <type> --assignee <assignee> [--taskId <id>] [--status <status>] [--summary <summary>] [--acceptanceCriteria <json-array>] [--order <n>]` — create or update a task
39
+ - `docyrus project-plan set-order --sectionId|--featureId|--taskId <id> --order <n>` — set display order on an existing entity (lower = first; unordered items sort last)
39
40
  - `docyrus project-plan check` — validate section references and graph integrity
40
41
  - `docyrus project-plan ensure` — initialize an empty project-plan graph if it does not yet exist
41
42
 
@@ -72,7 +72,7 @@ Schema-first workflow for new Docyrus-backed apps and major features:
72
72
 
73
73
  Project plan system:
74
74
 
75
- The project-plan is a repo-tracked work graph stored at `docyrus/project-plan/project-plan.json` with a derived `PROJECT_PLAN.md` always kept in sync. Work is organized into sections (standalone groupings like phases or feature areas), features, and tasks. Features are also synced into the knowledge base features document when it exists. Tasks have a type (`new-implementation`, `bug-fix`, `api-test`, `browser-automation-test`, `work`), an assignee (`agent` or `user`), a status (`planned`, `in_progress`, `blocked`, `done`), and optional acceptance criteria.
75
+ The project-plan is a repo-tracked work graph stored at `docyrus/project-plan/project-plan.json` with a derived `PROJECT_PLAN.md` always kept in sync. Work is organized into sections (standalone groupings like phases or feature areas), features, and tasks. Features are also synced into the knowledge base features document when it exists. Tasks have a type (`new-implementation`, `bug-fix`, `api-test`, `browser-automation-test`, `work`), an assignee (`agent` or `user`), a status (`planned`, `in_progress`, `blocked`, `done`), and optional acceptance criteria. Sections, features, and tasks each support an optional integer `order` field that controls display sequence (lower = first; entities without an order sort after ordered ones).
76
76
 
77
77
  Key commands:
78
78
 
@@ -80,9 +80,10 @@ Key commands:
80
80
  - `docyrus project-plan get-task --taskId <id> --json` — inspect a specific task and its linked local subtasks
81
81
  - `docyrus project-plan set-task-status --taskId <id> --status <status>` — advance task status (`planned` → `in_progress` → `done`, or `blocked`)
82
82
  - `docyrus project-plan create-linked-todo --taskId <id> [--title <title>] [--body <body>]` — create a local `.pi/todos` subtask linked to an agent-assigned canonical task
83
- - `docyrus project-plan upsert-section --title <title> [--id <id>] [--slug <slug>] [--summary <summary>]` — create or update a section
84
- - `docyrus project-plan upsert-feature --sectionId <id> --title <title> [--featureId <id>] [--slug <slug>] [--summary <summary>]` — create or update a feature
85
- - `docyrus project-plan upsert-task --featureId <id> --title <title> --type <type> --assignee <assignee> [--taskId <id>] [--status <status>] [--summary <summary>] [--acceptanceCriteria <json-array>]` — create or update a task
83
+ - `docyrus project-plan upsert-section --title <title> [--id <id>] [--slug <slug>] [--summary <summary>] [--order <n>]` — create or update a section
84
+ - `docyrus project-plan upsert-feature --sectionId <id> --title <title> [--featureId <id>] [--slug <slug>] [--summary <summary>] [--order <n>]` — create or update a feature
85
+ - `docyrus project-plan upsert-task --featureId <id> --title <title> --type <type> --assignee <assignee> [--taskId <id>] [--status <status>] [--summary <summary>] [--acceptanceCriteria <json-array>] [--order <n>]` — create or update a task
86
+ - `docyrus project-plan set-order --sectionId|--featureId|--taskId <id> --order <n>` — set display order on an existing entity (lower = first; unordered items sort last)
86
87
  - `docyrus project-plan check` — validate section references and graph integrity
87
88
  - `docyrus project-plan ensure` — initialize an empty project-plan graph if it does not yet exist
88
89
 
package/server-loader.js CHANGED
@@ -23487,16 +23487,30 @@ function normalizeTaskId(featureId, type, title) {
23487
23487
  function compareStrings(left, right) {
23488
23488
  return left.localeCompare(right);
23489
23489
  }
23490
+ function compareOrder(left, right) {
23491
+ if (left !== void 0 && right !== void 0) {
23492
+ return left - right;
23493
+ }
23494
+ if (left !== void 0) {
23495
+ return -1;
23496
+ }
23497
+ if (right !== void 0) {
23498
+ return 1;
23499
+ }
23500
+ return 0;
23501
+ }
23490
23502
  function sortGraph(graph) {
23491
23503
  return {
23492
23504
  version: 1,
23493
- sections: [...graph.sections].sort((left, right) => compareStrings(left.id, right.id)),
23494
- features: [...graph.features].sort((left, right) => {
23495
- return compareStrings(left.sectionId, right.sectionId) || compareStrings(left.title, right.title) || compareStrings(left.id, right.id);
23496
- }),
23497
- tasks: [...graph.tasks].sort((left, right) => {
23498
- return compareStrings(left.sectionId, right.sectionId) || compareStrings(left.featureId, right.featureId) || compareStrings(left.title, right.title) || compareStrings(left.id, right.id);
23499
- })
23505
+ sections: [...graph.sections].sort(
23506
+ (left, right) => compareOrder(left.order, right.order) || compareStrings(left.id, right.id)
23507
+ ),
23508
+ features: [...graph.features].sort(
23509
+ (left, right) => compareOrder(left.order, right.order) || compareStrings(left.sectionId, right.sectionId) || compareStrings(left.title, right.title) || compareStrings(left.id, right.id)
23510
+ ),
23511
+ tasks: [...graph.tasks].sort(
23512
+ (left, right) => compareOrder(left.order, right.order) || compareStrings(left.sectionId, right.sectionId) || compareStrings(left.featureId, right.featureId) || compareStrings(left.title, right.title) || compareStrings(left.id, right.id)
23513
+ )
23500
23514
  };
23501
23515
  }
23502
23516
  function resolveProjectPlanDirectory(root) {
@@ -23524,14 +23538,16 @@ function parseProjectPlanGraph(rawValue) {
23524
23538
  id: isNonEmptyString2(value2.id) ? value2.id.trim() : "",
23525
23539
  title: isNonEmptyString2(value2.title) ? value2.title.trim() : "",
23526
23540
  slug: isNonEmptyString2(value2.slug) ? value2.slug.trim() : "",
23527
- summary: typeof value2.summary === "string" ? value2.summary.trim() : ""
23541
+ summary: typeof value2.summary === "string" ? value2.summary.trim() : "",
23542
+ ...typeof value2.order === "number" ? { order: value2.order } : {}
23528
23543
  })).filter((value2) => value2.id.length > 0) : [];
23529
23544
  const features = Array.isArray(rawValue.features) ? rawValue.features.filter((value2) => isRecord3(value2)).map((value2) => ({
23530
23545
  id: isNonEmptyString2(value2.id) ? value2.id.trim() : "",
23531
23546
  title: isNonEmptyString2(value2.title) ? value2.title.trim() : "",
23532
23547
  slug: isNonEmptyString2(value2.slug) ? value2.slug.trim() : "",
23533
23548
  summary: typeof value2.summary === "string" ? value2.summary.trim() : "",
23534
- sectionId: isNonEmptyString2(value2.sectionId) ? value2.sectionId.trim() : ""
23549
+ sectionId: isNonEmptyString2(value2.sectionId) ? value2.sectionId.trim() : "",
23550
+ ...typeof value2.order === "number" ? { order: value2.order } : {}
23535
23551
  })).filter((value2) => value2.id.length > 0) : [];
23536
23552
  const tasks = Array.isArray(rawValue.tasks) ? rawValue.tasks.filter((value2) => isRecord3(value2)).map((value2) => ({
23537
23553
  id: isNonEmptyString2(value2.id) ? value2.id.trim() : "",
@@ -23542,7 +23558,8 @@ function parseProjectPlanGraph(rawValue) {
23542
23558
  status: typeof value2.status === "string" ? value2.status : "planned",
23543
23559
  acceptanceCriteria: normalizeStringArray(value2.acceptanceCriteria),
23544
23560
  featureId: isNonEmptyString2(value2.featureId) ? value2.featureId.trim() : "",
23545
- sectionId: isNonEmptyString2(value2.sectionId) ? value2.sectionId.trim() : ""
23561
+ sectionId: isNonEmptyString2(value2.sectionId) ? value2.sectionId.trim() : "",
23562
+ ...typeof value2.order === "number" ? { order: value2.order } : {}
23546
23563
  })).filter((value2) => value2.id.length > 0) : [];
23547
23564
  return sortGraph({
23548
23565
  version: 1,
@@ -23912,7 +23929,8 @@ async function upsertProjectPlanSection(params) {
23912
23929
  id: existing?.id || sectionId,
23913
23930
  title: params.title.trim(),
23914
23931
  slug,
23915
- summary: params.summary?.trim() || ""
23932
+ summary: params.summary?.trim() || "",
23933
+ ...params.order !== void 0 ? { order: params.order } : existing?.order !== void 0 ? { order: existing.order } : {}
23916
23934
  };
23917
23935
  const nextSections = existing ? graph.sections.map((section) => section.id === existing.id ? nextSection : section) : [...graph.sections, nextSection];
23918
23936
  await writeProjectPlanFiles(params.root, {
@@ -23932,7 +23950,8 @@ async function upsertProjectPlanFeature(params) {
23932
23950
  title: params.title.trim(),
23933
23951
  slug,
23934
23952
  summary: params.summary?.trim() || "",
23935
- sectionId: params.sectionId
23953
+ sectionId: params.sectionId,
23954
+ ...params.order !== void 0 ? { order: params.order } : existing?.order !== void 0 ? { order: existing.order } : {}
23936
23955
  };
23937
23956
  const nextFeatures = existing ? graph.features.map((feature) => feature.id === existing.id ? nextFeature : feature) : [...graph.features, nextFeature];
23938
23957
  await writeProjectPlanFiles(params.root, {
@@ -23974,7 +23993,8 @@ async function upsertProjectPlanTask(params) {
23974
23993
  status: params.status || "planned",
23975
23994
  acceptanceCriteria: [...new Set((params.acceptanceCriteria || []).map((item) => item.trim()).filter(Boolean))],
23976
23995
  featureId: feature.id,
23977
- sectionId
23996
+ sectionId,
23997
+ ...params.order !== void 0 ? { order: params.order } : existing?.order !== void 0 ? { order: existing.order } : {}
23978
23998
  };
23979
23999
  const nextTasks = existing ? graph.tasks.map((task) => task.id === existing.id ? nextTask : task) : [...graph.tasks, nextTask];
23980
24000
  await writeProjectPlanFiles(params.root, {