@hechura/noreaster-cli 0.1.1 → 0.2.2

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.
@@ -2,14 +2,32 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.registerDocumentCommands = registerDocumentCommands;
4
4
  const http_1 = require("../http");
5
+ const document_templates_1 = require("../document-templates");
5
6
  function registerDocumentCommands(parent) {
6
7
  const docs = parent.command("docs").description("Manage documents");
8
+ docs
9
+ .command("template")
10
+ .description("Print the markdown template for a document type")
11
+ .argument("<docType>", "Document type (feature_description, design_spec, adr, ...)")
12
+ .action((docType) => {
13
+ const template = (0, document_templates_1.templateForDocType)(docType);
14
+ if (!template) {
15
+ console.error(`No template for doc type: ${docType}`);
16
+ process.exitCode = 1;
17
+ return;
18
+ }
19
+ console.log(template);
20
+ });
7
21
  docs
8
22
  .command("list")
9
23
  .description("List documents")
10
24
  .option("--project-id <projectId>")
11
25
  .option("--customer-id <customerId>")
12
26
  .option("--prospect-id <prospectId>")
27
+ .option("--feature <featureId>")
28
+ .option("--type <docType>")
29
+ .option("--status <status>")
30
+ .option("--include-drafts", "Include non-approved documents")
13
31
  .option("--limit <limit>")
14
32
  .action(async (options) => {
15
33
  const params = new URLSearchParams();
@@ -19,6 +37,14 @@ function registerDocumentCommands(parent) {
19
37
  params.set("customer_id", options.customerId);
20
38
  if (options.prospectId)
21
39
  params.set("prospect_id", options.prospectId);
40
+ if (options.feature)
41
+ params.set("feature_id", options.feature);
42
+ if (options.type)
43
+ params.set("doc_type", options.type);
44
+ if (options.status)
45
+ params.set("status", options.status);
46
+ if (options.includeDrafts)
47
+ params.set("include_drafts", "true");
22
48
  if (options.limit)
23
49
  params.set("limit", options.limit);
24
50
  const query = params.toString();
@@ -29,8 +55,13 @@ function registerDocumentCommands(parent) {
29
55
  .command("get")
30
56
  .description("Get document by id")
31
57
  .argument("<id>")
32
- .action(async (id) => {
33
- const result = await (0, http_1.apiRequest)((0, http_1.resolveConfig)(), "GET", `/api/agent/documents/${id}`);
58
+ .option("--include-drafts", "Include non-approved documents")
59
+ .action(async (id, options) => {
60
+ const params = new URLSearchParams();
61
+ if (options.includeDrafts)
62
+ params.set("include_drafts", "true");
63
+ const query = params.toString();
64
+ const result = await (0, http_1.apiRequest)((0, http_1.resolveConfig)(), "GET", `/api/agent/documents/${id}${query ? `?${query}` : ""}`);
34
65
  console.log(JSON.stringify(result, null, 2));
35
66
  });
36
67
  docs
@@ -50,6 +81,36 @@ function registerDocumentCommands(parent) {
50
81
  const result = await (0, http_1.apiRequest)((0, http_1.resolveConfig)(), "PATCH", `/api/agent/documents/${id}`, (0, http_1.parsePayload)(options.data));
51
82
  console.log(JSON.stringify(result, null, 2));
52
83
  });
84
+ docs
85
+ .command("transition")
86
+ .description("Transition document status")
87
+ .argument("<id>")
88
+ .requiredOption("--status <status>", "Target status")
89
+ .option("--summary <summary>", "Change summary")
90
+ .action(async (id, options) => {
91
+ const payload = { status: options.status };
92
+ if (options.summary)
93
+ payload.change_summary = options.summary;
94
+ const result = await (0, http_1.apiRequest)((0, http_1.resolveConfig)(), "PATCH", `/api/agent/documents/${id}`, payload);
95
+ console.log(JSON.stringify(result, null, 2));
96
+ });
97
+ docs
98
+ .command("revisions")
99
+ .description("List document revisions")
100
+ .argument("<id>")
101
+ .option("--include-drafts", "Include revisions for non-approved documents")
102
+ .option("--version <version>", "Fetch a specific revision version")
103
+ .action(async (id, options) => {
104
+ const params = new URLSearchParams();
105
+ if (options.includeDrafts)
106
+ params.set("include_drafts", "true");
107
+ const query = params.toString();
108
+ const path = options.version
109
+ ? `/api/agent/documents/${id}/revisions/${options.version}`
110
+ : `/api/agent/documents/${id}/revisions`;
111
+ const result = await (0, http_1.apiRequest)((0, http_1.resolveConfig)(), "GET", `${path}${query ? `?${query}` : ""}`);
112
+ console.log(JSON.stringify(result, null, 2));
113
+ });
53
114
  docs
54
115
  .command("delete")
55
116
  .description("Delete document")
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerDraftRunCommands = registerDraftRunCommands;
4
+ const http_1 = require("../http");
5
+ function registerDraftRunCommands(parent) {
6
+ const draftRuns = parent.command("draft-runs").description("Manage external draft work-item runs");
7
+ draftRuns
8
+ .command("list")
9
+ .description("List draft runs for a feature")
10
+ .argument("<featureId>")
11
+ .action(async (featureId) => {
12
+ const result = await (0, http_1.apiRequest)((0, http_1.resolveConfig)(), "GET", `/api/agent/features/${featureId}/draft-runs`);
13
+ console.log(JSON.stringify(result, null, 2));
14
+ });
15
+ draftRuns
16
+ .command("get")
17
+ .description("Get a draft run")
18
+ .argument("<featureId>")
19
+ .argument("<runId>")
20
+ .action(async (featureId, runId) => {
21
+ const result = await (0, http_1.apiRequest)((0, http_1.resolveConfig)(), "GET", `/api/agent/features/${featureId}/draft-runs/${runId}`);
22
+ console.log(JSON.stringify(result, null, 2));
23
+ });
24
+ draftRuns
25
+ .command("submit")
26
+ .description("Submit a draft run for a feature")
27
+ .argument("<featureId>")
28
+ .requiredOption("--data <json>", "JSON payload with source_document_id and items")
29
+ .action(async (featureId, options) => {
30
+ const result = await (0, http_1.apiRequest)((0, http_1.resolveConfig)(), "POST", `/api/agent/features/${featureId}/draft-runs`, (0, http_1.parsePayload)(options.data));
31
+ console.log(JSON.stringify(result, null, 2));
32
+ });
33
+ draftRuns
34
+ .command("apply")
35
+ .description("Apply a draft run (creates work items)")
36
+ .argument("<featureId>")
37
+ .argument("<runId>")
38
+ .option("--data <json>", "Optional edited items payload")
39
+ .action(async (featureId, runId, options) => {
40
+ const payload = options.data ? (0, http_1.parsePayload)(options.data) : {};
41
+ const result = await (0, http_1.apiRequest)((0, http_1.resolveConfig)(), "POST", `/api/agent/features/${featureId}/draft-runs/${runId}/apply`, payload);
42
+ console.log(JSON.stringify(result, null, 2));
43
+ });
44
+ }
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerFeatureCommands = registerFeatureCommands;
4
+ const http_1 = require("../http");
5
+ function registerFeatureCommands(parent) {
6
+ const features = parent.command("features").description("Manage features");
7
+ features
8
+ .command("list")
9
+ .description("List features")
10
+ .option("--project-id <projectId>")
11
+ .option("--status <status>")
12
+ .option("--limit <limit>")
13
+ .action(async (options) => {
14
+ const params = new URLSearchParams();
15
+ if (options.projectId)
16
+ params.set("project_id", options.projectId);
17
+ if (options.status)
18
+ params.set("status", options.status);
19
+ if (options.limit)
20
+ params.set("limit", options.limit);
21
+ const query = params.toString();
22
+ const result = await (0, http_1.apiRequest)((0, http_1.resolveConfig)(), "GET", `/api/agent/features${query ? `?${query}` : ""}`);
23
+ console.log(JSON.stringify(result, null, 2));
24
+ });
25
+ features
26
+ .command("get")
27
+ .description("Get feature by id")
28
+ .argument("<id>")
29
+ .action(async (id) => {
30
+ const result = await (0, http_1.apiRequest)((0, http_1.resolveConfig)(), "GET", `/api/agent/features/${id}`);
31
+ console.log(JSON.stringify(result, null, 2));
32
+ });
33
+ features
34
+ .command("create")
35
+ .description("Create feature")
36
+ .requiredOption("--data <json>", "JSON payload")
37
+ .action(async (options) => {
38
+ const result = await (0, http_1.apiRequest)((0, http_1.resolveConfig)(), "POST", "/api/agent/features", (0, http_1.parsePayload)(options.data));
39
+ console.log(JSON.stringify(result, null, 2));
40
+ });
41
+ features
42
+ .command("update")
43
+ .description("Update feature")
44
+ .argument("<id>")
45
+ .requiredOption("--data <json>", "JSON payload")
46
+ .action(async (id, options) => {
47
+ const result = await (0, http_1.apiRequest)((0, http_1.resolveConfig)(), "PATCH", `/api/agent/features/${id}`, (0, http_1.parsePayload)(options.data));
48
+ console.log(JSON.stringify(result, null, 2));
49
+ });
50
+ features
51
+ .command("transition")
52
+ .description("Transition feature status")
53
+ .argument("<id>")
54
+ .requiredOption("--status <status>", "Target status")
55
+ .action(async (id, options) => {
56
+ const result = await (0, http_1.apiRequest)((0, http_1.resolveConfig)(), "PATCH", `/api/agent/features/${id}`, { status: options.status });
57
+ console.log(JSON.stringify(result, null, 2));
58
+ });
59
+ features
60
+ .command("delete")
61
+ .description("Delete feature")
62
+ .argument("<id>")
63
+ .action(async (id) => {
64
+ const result = await (0, http_1.apiRequest)((0, http_1.resolveConfig)(), "DELETE", `/api/agent/features/${id}`);
65
+ console.log(JSON.stringify(result, null, 2));
66
+ });
67
+ }
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerMyWorkCommands = registerMyWorkCommands;
4
+ const http_1 = require("../http");
5
+ function registerMyWorkCommands(parent) {
6
+ parent
7
+ .command("my-work")
8
+ .description("Discover assigned work items, pending reviews, open gates, and draft runs")
9
+ .action(async () => {
10
+ const result = await (0, http_1.apiRequest)((0, http_1.resolveConfig)(), "GET", "/api/agent/my-work");
11
+ console.log(JSON.stringify(result, null, 2));
12
+ });
13
+ }
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerReviewCommands = registerReviewCommands;
4
+ const http_1 = require("../http");
5
+ function registerReviewCommands(parent) {
6
+ const reviews = parent.command("reviews").description("Manage document reviews");
7
+ reviews
8
+ .command("list")
9
+ .description("List reviews for a document")
10
+ .argument("<documentId>")
11
+ .action(async (documentId) => {
12
+ const result = await (0, http_1.apiRequest)((0, http_1.resolveConfig)(), "GET", `/api/agent/documents/${documentId}/reviews`);
13
+ console.log(JSON.stringify(result, null, 2));
14
+ });
15
+ reviews
16
+ .command("request")
17
+ .description("Request a review on a document")
18
+ .argument("<documentId>")
19
+ .option("--data <json>", "JSON payload with reviewers")
20
+ .action(async (documentId, options) => {
21
+ const payload = options.data ? (0, http_1.parsePayload)(options.data) : {};
22
+ const result = await (0, http_1.apiRequest)((0, http_1.resolveConfig)(), "POST", `/api/agent/documents/${documentId}/reviews`, payload);
23
+ console.log(JSON.stringify(result, null, 2));
24
+ });
25
+ reviews
26
+ .command("approve")
27
+ .description("Approve a review")
28
+ .argument("<documentId>")
29
+ .argument("<reviewId>")
30
+ .action(async (documentId, reviewId) => {
31
+ const result = await (0, http_1.apiRequest)((0, http_1.resolveConfig)(), "PATCH", `/api/agent/documents/${documentId}/reviews/${reviewId}`, { action: "approve" });
32
+ console.log(JSON.stringify(result, null, 2));
33
+ });
34
+ reviews
35
+ .command("request-changes")
36
+ .description("Request changes on a review")
37
+ .argument("<documentId>")
38
+ .argument("<reviewId>")
39
+ .action(async (documentId, reviewId) => {
40
+ const result = await (0, http_1.apiRequest)((0, http_1.resolveConfig)(), "PATCH", `/api/agent/documents/${documentId}/reviews/${reviewId}`, { action: "request_changes" });
41
+ console.log(JSON.stringify(result, null, 2));
42
+ });
43
+ reviews
44
+ .command("check")
45
+ .description("Tick a checklist item")
46
+ .argument("<documentId>")
47
+ .argument("<reviewId>")
48
+ .argument("<itemKey>")
49
+ .option("--unchecked", "Mark item unchecked")
50
+ .action(async (documentId, reviewId, itemKey, options) => {
51
+ const result = await (0, http_1.apiRequest)((0, http_1.resolveConfig)(), "PATCH", `/api/agent/documents/${documentId}/reviews/${reviewId}`, { action: "check", item_key: itemKey, checked: !options.unchecked });
52
+ console.log(JSON.stringify(result, null, 2));
53
+ });
54
+ reviews
55
+ .command("comment")
56
+ .description("Add a comment to a document")
57
+ .argument("<documentId>")
58
+ .requiredOption("--body <text>", "Comment body")
59
+ .option("--review-id <reviewId>")
60
+ .action(async (documentId, options) => {
61
+ const result = await (0, http_1.apiRequest)((0, http_1.resolveConfig)(), "POST", `/api/agent/documents/${documentId}/comments`, { body: options.body, review_id: options.reviewId ?? null });
62
+ console.log(JSON.stringify(result, null, 2));
63
+ });
64
+ reviews
65
+ .command("resolve-comment")
66
+ .description("Resolve a comment")
67
+ .argument("<documentId>")
68
+ .argument("<commentId>")
69
+ .action(async (documentId, commentId) => {
70
+ const result = await (0, http_1.apiRequest)((0, http_1.resolveConfig)(), "PATCH", `/api/agent/documents/${documentId}/comments/${commentId}`, { action: "resolve" });
71
+ console.log(JSON.stringify(result, null, 2));
72
+ });
73
+ }
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.registerSkillCommands = registerSkillCommands;
4
+ const node_fs_1 = require("node:fs");
5
+ const node_os_1 = require("node:os");
6
+ const node_path_1 = require("node:path");
7
+ function resolvePackagedSkillPath() {
8
+ const candidates = [
9
+ (0, node_path_1.join)(__dirname, "../../skills/hechura-manager-noreaster/SKILL.md"),
10
+ (0, node_path_1.join)(__dirname, "../../../.agents/skills/hechura-manager-noreaster/SKILL.md"),
11
+ (0, node_path_1.join)(process.cwd(), "packages/noreaster-cli/skills/hechura-manager-noreaster/SKILL.md"),
12
+ (0, node_path_1.join)(process.cwd(), ".agents/skills/hechura-manager-noreaster/SKILL.md"),
13
+ ];
14
+ for (const candidate of candidates) {
15
+ if ((0, node_fs_1.existsSync)(candidate))
16
+ return candidate;
17
+ }
18
+ throw new Error("Packaged skill file not found");
19
+ }
20
+ function installTargets() {
21
+ const home = (0, node_os_1.homedir)();
22
+ return [
23
+ (0, node_path_1.join)(home, ".claude/skills/hechura-manager-noreaster/SKILL.md"),
24
+ (0, node_path_1.join)(home, ".cursor/skills/hechura-manager-noreaster/SKILL.md"),
25
+ ];
26
+ }
27
+ function registerSkillCommands(parent) {
28
+ const skill = parent.command("skill").description("Manage the Noreaster agent skill");
29
+ skill
30
+ .command("install")
31
+ .description("Copy the packaged hechura-manager-noreaster skill into local skill directories")
32
+ .action(() => {
33
+ const source = resolvePackagedSkillPath();
34
+ const installed = [];
35
+ for (const target of installTargets()) {
36
+ (0, node_fs_1.mkdirSync)((0, node_path_1.dirname)(target), { recursive: true });
37
+ (0, node_fs_1.copyFileSync)(source, target);
38
+ installed.push(target);
39
+ }
40
+ console.log(JSON.stringify({
41
+ data: {
42
+ source,
43
+ installed,
44
+ },
45
+ }, null, 2));
46
+ });
47
+ }
@@ -9,6 +9,7 @@ function registerTaskCommands(parent) {
9
9
  .description("List tasks")
10
10
  .option("--project-id <projectId>")
11
11
  .option("--status <status>")
12
+ .option("--area <area>", "Filter by project area key")
12
13
  .option("--limit <limit>")
13
14
  .action(async (options) => {
14
15
  const params = new URLSearchParams();
@@ -16,6 +17,8 @@ function registerTaskCommands(parent) {
16
17
  params.set("project_id", options.projectId);
17
18
  if (options.status)
18
19
  params.set("status", options.status);
20
+ if (options.area)
21
+ params.set("area", options.area);
19
22
  if (options.limit)
20
23
  params.set("limit", options.limit);
21
24
  const query = params.toString();
@@ -55,4 +58,25 @@ function registerTaskCommands(parent) {
55
58
  const result = await (0, http_1.apiRequest)((0, http_1.resolveConfig)(), "DELETE", `/api/agent/tasks/${id}`);
56
59
  console.log(JSON.stringify(result, null, 2));
57
60
  });
61
+ tasks
62
+ .command("pr-link")
63
+ .description("Link a GitHub pull request URL to a task")
64
+ .argument("<id>")
65
+ .requiredOption("--url <url>", "GitHub pull request URL")
66
+ .action(async (id, options) => {
67
+ const result = await (0, http_1.apiRequest)((0, http_1.resolveConfig)(), "POST", `/api/agent/tasks/${id}/pull-requests`, {
68
+ url: options.url,
69
+ });
70
+ console.log(JSON.stringify(result, null, 2));
71
+ });
72
+ tasks
73
+ .command("pr-unlink")
74
+ .description("Unlink a GitHub pull request URL from a task")
75
+ .argument("<id>")
76
+ .requiredOption("--url <url>", "GitHub pull request URL")
77
+ .action(async (id, options) => {
78
+ const params = new URLSearchParams({ url: options.url });
79
+ const result = await (0, http_1.apiRequest)((0, http_1.resolveConfig)(), "DELETE", `/api/agent/tasks/${id}/pull-requests?${params.toString()}`);
80
+ console.log(JSON.stringify(result, null, 2));
81
+ });
58
82
  }
@@ -0,0 +1,468 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TEMPLATE_DOC_TYPES = void 0;
4
+ exports.isTemplateDocType = isTemplateDocType;
5
+ exports.templateForDocType = templateForDocType;
6
+ exports.resolveDocumentContent = resolveDocumentContent;
7
+ exports.TEMPLATE_DOC_TYPES = [
8
+ "feature_description",
9
+ "design_spec",
10
+ "adr",
11
+ "architecture",
12
+ "design_system",
13
+ "implementation_plan",
14
+ "prd",
15
+ "technical_design",
16
+ "feature_summary",
17
+ "sprint_plan",
18
+ "executive_summary",
19
+ ];
20
+ const AI_WRITING_HINT = `<!-- Writing for AI tools:
21
+ - Be explicit with exact values ("max file size: 10MB", not "reasonable").
22
+ - Describe UI in words — AI tools cannot parse Figma links.
23
+ - Edge-case table rows become test cases; be exhaustive.
24
+ - Include API request/response shapes so handlers can be generated directly.
25
+ -->`;
26
+ const FEATURE_DESCRIPTION_TEMPLATE = `# Feature Description
27
+
28
+ ${AI_WRITING_HINT}
29
+
30
+ ## Problem Statement
31
+
32
+ <!-- 2-3 sentences describing the user or business problem this feature solves.
33
+ Be specific about who is affected and what pain they experience. -->
34
+
35
+ ## Goals & Success Metrics
36
+
37
+ | Goal | Success Metric | Baseline | Target |
38
+ |------|---------------|----------|--------|
39
+ | | | | |
40
+
41
+ ## User Stories
42
+
43
+ - As a [persona], I want to [action] so that [outcome].
44
+
45
+ ## Requirements
46
+
47
+ ### Functional Requirements
48
+
49
+ 1. The system must [specific behavior].
50
+ 2. When a user [action], the system must [specific response].
51
+
52
+ ### Non-Functional Requirements
53
+
54
+ - **Performance:**
55
+ - **Accessibility:**
56
+ - **Security:**
57
+ - **Scalability:**
58
+
59
+ ## Scope
60
+
61
+ ### In Scope
62
+
63
+ -
64
+
65
+ ### Out of Scope
66
+
67
+ -
68
+
69
+ ## UX / Design
70
+
71
+ **Design Link:**
72
+
73
+ ### Key Screens & Flows
74
+
75
+ **Screen: [Name]**
76
+ - Layout:
77
+ - Primary action:
78
+ - Feedback states:
79
+
80
+ **Flow: [Name]**
81
+ 1. User [action] → System shows [response]
82
+
83
+ ## Open Questions
84
+
85
+ - [ ]
86
+ `;
87
+ const DESIGN_SPEC_TEMPLATE = `# Feature Design Spec
88
+
89
+ ${AI_WRITING_HINT}
90
+
91
+ ## Technical Context
92
+
93
+ <!-- Co-authored with engineering after requirements approval. -->
94
+
95
+ ## Affected Areas
96
+
97
+ <!-- One subsection per project area. Each developer walks their area to generate work items. -->
98
+
99
+ ### Frontend
100
+
101
+ - Services & APIs Affected:
102
+ - Changes needed:
103
+
104
+ ### Backend
105
+
106
+ - Services & APIs Affected:
107
+ - Changes needed:
108
+
109
+ ## API Contract
110
+
111
+ \`\`\`
112
+ POST /api/v1/[resource]
113
+ Request:
114
+ {
115
+ "field": "type — description"
116
+ }
117
+
118
+ Response (200):
119
+ {
120
+ "field": "type — description"
121
+ }
122
+
123
+ Response (400):
124
+ {
125
+ "error": "VALIDATION_ERROR",
126
+ "message": "Human-readable description"
127
+ }
128
+ \`\`\`
129
+
130
+ ## Data Model Changes
131
+
132
+ \`\`\`
133
+ Table: [table_name]
134
+ + new_column (type, constraints)
135
+ ~ modified_column (old_type → new_type)
136
+ \`\`\`
137
+
138
+ ## Edge Cases & Error Handling
139
+
140
+ | # | Scenario | Expected Behavior | Error Message (if applicable) |
141
+ |---|----------|-------------------|-------------------------------|
142
+ | 1 | | | |
143
+
144
+ ## Dependencies & Risks
145
+
146
+ -
147
+
148
+ ## Open Questions
149
+
150
+ - [ ]
151
+
152
+ ## Decision Log
153
+
154
+ | Date | Decision | Rationale | Decided By |
155
+ |------|----------|-----------|------------|
156
+ | | | | |
157
+ `;
158
+ const ADR_TEMPLATE = `# ADR: [Title]
159
+
160
+ ${AI_WRITING_HINT}
161
+
162
+ ## Context
163
+
164
+ <!-- What issue motivates this decision? Include constraints and forces. -->
165
+
166
+ ## Decision
167
+
168
+ <!-- State the change clearly and concisely. -->
169
+
170
+ ## Consequences
171
+
172
+ ### Positive
173
+
174
+ -
175
+
176
+ ### Negative
177
+
178
+ -
179
+
180
+ ### Neutral
181
+
182
+ -
183
+
184
+ ## Alternatives Considered
185
+
186
+ ### [Alternative 1]
187
+
188
+ - **Description:**
189
+ - **Rejected because:**
190
+
191
+ ### [Alternative 2]
192
+
193
+ - **Description:**
194
+ - **Rejected because:**
195
+ `;
196
+ const ARCHITECTURE_TEMPLATE = `# Architecture Overview
197
+
198
+ ${AI_WRITING_HINT}
199
+
200
+ ## Service Map
201
+
202
+ <!-- List services and how they relate. -->
203
+
204
+ -
205
+
206
+ ## Cross-Service Data Flows
207
+
208
+ <!-- Describe the important flows that no single service owns. -->
209
+
210
+ -
211
+
212
+ ## Shared Infrastructure
213
+
214
+ <!-- Auth, storage, messaging, observability, etc. -->
215
+
216
+ -
217
+
218
+ ## Conventions
219
+
220
+ -
221
+ `;
222
+ const DESIGN_SYSTEM_TEMPLATE = `# Design System
223
+
224
+ ${AI_WRITING_HINT}
225
+
226
+ ## Tokens
227
+
228
+ <!-- Colors, spacing, radii, elevation. Prefer exact values AI tools can apply. -->
229
+
230
+ | Token | Value | Usage |
231
+ |-------|-------|-------|
232
+ | | | |
233
+
234
+ ## Typography
235
+
236
+ | Role | Font | Size / Line height | Weight |
237
+ |------|------|--------------------|--------|
238
+ | Display | | | |
239
+ | Body | | | |
240
+ | Caption | | | |
241
+
242
+ ## Components
243
+
244
+ ### [Component name]
245
+
246
+ - Purpose:
247
+ - Variants:
248
+ - States (default / hover / focus / disabled / error):
249
+ - Content rules:
250
+
251
+ ## Interaction Patterns
252
+
253
+ - Navigation:
254
+ - Forms & validation:
255
+ - Feedback (toasts, empty states, loading):
256
+
257
+ ## Accessibility
258
+
259
+ - Contrast:
260
+ - Keyboard:
261
+ - Screen reader / labels:
262
+ - Motion:
263
+ `;
264
+ const IMPLEMENTATION_PLAN_TEMPLATE = `# Implementation Plan
265
+
266
+ ${AI_WRITING_HINT}
267
+
268
+ ## Plan
269
+
270
+ <!-- Steps, sequencing, and ownership for this work item. -->
271
+
272
+ 1.
273
+
274
+ ## Risks & Dependencies
275
+
276
+ -
277
+
278
+ ## Implementation Notes
279
+
280
+ <!-- Fill in AFTER development, not before. -->
281
+
282
+ ### Deviations from Spec
283
+
284
+ -
285
+
286
+ ### Key Implementation Details
287
+
288
+ -
289
+
290
+ ### Known Limitations
291
+
292
+ -
293
+ `;
294
+ const PRD_TEMPLATE = `# Product Requirements Document
295
+
296
+ ${AI_WRITING_HINT}
297
+
298
+ ## Problem
299
+
300
+ ## Goals
301
+
302
+ ## Personas
303
+
304
+ ## Feature List
305
+
306
+ -
307
+ `;
308
+ const TECHNICAL_DESIGN_TEMPLATE = `# Technical Design
309
+
310
+ ${AI_WRITING_HINT}
311
+
312
+ ## Technical Context
313
+
314
+ <!-- Co-authored with engineering. -->
315
+
316
+ ## Affected Areas
317
+
318
+ <!-- One subsection per project area. -->
319
+
320
+ ### Frontend
321
+
322
+ - Services & APIs Affected:
323
+ - Changes needed:
324
+
325
+ ### Backend
326
+
327
+ - Services & APIs Affected:
328
+ - Changes needed:
329
+
330
+ ## API Contract
331
+
332
+ \`\`\`
333
+ POST /api/v1/[resource]
334
+ Request:
335
+ {
336
+ "field": "type — description"
337
+ }
338
+
339
+ Response (200):
340
+ {
341
+ "field": "type — description"
342
+ }
343
+
344
+ Response (400):
345
+ {
346
+ "error": "VALIDATION_ERROR",
347
+ "message": "Human-readable description"
348
+ }
349
+ \`\`\`
350
+
351
+ ## Data Model Changes
352
+
353
+ \`\`\`
354
+ Table: [table_name]
355
+ + new_column (type, constraints)
356
+ ~ modified_column (old_type → new_type)
357
+ \`\`\`
358
+
359
+ ## Edge Cases & Error Handling
360
+
361
+ | # | Scenario | Expected Behavior | Error Message (if applicable) |
362
+ |---|----------|-------------------|-------------------------------|
363
+ | 1 | | | |
364
+
365
+ ## Dependencies & Risks
366
+
367
+ -
368
+
369
+ ## Open Questions
370
+
371
+ - [ ]
372
+
373
+ ## Decision Log
374
+
375
+ | Date | Decision | Rationale | Decided By |
376
+ |------|----------|-----------|------------|
377
+ | | | | |
378
+ `;
379
+ const FEATURE_SUMMARY_TEMPLATE = `# Feature Summary
380
+
381
+ ${AI_WRITING_HINT}
382
+
383
+ ## Problem
384
+
385
+ ## Outcome
386
+
387
+ ## In Scope
388
+
389
+ -
390
+
391
+ ## Out of Scope
392
+
393
+ -
394
+
395
+ ## Key Decisions
396
+
397
+ -
398
+ `;
399
+ const SPRINT_PLAN_TEMPLATE = `# Sprint Plan
400
+
401
+ ${AI_WRITING_HINT}
402
+
403
+ ## Sprint Goal
404
+
405
+ ## Scope
406
+
407
+ -
408
+
409
+ ## Deliverables
410
+
411
+ | Item | Owner | Done when |
412
+ |------|-------|-----------|
413
+ | | | |
414
+
415
+ ## Risks & Dependencies
416
+
417
+ -
418
+
419
+ ## Notes
420
+
421
+ -
422
+ `;
423
+ const EXECUTIVE_SUMMARY_TEMPLATE = `# Executive Summary
424
+
425
+ ${AI_WRITING_HINT}
426
+
427
+ ## Situation
428
+
429
+ ## Recommendation
430
+
431
+ ## Status
432
+
433
+ ## Decisions Needed
434
+
435
+ -
436
+
437
+ ## Next Steps
438
+
439
+ -
440
+ `;
441
+ const TEMPLATES = {
442
+ feature_description: FEATURE_DESCRIPTION_TEMPLATE,
443
+ design_spec: DESIGN_SPEC_TEMPLATE,
444
+ adr: ADR_TEMPLATE,
445
+ architecture: ARCHITECTURE_TEMPLATE,
446
+ design_system: DESIGN_SYSTEM_TEMPLATE,
447
+ implementation_plan: IMPLEMENTATION_PLAN_TEMPLATE,
448
+ prd: PRD_TEMPLATE,
449
+ technical_design: TECHNICAL_DESIGN_TEMPLATE,
450
+ feature_summary: FEATURE_SUMMARY_TEMPLATE,
451
+ sprint_plan: SPRINT_PLAN_TEMPLATE,
452
+ executive_summary: EXECUTIVE_SUMMARY_TEMPLATE,
453
+ };
454
+ function isTemplateDocType(value) {
455
+ return value != null && exports.TEMPLATE_DOC_TYPES.includes(value);
456
+ }
457
+ function templateForDocType(docType) {
458
+ if (!isTemplateDocType(docType))
459
+ return null;
460
+ return TEMPLATES[docType];
461
+ }
462
+ /** Seed template content when creating a doc with empty content. Explicit content always wins. */
463
+ function resolveDocumentContent(docType, content) {
464
+ if (content != null && content.trim().length > 0) {
465
+ return content;
466
+ }
467
+ return templateForDocType(docType);
468
+ }
package/dist/index.js CHANGED
@@ -13,13 +13,23 @@ const customers_1 = require("./commands/customers");
13
13
  const prospects_1 = require("./commands/prospects");
14
14
  const meetings_1 = require("./commands/meetings");
15
15
  const timeline_1 = require("./commands/timeline");
16
+ const features_1 = require("./commands/features");
17
+ const reviews_1 = require("./commands/reviews");
18
+ const draft_runs_1 = require("./commands/draft-runs");
19
+ const my_work_1 = require("./commands/my-work");
20
+ const skill_1 = require("./commands/skill");
16
21
  async function main() {
17
22
  const program = new commander_1.Command()
18
23
  .name("noreaster")
19
24
  .description("CLI for admin-equivalent AI agent API access")
20
- .version("0.1.0");
25
+ .version("0.1.1");
21
26
  (0, tasks_1.registerTaskCommands)(program);
22
27
  (0, docs_1.registerDocumentCommands)(program);
28
+ (0, features_1.registerFeatureCommands)(program);
29
+ (0, reviews_1.registerReviewCommands)(program);
30
+ (0, draft_runs_1.registerDraftRunCommands)(program);
31
+ (0, my_work_1.registerMyWorkCommands)(program);
32
+ (0, skill_1.registerSkillCommands)(program);
23
33
  (0, projects_1.registerProjectCommands)(program);
24
34
  (0, team_1.registerTeamCommands)(program);
25
35
  (0, messages_1.registerMessageCommands)(program);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hechura/noreaster-cli",
3
- "version": "0.1.1",
3
+ "version": "0.2.2",
4
4
  "description": "CLI for Hechura Noreaster agent API access",
5
5
  "repository": {
6
6
  "type": "git",
@@ -11,17 +11,19 @@
11
11
  "access": "public"
12
12
  },
13
13
  "bin": {
14
- "noreaster": "./dist/index.js",
15
- "hechura-agent": "./dist/index.js"
14
+ "noreaster": "dist/index.js",
15
+ "hechura-agent": "dist/index.js"
16
16
  },
17
17
  "files": [
18
- "dist"
18
+ "dist",
19
+ "skills"
19
20
  ],
20
21
  "scripts": {
21
- "build": "npx tsc -p tsconfig.json",
22
+ "build": "npx tsc -p tsconfig.json && node -e \"require('node:fs').chmodSync('dist/index.js', 0o755)\"",
22
23
  "clean": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"",
23
24
  "prepack": "npm run clean && npm run build",
24
- "pack:dry-run": "npm pack --dry-run"
25
+ "pack:dry-run": "npm pack --dry-run",
26
+ "publish:package": "npm publish --access public"
25
27
  },
26
28
  "engines": {
27
29
  "node": ">=18"
@@ -30,6 +32,7 @@
30
32
  "commander": "^14.0.3"
31
33
  },
32
34
  "devDependencies": {
35
+ "@types/node": "^22.20.1",
33
36
  "typescript": "^5.7.3"
34
37
  }
35
38
  }
@@ -0,0 +1,249 @@
1
+ ---
2
+ name: hechura-manager-noreaster
3
+ description: Operates Hechura Manager / Noreaster via the official agent CLI and PAT-scoped APIs, including the feature-spec process chain. Use when the user asks to manage Noreaster projects, tasks, sprints, customers, prospects, meetings, timeline entries, documents, features, reviews, draft runs, PR links, team/admin agent routes, or references HECHURA_AGENT_TOKEN, agent scopes, or noreaster.vercel.app docs. Also trigger for process phrases like "pick up my next work item", "submit the breakdown for review", "what gates are open", "link this PR", or "install the noreaster skill".
4
+ ---
5
+
6
+ # Hechura Manager / Noreaster Operations
7
+
8
+ Use this skill for operational work in Noreaster through the official agent CLI surface.
9
+
10
+ ## Execution Defaults
11
+
12
+ 1. Prefer the published CLI:
13
+ - `npx @hechura/noreaster-cli@0.2.2 <command>` or `noreaster <command>` after global install (`npm install -g @hechura/noreaster-cli@0.2.2`)
14
+ - In this repo: `npm run agent -- <command>`
15
+ 2. Default API base URL:
16
+ - `https://noreaster.vercel.app`
17
+ 3. Required runtime credentials:
18
+ - `HECHURA_API_BASE_URL`
19
+ - `HECHURA_AGENT_TOKEN`
20
+ 4. Before any write/delete operation, preview with a list/get command first.
21
+ 5. Never run delete/destructive commands without explicit user confirmation.
22
+ 6. After upgrading the CLI, always run `noreaster skill install` so local skill copies stay current.
23
+
24
+ ## Spec Process Chain
25
+
26
+ Noreaster is the system of record. External agents (or humans) drive generation and transitions. Chain:
27
+
28
+ ```
29
+ PRD → Feature → Feature PRD (feature_description) → Feature Spec (design_spec)
30
+ → Work Items → Implementation Plan docs → GitHub PRs
31
+ ```
32
+
33
+ ### The source-of-truth document set
34
+
35
+ Project documents are the versioned source of truth for how a project is built. Read the relevant docs before doing work; treat their contents as binding unless a human approves a change. UI labels are for humans; CLI/API payloads use `doc_type` values:
36
+
37
+ | UI label | `doc_type` | Purpose — how agents use it |
38
+ | --- | --- | --- |
39
+ | PRD | `prd` | Product requirements: problem, goals, personas, feature list. Governs *what* to build and why. |
40
+ | Architecture | `architecture` | System overview: services, data flows, infrastructure. Governs *where* code lives and how systems connect. |
41
+ | Technical Design | `technical_design` | Project-level technical design: affected areas, API contracts, data model, edge cases. Governs implementation shape. |
42
+ | Design System | `design_system` | UI system: tokens, typography, components, a11y rules. All UI work must conform to it. |
43
+ | Feature Summary | `feature_summary` | Concise feature overview: problem, outcome, in/out of scope. Orients agents before deeper docs. |
44
+ | Sprint Plan | `sprint_plan` | Sprint goal, scope, deliverables, risks. Governs what belongs in the current sprint. |
45
+ | Executive Summary | `executive_summary` | Stakeholder-facing status and decisions. Read for context; humans own the framing. |
46
+ | General Context | `general_context` | Background context for the project or engagement. Read early; useful constraints often live here. |
47
+ | Feature PRD | `feature_description` | Feature-scoped requirements (feature-linked, not a Core Document). |
48
+ | Feature Spec | `design_spec` | Feature-scoped technical design (feature-linked, not a Core Document). |
49
+
50
+ Do not invent types like `feature_prd`. Use the `doc_type` column in create/update payloads and `docs template <docType>`.
51
+
52
+ Ownership defaults:
53
+
54
+ - PRD / Feature / Feature PRD: PM-owned
55
+ - Feature Spec: engineering-owned
56
+ - Work-item breakdowns: submitted by external agents as draft runs; humans review/apply
57
+ - Implementation plans: authored by a developer's agent, linked to a work item
58
+ - PRs: linked manually or via inbound webhook matching `{ticket_prefix}-<n>` (e.g. `AIM-12`)
59
+
60
+ ## Lifecycle Gates
61
+
62
+ Illegal transitions are refused server-side with HTTP 409 and `gate_not_satisfied`.
63
+
64
+ Common gates:
65
+
66
+ - Feature PRD (`feature_description`) must be approved before Feature Spec (`design_spec`) can be approved
67
+ - Feature Spec must be approved before draft-run apply creates work items
68
+ - Document → `approved` requires a matching approved review
69
+ - Agent document reads return `approved` docs by default; use `--include-drafts` only when intentionally working on drafts
70
+
71
+ When refused, read the `gate` / `error` fields, fix the missing prerequisite, then retry.
72
+
73
+ ## Consuming project documents
74
+
75
+ Before implementing a work item, load the governing docs — do not invent contracts from memory.
76
+
77
+ 1. Fetch the work item: `tasks get <id>`
78
+ 2. Follow `source_document_id` (or the feature's Feature Spec / `design_spec`) and read it: `docs get <id>`
79
+ 3. Load project foundation docs:
80
+ - `docs list --project-id <id> --type architecture`
81
+ - `docs list --project-id <id> --type design_system`
82
+ - `docs list --project-id <id> --type technical_design`
83
+ - `docs list --project-id <id> --type general_context` (constraints and background often live here)
84
+ 4. If an ADR governs the change, read it (`--type adr`) before contradicting prior decisions.
85
+
86
+ Compliance rules while coding:
87
+
88
+ - Honor the Feature Spec's API contract and data model verbatim
89
+ - Every edge-case table row becomes a required test
90
+ - UI work must conform to the approved design-system doc (tokens, components, a11y)
91
+ - Do not contradict an approved ADR — propose a new ADR instead
92
+ - Prefer exact values from the spec over "reasonable" guesses
93
+
94
+ On completion:
95
+
96
+ - Record deviations under the design/implementation notes **Deviations from Spec** section
97
+ - Link the PR with `{ticket_prefix}-<n>` in the branch name or title (`tasks pr-link` if needed)
98
+
99
+ ## Recording decisions in the source of truth
100
+
101
+ The document set only works as a source of truth if decisions land in it explicitly. Agents may update project documents, but every decision made during work must be recorded — never applied silently in code alone.
102
+
103
+ Rules:
104
+
105
+ - Every content update writes a new revision. Always pass `change_summary` stating what changed and why:
106
+
107
+ ```bash
108
+ noreaster docs update <id> --data '{"content":"...","change_summary":"Recorded decision: switched session storage to Redis (perf, NOR-42)"}'
109
+ ```
110
+
111
+ - Architectural decisions (technology choices, service boundaries, data model direction) go in a new ADR (`doc_type: "adr"`), not buried in an edit. Then update the affected `architecture` / `technical_design` doc to reflect it, with a `change_summary` referencing the ADR.
112
+ - Implementation decisions that deviate from or refine an approved doc: update the governing doc's **Decision Log** / **Deviations from Spec** section with date, decision, rationale, and who decided — plus a `change_summary`.
113
+ - Never rewrite history: use `docs revisions <id>` to inspect prior versions; corrections are new revisions, not silent replacements.
114
+ - Approved docs are gated: content edits to an `approved` doc still record revisions, but status changes go through review (`reviews request` → human approval). If your change invalidates an approval, say so and request re-review rather than working around it.
115
+
116
+ ## Work Discovery
117
+
118
+ Start here when asked to pick up next work:
119
+
120
+ ```bash
121
+ noreaster my-work
122
+ ```
123
+
124
+ Returns:
125
+
126
+ - assigned work items for this agent
127
+ - open reviews for the principal owner (or unassigned open reviews)
128
+ - features with open gates (Feature PRD approved awaiting Feature Spec; Feature Spec approved awaiting draft apply)
129
+ - draft runs awaiting apply
130
+
131
+ ## Draft Runs
132
+
133
+ 1. Submit breakdown: `draft-runs submit <featureId> --data '...'`
134
+ 2. Humans review in the dashboard
135
+ 3. Apply after Feature Spec approval: `draft-runs apply <featureId> <runId> [--data '...']`
136
+
137
+ Do not invent silent auto-apply behavior.
138
+
139
+ ## NOR Short IDs and PR Linking
140
+
141
+ - Work items have per-project short IDs rendered as `{ticket_prefix}-<n>` (starting at 1 per project)
142
+ - Branch convention: `{prefix}-<n>-<kebab-title>` (e.g. `aim-12-fix-login`)
143
+ - Put `{ticket_prefix}-<n>` in the branch name or PR title so the webhook can auto-link
144
+ - Manual link: `tasks pr-link <id> --url <github-pr-url>`
145
+ - Unlink: `tasks pr-unlink <id> --url <github-pr-url>`
146
+ - PR merge never silently moves work-item status; humans accept "PR merged — move to done?"
147
+
148
+ ## Work Item Authoring Conventions
149
+
150
+ When creating or editing work items, prefer:
151
+
152
+ - **What**: concrete outcome
153
+ - **Why**: user/business reason (include a link back to the source spec)
154
+ - **Acceptance Criteria**: testable checklist of observable outcomes — not implementation details
155
+
156
+ Breakdown rules (ported from the CTF jira-tickets skill):
157
+
158
+ - Emit **one work item per affected area** from the project's area registry — never bundle FE and BE into a single item
159
+ - Prefix titles with the area label: `[FE - web] …`, `[BE - api] …` (use `[<area label>]`)
160
+ - Use `tasks list --area <key>` / `my-work` to stay in your lane
161
+
162
+ Writing for AI tools when authoring specs:
163
+
164
+ - Prefer exact values ("max file size: 10MB") over vague language
165
+ - Describe UI in words — tools cannot parse Figma links
166
+ - Edge-case table rows become test cases; be exhaustive
167
+ - Include API request/response shapes
168
+
169
+ Document templates:
170
+
171
+ ```bash
172
+ noreaster docs template design_spec
173
+ noreaster docs template feature_description
174
+ noreaster docs create --data '{"name":"Feature Spec","doc_type":"design_spec","project_id":"<id>","feature_id":"<id>"}'
175
+ ```
176
+
177
+ Empty `content` on create is seeded from the template for that `doc_type`.
178
+
179
+ ## Command Rules
180
+
181
+ - `--data` must be a JSON object (not an array).
182
+ - Use single quotes around JSON payloads:
183
+ - `--data '{"title":"Follow up"}'`
184
+ - API failures should be treated as blocking:
185
+ - non-zero exit code means the command did not complete.
186
+
187
+ ## Auth, Scopes, and Admin Flags
188
+
189
+ - Operational routes require PAT auth plus route-level scopes (for example `projects.write`, `work_items.write`, `features.write`).
190
+ - Agent scopes come from `ai_agents.metadata.scopes`; `*` grants all scopes.
191
+ - Admin PAT routes depend on feature flags:
192
+ - `AGENT_ADMIN_PAT_ENABLED=true`
193
+ - `AGENT_ADMIN_PAT_AGENTS_ENABLED=true`
194
+ - `AGENT_ADMIN_PAT_TOKENS_ENABLED=true`
195
+ - `AGENT_ADMIN_PAT_MONITORING_ENABLED=true`
196
+ - If PAT is not supplied on admin routes, fallback auth may use admin session behavior where enabled.
197
+
198
+ ## Core Command Surface
199
+
200
+ - `my-work`: work discovery inbox
201
+ - `skill install`: copy this skill into local Claude/Cursor skill dirs
202
+ - `tasks`: list/get/create/update/delete + `pr-link` / `pr-unlink`
203
+ - `projects`: list/get/create/update/delete + assignees/calendar color helpers (`github_repos` via update payload)
204
+ - `sprints`: list/get/create/update/delete
205
+ - `customers`: list/get/create/update/delete
206
+ - `prospects`: list/get/create/update/delete + convert
207
+ - `meetings`: list/get/create/update/delete
208
+ - `timeline`: list/get/create/update/delete
209
+ - `docs`: list/get/create/update/transition/revisions/delete
210
+ - `features`: list/get/create/update/transition/delete
211
+ - `reviews`: request/approve/request-changes/check/comment/resolve-comment
212
+ - `draft-runs`: list/get/submit/apply
213
+ - `messages`: list/create
214
+ - `team`: invite/update-role/remove
215
+ - `admin`: agents/tokens/monitoring lifecycle commands
216
+
217
+ ## Standard Workflow
218
+
219
+ 1. Validate environment (`HECHURA_API_BASE_URL`, `HECHURA_AGENT_TOKEN`)
220
+ 2. Discover work with `my-work` or targeted list/get
221
+ 3. Execute with strict JSON payloads
222
+ 4. Verify with get/list
223
+ 5. Report concise outcomes and next gates
224
+
225
+ ## Quick Command Examples
226
+
227
+ ```bash
228
+ npm install -g @hechura/noreaster-cli@0.2.2
229
+ noreaster skill install
230
+ noreaster my-work
231
+ noreaster features list --project-id <project-id>
232
+ noreaster draft-runs submit <feature-id> --data '{"document_id":"<design-spec-id>","generated_items":[{"title":"Add login","type":"task","priority":"high"}]}'
233
+ noreaster tasks pr-link <task-id> --url 'https://github.com/owner/repo/pull/12'
234
+ ```
235
+
236
+ ## Troubleshooting Playbook
237
+
238
+ - `Missing token`: set `HECHURA_AGENT_TOKEN` and retry.
239
+ - `Invalid JSON payload`: ensure `--data` is a valid JSON object in single quotes.
240
+ - `401 Unauthorized`: token missing, expired, or revoked.
241
+ - `403 Forbidden`: token scope mismatch or admin PAT route disabled by flags.
242
+ - `409 gate_not_satisfied`: missing lifecycle prerequisite; inspect `gate` and unblock.
243
+ - `429 Too Many Requests`: respect `retry_after_seconds` before retrying.
244
+ - Stale process guidance after a CLI upgrade: run `noreaster skill install` again.
245
+
246
+ ## Known Divergence
247
+
248
+ - Team admin MCP tools are planned but not primary yet; CLI/API are complete for team operations.
249
+ - Some bulk/reorder/image task workflows still use session routes under `/api/work-items/*` and are not fully mirrored in `/api/agent/tasks/*`.