esedre 0.1.8 → 0.1.10
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/CHANGELOG.md +68 -0
- package/README.md +7 -6
- package/dist/esedre.mjs +188 -37
- package/package.json +3 -2
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to Esedre are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.1.10] - 2026-09-26
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- **Single-Step Ticket Creation (`--detail` & `--file`)**: `ese create` accepts `--detail "<md>"` and `--file <path>` to populate `detail.md` specifications during ticket creation without requiring a secondary `ese plan` call.
|
|
12
|
+
- **MCP `esedre_create_ticket` Specification Markdown**: Added optional `detail` parameter to the MCP create tool for agents to mint tickets with full specifications in a single turn.
|
|
13
|
+
- **`ese refresh` CLI Alias**: Added `refresh` as a direct alias for `ese snapshot` to regenerate the `.esedre/snapshot.json` projection.
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
- **Windows CMD Batch Label Syntax Error**: Refactored `WRAPPER_CMD` (`ese.cmd` / `esedre.cmd`) to eliminate parenthesized `if (...)` blocks around `goto` statements, converted jump points to top-level labels, and prefixed all batch script invocations with `call` to prevent `'The system cannot find the batch label specified - done'` crashes on Windows.
|
|
17
|
+
- **PowerShell Console Stream UTF-8 Encoding**: Enforced `[Console]::OutputEncoding`, `[Console]::InputEncoding`, and `$OutputEncoding = UTF-8` in `ese.ps1` to prevent Unicode characters (en-dashes, quotes) from rendering as mojibake.
|
|
18
|
+
- **Structured JSON Output for `ese plan --json`**: Corrected `ese plan <id> --json` to emit a machine-readable JSON payload (`{ success, ticketId, project, planMarkdown, sha1 }`) instead of ANSI terminal text.
|
|
19
|
+
|
|
20
|
+
## [0.1.9] - 2026-09-25
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
- **Smart npm Publish Lifecycle Wrapper (`npm run pub`)**: Upfront authentication pre-check (`npm whoami`) with automatic interactive login before compilation, executing full prepublish test/lint/build lifecycle.
|
|
24
|
+
- **Multi-Layer Zero-Crawl Protection**: Edge and Vite middleware security preventing search spiders and AI crawler cataloging on development tunnels (`esedre.aroomwithamoose.com`).
|
|
25
|
+
- **Canonical Apex Ecosystem Links**: Standardized all portfolio ecosystem references to canonical apex `https://arwam.com`.
|
|
26
|
+
|
|
27
|
+
## [0.1.8] - 2026-09-11
|
|
28
|
+
|
|
29
|
+
### Added
|
|
30
|
+
- **Dynamic Configuration & Manifest Reloading**: 3-second TTL polling (`ensureFreshConfig`) reloading external hubs and manifests in real time without daemon restarts.
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
- **Gateway Server Portfolio Decoupling**: Background daemon and gateway cluster (`ese start`) serve unconstrained portfolio views across all registered data hubs regardless of which workspace directory the server was launched from.
|
|
34
|
+
- **Slug Normalization**: Removed redundant `slug` field from `ProjectDescriptor`, manifests, and storage adapters in favor of canonical case-remembering `code`.
|
|
35
|
+
|
|
36
|
+
## [0.1.7] - 2026-09-11
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
- **Case-Remembering Project Resolution**: Preserves canonical casing for project codes up to 8 characters on disk and manifests while supporting case-insensitive lookups across CLI, MCP, and REST endpoints.
|
|
40
|
+
- **Workspaceless & Multi-Hub Project Init**: `ese init --project <Code> [--hub <name|path>]` creates projects directly in configured hubs without overwriting existing workspace configurations.
|
|
41
|
+
|
|
42
|
+
## [0.1.6] - 2026-09-10
|
|
43
|
+
|
|
44
|
+
### Added
|
|
45
|
+
- **Multi-Manifest Detection in `ese init`**: Auto-detects project codes and names from `Cargo.toml`, `pyproject.toml`, `settings.gradle.kts`, `app/build.gradle.kts`, and `go.mod`.
|
|
46
|
+
- **Global Port Settings**: Centralized port configuration in `~/.esedre/config.json` with CLI overrides and workspace inheritance.
|
|
47
|
+
- **Agent Project Allow-List Isolation**: Multi-tenant workspace scoping strictly limiting CLI and MCP access to declared `allowedProjects`.
|
|
48
|
+
|
|
49
|
+
## [0.1.5] - 2026-09-09
|
|
50
|
+
|
|
51
|
+
### Added
|
|
52
|
+
- **Interactive Web UI Assets & Previews**: Standalone React 19 web dashboard assets, dark and light preview cards, and documentation guides.
|
|
53
|
+
|
|
54
|
+
## [0.1.4] - 2026-09-08
|
|
55
|
+
|
|
56
|
+
### Added
|
|
57
|
+
- **MPL-2.0 License Transition**: Open source licensing under Mozilla Public License 2.0.
|
|
58
|
+
- **LLM Agent Long-Term Grounding Mission**: Formalized ground-truth architecture providing persistent context across compaction events.
|
|
59
|
+
|
|
60
|
+
## [0.1.1] - 2026-09-08
|
|
61
|
+
|
|
62
|
+
### Added
|
|
63
|
+
- **Project Onboarding & Configuration Tools**: Initial interactive setup via `ese configure` and `ese init`.
|
|
64
|
+
|
|
65
|
+
## [0.1.0] - 2026-09-08
|
|
66
|
+
|
|
67
|
+
### Added
|
|
68
|
+
- Initial release of the Esedre ticketing engine, CLI (`ese` / `esedre`), background daemon, and Model Context Protocol (MCP) server.
|
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
[](LICENSE)
|
|
10
10
|
[](tests/)
|
|
11
|
-
[](https://arwam.com)
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
@@ -115,10 +115,10 @@ Core day-to-day workflow commands for scoping, viewing, planning, and verifying
|
|
|
115
115
|
| `list` | `ese list [-p\|--project <code\|all>] [-s\|--status <status>] [-t\|--type <type>] [--json]` | List roadmap tickets with optional filters. Defaults to the active project. |
|
|
116
116
|
| `get` | `ese get <id> [--json]` | View ticket specifications, feature breakdown, comments, and SHA-1 hash. |
|
|
117
117
|
| `plan` | `ese plan <id> [--set "<markdown>"] [--file <path>] [--last-hash <h>]` | Read or update the active implementation plan markdown. |
|
|
118
|
-
| `create` | `ese create --title "..." [-p\|--project <code>] [-t\|--type <type>]` | Create a new ticket with auto-sequential ID. Title strictly capped at 48 chars. |
|
|
118
|
+
| `create` | `ese create --title "..." [-p\|--project <code>] [-t\|--type <type>] [--detail "<md>"] [--file <path>]` | Create a new ticket with auto-sequential ID and optional specification markdown. Title strictly capped at 48 chars. |
|
|
119
119
|
| `update` | `ese update <id> [-s\|--status <status>] [-t\|--type <type>] [--title "..."] [--last-hash <h>]` | Update ticket status, type, or title with optimistic concurrency protection. |
|
|
120
120
|
| `comment` | `ese comment <id> ["<text>"] [--text "..."] [--author "..."]` | Append a developer or LLM agent note to ticket history. |
|
|
121
|
-
| `snapshot` | `ese snapshot [--project <code>] [--json]` | Generate
|
|
121
|
+
| `snapshot`, `refresh` | `ese snapshot [--project <code>] [--json]` | Generate or refresh projection `.esedre/snapshot.json` for zero-latency agent context. |
|
|
122
122
|
| `projects` | `ese projects [--json]` | List registered projects within authorized scope. |
|
|
123
123
|
|
|
124
124
|
### Service Daemon Commands
|
|
@@ -186,7 +186,7 @@ To connect Esedre to **Google Antigravity**, **Claude Code**, **Cursor**, or any
|
|
|
186
186
|
- `esedre_list_tickets`: List tickets with optional project, status, category, or search filter.
|
|
187
187
|
- `esedre_get_ticket`: Retrieve full specification, summary, comments, revision, and content hash (`sha1`).
|
|
188
188
|
- `esedre_get_plan` & `esedre_save_plan`: Inspect and update implementation plans with optimistic concurrency (`lastHash`).
|
|
189
|
-
- `esedre_create_ticket`: Mint new roadmap tickets with project code validation (up to 8 chars).
|
|
189
|
+
- `esedre_create_ticket`: Mint new roadmap tickets with project code validation (up to 8 chars) and optional specification detail markdown.
|
|
190
190
|
- `esedre_update_ticket`: Modify status, title, complexity, or effort with optimistic concurrency (`lastHash`).
|
|
191
191
|
- `esedre_add_comment`: Append developer or LLM agent verification notes.
|
|
192
192
|
|
|
@@ -281,6 +281,7 @@ npm run build
|
|
|
281
281
|
|
|
282
282
|
---
|
|
283
283
|
|
|
284
|
-
## 📄 License
|
|
284
|
+
## 📄 License & Changelog
|
|
285
285
|
|
|
286
|
-
[Mozilla Public License 2.0 (MPL-2.0)](LICENSE) © [ARWAM](https://
|
|
286
|
+
- **License**: [Mozilla Public License 2.0 (MPL-2.0)](LICENSE) © [ARWAM](https://arwam.com)
|
|
287
|
+
- **Changelog**: See [CHANGELOG.md](CHANGELOG.md) for detailed release notes and version history.
|
package/dist/esedre.mjs
CHANGED
|
@@ -9,7 +9,7 @@ import fs3 from "node:fs";
|
|
|
9
9
|
import path3 from "node:path";
|
|
10
10
|
|
|
11
11
|
// src/types.ts
|
|
12
|
-
var CURRENT_ESEDRE_VERSION = "0.1.
|
|
12
|
+
var CURRENT_ESEDRE_VERSION = "0.1.10";
|
|
13
13
|
var EsedreConflictError = class extends Error {
|
|
14
14
|
constructor(ticketId, currentHash, lastHash) {
|
|
15
15
|
super(
|
|
@@ -1428,7 +1428,62 @@ ${formattedList}`
|
|
|
1428
1428
|
projectId: targetLoc.project.id,
|
|
1429
1429
|
project: targetLoc.project.code
|
|
1430
1430
|
};
|
|
1431
|
-
const
|
|
1431
|
+
const rawDetail = (input.detailMarkdown || input.detail)?.trim();
|
|
1432
|
+
let detailMd;
|
|
1433
|
+
if (rawDetail) {
|
|
1434
|
+
if (/^#\s+[^\n]+/m.test(rawDetail)) {
|
|
1435
|
+
let processed = rawDetail.replace(/^#\s+[^\n]+/m, `# Ticket #${nextId}: ${meta.title}`);
|
|
1436
|
+
if (!/\*\*(?:Type|Category)\*\*:/i.test(processed)) {
|
|
1437
|
+
const metaBlock = `
|
|
1438
|
+
**Category**: ${meta.category}
|
|
1439
|
+
**Complexity**: ${meta.complexity}
|
|
1440
|
+
**Estimated Effort**: ${meta.estimatedEffort}
|
|
1441
|
+
`;
|
|
1442
|
+
processed = processed.replace(/^(# Ticket[^\n]+\n)/m, `$1${metaBlock}`);
|
|
1443
|
+
}
|
|
1444
|
+
if (!/(?:##|###)\s*(?:Summary|Rationale)/i.test(processed)) {
|
|
1445
|
+
const summaryBlock = `
|
|
1446
|
+
### Summary
|
|
1447
|
+
${input.summary || "Summary to be defined."}
|
|
1448
|
+
`;
|
|
1449
|
+
processed = processed.replace(/^((?:# Ticket[^\n]+\n)(?:\*\*[^\n]+\n)*)/m, `$1${summaryBlock}`);
|
|
1450
|
+
}
|
|
1451
|
+
detailMd = processed.endsWith("\n") ? processed : `${processed}
|
|
1452
|
+
`;
|
|
1453
|
+
} else {
|
|
1454
|
+
const hasSummary = /(?:##|###)\s*(?:Summary|Rationale)/i.test(rawDetail);
|
|
1455
|
+
const hasBreakdown = /(?:##|###)\s*Feature Breakdown/i.test(rawDetail);
|
|
1456
|
+
let body = "";
|
|
1457
|
+
if (!hasSummary) {
|
|
1458
|
+
body += `### Summary
|
|
1459
|
+
${input.summary || "Summary to be defined."}
|
|
1460
|
+
|
|
1461
|
+
`;
|
|
1462
|
+
}
|
|
1463
|
+
if (!hasBreakdown && !rawDetail.startsWith("#")) {
|
|
1464
|
+
body += `### Feature Breakdown
|
|
1465
|
+
${rawDetail}
|
|
1466
|
+
|
|
1467
|
+
### Technical Details & Architecture
|
|
1468
|
+
- Architecture specifications to be documented.
|
|
1469
|
+
|
|
1470
|
+
### Open Questions & Decisions
|
|
1471
|
+
- None recorded at initialization.
|
|
1472
|
+
`;
|
|
1473
|
+
} else {
|
|
1474
|
+
body += `${rawDetail}
|
|
1475
|
+
`;
|
|
1476
|
+
}
|
|
1477
|
+
detailMd = `# Ticket #${nextId}: ${meta.title}
|
|
1478
|
+
**Category**: ${meta.category}
|
|
1479
|
+
**Complexity**: ${meta.complexity}
|
|
1480
|
+
**Estimated Effort**: ${meta.estimatedEffort}
|
|
1481
|
+
|
|
1482
|
+
${body.trim()}
|
|
1483
|
+
`;
|
|
1484
|
+
}
|
|
1485
|
+
} else {
|
|
1486
|
+
detailMd = `# Ticket #${nextId}: ${meta.title}
|
|
1432
1487
|
**Category**: ${meta.category}
|
|
1433
1488
|
**Complexity**: ${meta.complexity}
|
|
1434
1489
|
**Estimated Effort**: ${meta.estimatedEffort}
|
|
@@ -1446,6 +1501,7 @@ ${input.summary || "Summary to be defined."}
|
|
|
1446
1501
|
### Open Questions & Decisions
|
|
1447
1502
|
- None recorded at initialization.
|
|
1448
1503
|
`;
|
|
1504
|
+
}
|
|
1449
1505
|
writeSafeFile(path3.join(ticketDir, "meta.json"), JSON.stringify(meta, null, 2) + "\n");
|
|
1450
1506
|
writeSafeFile(path3.join(ticketDir, "detail.md"), detailMd);
|
|
1451
1507
|
const created = await this.getTicket(`${targetLoc.project.code}-${nextId}`);
|
|
@@ -2066,6 +2122,7 @@ Status: ${ticket.meta.status}`;
|
|
|
2066
2122
|
complexity: { type: "string", description: "Complexity (e.g. Low, Medium, High)" },
|
|
2067
2123
|
effort: { type: "string", description: "Estimated effort (e.g. 2.0 - 4.0 hours)" },
|
|
2068
2124
|
summary: { type: "string", description: "Initial feature summary" },
|
|
2125
|
+
detail: { type: "string", description: "Initial specification, feature breakdown, or technical detail markdown" },
|
|
2069
2126
|
author: { type: "string", description: "Submitting author name" }
|
|
2070
2127
|
},
|
|
2071
2128
|
required: ["title"]
|
|
@@ -2156,6 +2213,8 @@ Status: ${ticket.meta.status}`;
|
|
|
2156
2213
|
complexity: args.complexity,
|
|
2157
2214
|
estimatedEffort: args.effort,
|
|
2158
2215
|
summary: args.summary,
|
|
2216
|
+
detail: args.detail || args.detailMarkdown,
|
|
2217
|
+
detailMarkdown: args.detailMarkdown || args.detail,
|
|
2159
2218
|
submittedBy: args.author || "Agent"
|
|
2160
2219
|
});
|
|
2161
2220
|
return created;
|
|
@@ -2770,33 +2829,44 @@ function classifyContent(currentContent, latestTemplate, historicHashes) {
|
|
|
2770
2829
|
var WRAPPER_CMD = `@echo off
|
|
2771
2830
|
REM Esedre Autonomous Ticketing & Project Planning Engine Wrapper (Windows CMD)
|
|
2772
2831
|
setlocal
|
|
2832
|
+
|
|
2773
2833
|
where ese >nul 2>nul
|
|
2774
|
-
if %ERRORLEVEL% equ 0
|
|
2775
|
-
|
|
2776
|
-
goto :done
|
|
2777
|
-
)
|
|
2834
|
+
if %ERRORLEVEL% equ 0 goto use_ese
|
|
2835
|
+
|
|
2778
2836
|
where esedre >nul 2>nul
|
|
2779
|
-
if %ERRORLEVEL% equ 0
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
if exist "%~dp0
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2837
|
+
if %ERRORLEVEL% equ 0 goto use_esedre
|
|
2838
|
+
|
|
2839
|
+
if exist "%~dp0..\\..\\esedre\\dist\\esedre.mjs" goto use_sibling_dist
|
|
2840
|
+
if exist "%~dp0..\\esedre\\dist\\esedre.mjs" goto use_local_dist
|
|
2841
|
+
if exist "%~dp0..\\node_modules\\.bin\\ese.cmd" goto use_node_modules_ese
|
|
2842
|
+
if exist "%~dp0..\\node_modules\\.bin\\esedre.cmd" goto use_node_modules_esedre
|
|
2843
|
+
|
|
2844
|
+
call npx --yes esedre %*
|
|
2845
|
+
goto done
|
|
2846
|
+
|
|
2847
|
+
:use_ese
|
|
2848
|
+
call ese %*
|
|
2849
|
+
goto done
|
|
2850
|
+
|
|
2851
|
+
:use_esedre
|
|
2852
|
+
call esedre %*
|
|
2853
|
+
goto done
|
|
2854
|
+
|
|
2855
|
+
:use_sibling_dist
|
|
2856
|
+
node "%~dp0..\\..\\esedre\\dist\\esedre.mjs" %*
|
|
2857
|
+
goto done
|
|
2858
|
+
|
|
2859
|
+
:use_local_dist
|
|
2860
|
+
node "%~dp0..\\esedre\\dist\\esedre.mjs" %*
|
|
2861
|
+
goto done
|
|
2862
|
+
|
|
2863
|
+
:use_node_modules_ese
|
|
2864
|
+
call "%~dp0..\\node_modules\\.bin\\ese.cmd" %*
|
|
2865
|
+
goto done
|
|
2866
|
+
|
|
2867
|
+
:use_node_modules_esedre
|
|
2868
|
+
call "%~dp0..\\node_modules\\.bin\\esedre.cmd" %*
|
|
2869
|
+
goto done
|
|
2800
2870
|
|
|
2801
2871
|
:done
|
|
2802
2872
|
endlocal
|
|
@@ -2804,6 +2874,14 @@ exit /b %ERRORLEVEL%
|
|
|
2804
2874
|
`;
|
|
2805
2875
|
var WRAPPER_PS1 = `# Esedre Autonomous Ticketing & Project Planning Engine Wrapper (PowerShell)
|
|
2806
2876
|
$ErrorActionPreference = "Stop"
|
|
2877
|
+
|
|
2878
|
+
# Ensure UTF-8 console output and pipeline encoding on Windows
|
|
2879
|
+
try {
|
|
2880
|
+
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
|
2881
|
+
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
|
|
2882
|
+
$OutputEncoding = [System.Text.Encoding]::UTF8
|
|
2883
|
+
} catch {}
|
|
2884
|
+
|
|
2807
2885
|
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
2808
2886
|
|
|
2809
2887
|
if (Get-Command "ese" -ErrorAction SilentlyContinue) {
|
|
@@ -2865,8 +2943,15 @@ exec npx --yes esedre "$@"
|
|
|
2865
2943
|
var ESE_WRAPPER_CMD = `@echo off
|
|
2866
2944
|
REM Ese CLI short alias wrapper for Esedre (Windows CMD)
|
|
2867
2945
|
call "%~dp0esedre.cmd" %*
|
|
2946
|
+
exit /b %ERRORLEVEL%
|
|
2868
2947
|
`;
|
|
2869
2948
|
var ESE_WRAPPER_PS1 = `# Ese CLI short alias wrapper for Esedre (PowerShell)
|
|
2949
|
+
try {
|
|
2950
|
+
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
|
|
2951
|
+
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
|
|
2952
|
+
$OutputEncoding = [System.Text.Encoding]::UTF8
|
|
2953
|
+
} catch {}
|
|
2954
|
+
|
|
2870
2955
|
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
2871
2956
|
& (Join-Path $scriptDir "esedre.ps1") @args
|
|
2872
2957
|
exit $LASTEXITCODE
|
|
@@ -2878,7 +2963,9 @@ exec "$DIR/esedre" "$@"
|
|
|
2878
2963
|
`;
|
|
2879
2964
|
var HISTORIC_SKILL_HASHES = [
|
|
2880
2965
|
"8611116c276fdfb598b965c716b251ce7c77c7f7",
|
|
2881
|
-
"05f129fb6e06a18df00215af105567abcbf0bc67"
|
|
2966
|
+
"05f129fb6e06a18df00215af105567abcbf0bc67",
|
|
2967
|
+
"5d330ecf8fc96f383946e0351adb60378afa70f0",
|
|
2968
|
+
"23716c9db561e52e5115dc364fe154d3a7bc1e23"
|
|
2882
2969
|
];
|
|
2883
2970
|
var ESEDRE_SKILL_TEMPLATE = `---
|
|
2884
2971
|
name: esedre
|
|
@@ -2889,9 +2976,18 @@ description: Tooling and workflow reference for interacting with the Esedre deve
|
|
|
2889
2976
|
|
|
2890
2977
|
Esedre is the developer ticketing and LLM coding partner coordination platform. The engine codebase resides in the standalone repository \`aellinsar/esedre\` (\`../esedre\`), and operates on decoupled ticket repositories (such as \`aellinsar/esedre-data\` configured in \`.esedre/esedre.json\`). Interact with tickets via in-repo shell wrappers in \`.esedre/\` (\`.esedre/ese\`), or the global \`ese\` CLI.
|
|
2891
2978
|
|
|
2892
|
-
## 0.
|
|
2979
|
+
## 0. Authoritative Ingress Hierarchy & Zero-Latency Context (\`.esedre/snapshot.json\`)
|
|
2893
2980
|
|
|
2894
|
-
|
|
2981
|
+
All ticket discovery, inspection, and state management strictly follow this positive ingress hierarchy:
|
|
2982
|
+
|
|
2983
|
+
1. **Step 1 (Default for Read-Only Inspection) - Local Snapshot Projection**:
|
|
2984
|
+
Always read \`.esedre/snapshot.json\` in the workspace root first. It provides an immediate, zero-latency local projection containing all active and completed tickets, summaries, implementation plans, revision numbers, completion dates (\`completedAt\`), and staleness metrics (\`daysSinceUpdate\`).
|
|
2985
|
+
2. **Step 2 (Dynamic Queries & State Mutations) - Esedre MCP Tools**:
|
|
2986
|
+
Use first-class MCP tools when active in the session (\`esedre_list_tickets\`, \`esedre_get_ticket\`, \`esedre_get_plan\`, \`esedre_save_plan\`, \`esedre_update_ticket\`, \`esedre_add_comment\`).
|
|
2987
|
+
3. **Step 3 (Terminal & Script Fallback) - In-Repo CLI Wrapper**:
|
|
2988
|
+
Use \`.esedre/ese\` (\`.esedre/ese get\`, \`.esedre/ese plan\`, \`.esedre/ese update\`, \`.esedre/ese snapshot\`, \`.esedre/ese refresh\`).
|
|
2989
|
+
4. **Storage Boundary**:
|
|
2990
|
+
Backing ticket hubs (such as \`esedre-data\`) represent data storage managed by the engine. All agent interactions with roadmap tickets flow through the snapshot projection, MCP tools, or CLI wrappers.
|
|
2895
2991
|
|
|
2896
2992
|
## 1. Model Context Protocol (MCP) Tools
|
|
2897
2993
|
|
|
@@ -2903,7 +2999,7 @@ When Esedre MCP is active in your agent session (\`.agents/mcp_config.json\`), u
|
|
|
2903
2999
|
| \`esedre_get_ticket\` | Full specification, summary, comments, revision & sha1 | \`ticketId\` (numeric e.g. \`96\` or compound e.g. \`Profe-96\`) |
|
|
2904
3000
|
| \`esedre_get_plan\` | Active implementation plan markdown | \`ticketId\` (numeric or compound) |
|
|
2905
3001
|
| \`esedre_save_plan\` | Save implementation plan markdown with OCC | \`ticketId\`, \`planMarkdown\`, \`lastHash\` |
|
|
2906
|
-
| \`esedre_create_ticket\` | Mint a new ticket with auto sequential ID | \`title\` (max 48 chars), \`type\`, \`project\`, \`effort\`, \`summary\` |
|
|
3002
|
+
| \`esedre_create_ticket\` | Mint a new ticket with auto sequential ID | \`title\` (max 48 chars), \`type\`, \`project\`, \`effort\`, \`summary\`, \`detail\` |
|
|
2907
3003
|
| \`esedre_update_ticket\` | Update ticket attributes with OCC | \`ticketId\`, \`status\`, \`type\`, \`title\`, \`complexity\`, \`effort\`, \`inDevelopment\`, \`featureFlag\`, \`lastHash\` |
|
|
2908
3004
|
| \`esedre_add_comment\` | Append developer or agent comment | \`ticketId\`, \`text\`, \`author\` |
|
|
2909
3005
|
|
|
@@ -2930,7 +3026,7 @@ Both \`esedre\` and \`ese\` work interchangeably:
|
|
|
2930
3026
|
|
|
2931
3027
|
### Create a Ticket
|
|
2932
3028
|
\`\`\`bash
|
|
2933
|
-
.esedre/ese create --title "..." [-p|--project <code>] [-t|--type Feature] [--complexity Medium] [--effort "2.0 - 4.0 hours"] [--json]
|
|
3029
|
+
.esedre/ese create --title "..." [-p|--project <code>] [-t|--type Feature] [--complexity Medium] [--effort "2.0 - 4.0 hours"] [--detail "<md>"] [--file <path>] [--json]
|
|
2934
3030
|
\`\`\`
|
|
2935
3031
|
|
|
2936
3032
|
### Update Ticket Status & Attributes
|
|
@@ -2949,6 +3045,7 @@ Both \`esedre\` and \`ese\` work interchangeably:
|
|
|
2949
3045
|
### Regenerate Snapshot
|
|
2950
3046
|
\`\`\`bash
|
|
2951
3047
|
.esedre/ese snapshot
|
|
3048
|
+
.esedre/ese refresh
|
|
2952
3049
|
\`\`\`
|
|
2953
3050
|
|
|
2954
3051
|
### Server Lifecycle & Daemon Management
|
|
@@ -3300,6 +3397,18 @@ function configureWorkspace(targetDir, options = {}) {
|
|
|
3300
3397
|
};
|
|
3301
3398
|
}
|
|
3302
3399
|
var initWorkspace = configureWorkspace;
|
|
3400
|
+
var ESEDRE_HUB_AGENTS_TEMPLATE = `# Agent Guidelines: esedre-data
|
|
3401
|
+
|
|
3402
|
+
## 1. Role & Storage Boundary
|
|
3403
|
+
- **Backing Storage Repository**: \`esedre-data\` is a dedicated, decoupled data hub storing raw tickets, metadata manifests, and implementation plans managed by the Esedre engine.
|
|
3404
|
+
- **Authorized Ingress Channels**: Ticket discovery, read-only inspection, status updates, and plan authoring strictly ingress through the Esedre application layer in consuming project workspaces:
|
|
3405
|
+
1. **Local Workspace Snapshot**: Check the consuming workspace's \`.esedre/snapshot.json\` first for instant, zero-latency read access to ticket summaries, plans, and statuses.
|
|
3406
|
+
2. **Esedre MCP Tools**: Use \`esedre_get_ticket\`, \`esedre_list_tickets\`, \`esedre_get_plan\`, \`esedre_save_plan\`, and \`esedre_update_ticket\`.
|
|
3407
|
+
3. **Esedre CLI**: Execute \`.esedre/ese get <id>\`, \`.esedre/ese list\`, or \`.esedre/ese plan\` from within the relevant project workspace.
|
|
3408
|
+
|
|
3409
|
+
## 2. Ingress Redirection Protocol
|
|
3410
|
+
When inspecting or managing tickets for any project (such as \`Profe\`, \`Esedre\`, or \`Alce\`), navigate to that project's workspace and utilize its local \`.esedre/snapshot.json\`, Esedre MCP tools, or \`.esedre/ese\` CLI wrapper.
|
|
3411
|
+
`;
|
|
3303
3412
|
function initHub(targetDir) {
|
|
3304
3413
|
const resolved = path6.resolve(targetDir);
|
|
3305
3414
|
if (!fs6.existsSync(resolved)) {
|
|
@@ -3317,9 +3426,16 @@ function initHub(targetDir) {
|
|
|
3317
3426
|
fs6.writeFileSync(projectsJsonPath, "[]\n", "utf-8");
|
|
3318
3427
|
projectsJsonCreated = true;
|
|
3319
3428
|
}
|
|
3429
|
+
const agentsMdPath = path6.join(resolved, "AGENTS.md");
|
|
3430
|
+
let agentsMdCreated = false;
|
|
3431
|
+
if (!fs6.existsSync(agentsMdPath)) {
|
|
3432
|
+
fs6.writeFileSync(agentsMdPath, ESEDRE_HUB_AGENTS_TEMPLATE, "utf-8");
|
|
3433
|
+
agentsMdCreated = true;
|
|
3434
|
+
}
|
|
3320
3435
|
return {
|
|
3321
3436
|
projectsJsonCreated,
|
|
3322
3437
|
projectsDirCreated,
|
|
3438
|
+
agentsMdCreated,
|
|
3323
3439
|
hubDir: resolved.replace(/\\/g, "/")
|
|
3324
3440
|
};
|
|
3325
3441
|
}
|
|
@@ -3885,7 +4001,7 @@ ${colors.bold}ROADMAP COMMANDS (Pair Programming & LLM Agents):${colors.reset}
|
|
|
3885
4001
|
${colors.bold}plan${colors.reset} <id> [--file <path> | --set "<markdown>"] [--last-hash <sha1>] [--json]
|
|
3886
4002
|
View or update implementation plan with optimistic concurrency control.
|
|
3887
4003
|
|
|
3888
|
-
${colors.bold}create${colors.reset} --title "..." [-p|--project <code>] [-t|--type <type>] [--complexity <c>] [--effort "<e>"] [--summary "<s>"] [--json]
|
|
4004
|
+
${colors.bold}create${colors.reset} --title "..." [-p|--project <code>] [-t|--type <type>] [--complexity <c>] [--effort "<e>"] [--summary "<s>"] [--detail "<md>"] [--file <path>] [--json]
|
|
3889
4005
|
Mint a new roadmap ticket with sequential numeric ID.
|
|
3890
4006
|
|
|
3891
4007
|
${colors.bold}update${colors.reset} <id> [-s|--status <status>] [-t|--type <type>] [--title "..."] [--complexity <c>] [--effort "<e>"] [--in-dev] [--flag <name>] [--last-hash <sha1>] [--force] [--json]
|
|
@@ -3894,7 +4010,7 @@ ${colors.bold}ROADMAP COMMANDS (Pair Programming & LLM Agents):${colors.reset}
|
|
|
3894
4010
|
${colors.bold}comment${colors.reset} <id> ["<text>"] [--text "..."] [--author "..."] [--json]
|
|
3895
4011
|
Append a research finding, test verification, or note to ticket history.
|
|
3896
4012
|
|
|
3897
|
-
${colors.bold}snapshot${colors.reset}
|
|
4013
|
+
${colors.bold}snapshot, refresh${colors.reset} [--project <code>] [--json]
|
|
3898
4014
|
Generate lean read-only projection snapshot (.esedre/snapshot.json) for zero-latency agent context.
|
|
3899
4015
|
|
|
3900
4016
|
${colors.bold}SERVICE DAEMON COMMANDS:${colors.reset}
|
|
@@ -3938,6 +4054,8 @@ ${colors.bold}OPTIONS:${colors.reset}
|
|
|
3938
4054
|
-t, --type <type> Ticket type ('Feature', 'Platform', 'Tools', 'Idea', 'Bug').
|
|
3939
4055
|
-s, --status <stat> Ticket status ('Planned', 'In Development', 'Completed', 'Rejected').
|
|
3940
4056
|
-q, --search <query> Case-insensitive substring search query.
|
|
4057
|
+
--detail "<md>" Specification markdown for ticket detail during create.
|
|
4058
|
+
--file <path> Path to markdown file for detail (create) or implementation plan (plan).
|
|
3941
4059
|
--json Output raw machine-readable JSON (strongly recommended for autonomous LLM coding agents).
|
|
3942
4060
|
--last-hash <hash> Optimistic concurrency control: last known sha1 hash of the ticket from 'get'.
|
|
3943
4061
|
--force Bypass optimistic concurrency last-hash conflict checks on writes.
|
|
@@ -4450,6 +4568,7 @@ ${colors.bold}Commands:${colors.reset}`);
|
|
|
4450
4568
|
}
|
|
4451
4569
|
return;
|
|
4452
4570
|
}
|
|
4571
|
+
case "refresh":
|
|
4453
4572
|
case "snapshot": {
|
|
4454
4573
|
const projectCode = flags["project"] || discovered.config?.projectCode;
|
|
4455
4574
|
if (!projectCode) {
|
|
@@ -4656,12 +4775,27 @@ ${colors.dim}Total: ${tickets.length} tickets${colors.reset}`);
|
|
|
4656
4775
|
content = fs9.readFileSync(filePath, "utf-8");
|
|
4657
4776
|
}
|
|
4658
4777
|
await storage.savePlan(id, content, lastHash);
|
|
4659
|
-
|
|
4778
|
+
if (isJson) {
|
|
4779
|
+
const updated = await storage.getTicket(id);
|
|
4780
|
+
console.log(JSON.stringify({
|
|
4781
|
+
success: true,
|
|
4782
|
+
ticketId: id,
|
|
4783
|
+
project: updated?.projectDescriptor?.code || updated?.meta?.project || "UNASSIGNED",
|
|
4784
|
+
planMarkdown: content,
|
|
4785
|
+
sha1: updated?.sha1 || updated?.meta?.sha1
|
|
4786
|
+
}, null, 2));
|
|
4787
|
+
} else {
|
|
4788
|
+
console.log(`${colors.green}\u2714 Implementation plan saved for Ticket #${id}${colors.reset}`);
|
|
4789
|
+
}
|
|
4660
4790
|
return;
|
|
4661
4791
|
}
|
|
4662
4792
|
const plan = await storage.getPlan(id);
|
|
4663
4793
|
if (!plan) {
|
|
4664
|
-
|
|
4794
|
+
if (isJson) {
|
|
4795
|
+
console.log(JSON.stringify({ ticketId: id, planMarkdown: null }, null, 2));
|
|
4796
|
+
} else {
|
|
4797
|
+
console.log(`${colors.dim}No implementation plan found for Ticket #${id}.${colors.reset}`);
|
|
4798
|
+
}
|
|
4665
4799
|
return;
|
|
4666
4800
|
}
|
|
4667
4801
|
if (isJson) {
|
|
@@ -4694,6 +4828,21 @@ ${colors.dim}Total: ${tickets.length} tickets${colors.reset}`);
|
|
|
4694
4828
|
console.error(`${colors.red}Error: ${val.error}${colors.reset}`);
|
|
4695
4829
|
process.exit(1);
|
|
4696
4830
|
}
|
|
4831
|
+
const detailArg = flags["detail"];
|
|
4832
|
+
const fileArg = flags["file"];
|
|
4833
|
+
let detailMarkdown = detailArg;
|
|
4834
|
+
if (fileArg) {
|
|
4835
|
+
const filePath = path9.resolve(fileArg);
|
|
4836
|
+
if (!fs9.existsSync(filePath)) {
|
|
4837
|
+
if (isJson) {
|
|
4838
|
+
console.error(JSON.stringify({ error: `Detail file "${fileArg}" not found` }));
|
|
4839
|
+
} else {
|
|
4840
|
+
console.error(`${colors.red}Error: Detail file "${fileArg}" not found.${colors.reset}`);
|
|
4841
|
+
}
|
|
4842
|
+
process.exit(1);
|
|
4843
|
+
}
|
|
4844
|
+
detailMarkdown = fs9.readFileSync(filePath, "utf-8");
|
|
4845
|
+
}
|
|
4697
4846
|
const created = await storage.createTicket({
|
|
4698
4847
|
title,
|
|
4699
4848
|
type,
|
|
@@ -4702,7 +4851,9 @@ ${colors.dim}Total: ${tickets.length} tickets${colors.reset}`);
|
|
|
4702
4851
|
complexity,
|
|
4703
4852
|
estimatedEffort,
|
|
4704
4853
|
summary,
|
|
4705
|
-
submittedBy
|
|
4854
|
+
submittedBy,
|
|
4855
|
+
detail: detailMarkdown,
|
|
4856
|
+
detailMarkdown
|
|
4706
4857
|
});
|
|
4707
4858
|
if (isJson) {
|
|
4708
4859
|
console.log(JSON.stringify(created, null, 2));
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "esedre",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10",
|
|
4
4
|
"description": "Esedre: Developer roadmap, ticketing, and LLM coding partner coordination platform",
|
|
5
|
-
"homepage": "https://
|
|
5
|
+
"homepage": "https://arwam.com",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "git+https://github.com/Aellinsar/esedre.git"
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"files": [
|
|
28
28
|
"dist",
|
|
29
29
|
"README.md",
|
|
30
|
+
"CHANGELOG.md",
|
|
30
31
|
"LICENSE",
|
|
31
32
|
"docs/assets"
|
|
32
33
|
],
|