@inharness-ai/claude4spec 1.0.4 → 1.0.5
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 +10 -0
- package/dist/bin/c4s/commands/ask.d.ts +13 -0
- package/dist/bin/c4s/commands/ask.js +167 -0
- package/dist/bin/c4s/commands/ask.js.map +1 -0
- package/dist/bin/c4s/errors.d.ts +1 -1
- package/dist/bin/c4s/errors.js.map +1 -1
- package/dist/bin/c4s/project.d.ts +6 -0
- package/dist/bin/c4s/project.js +25 -0
- package/dist/bin/c4s/project.js.map +1 -1
- package/dist/bin/c4s.js +12 -6
- package/dist/bin/c4s.js.map +1 -1
- package/dist/server/external-skills/brief-implementer-template.d.ts +1 -1
- package/dist/server/external-skills/brief-implementer-template.js +14 -0
- package/dist/server/external-skills/brief-implementer-template.js.map +1 -1
- package/dist/server/external-skills/spec-reader-template.d.ts +1 -1
- package/dist/server/external-skills/spec-reader-template.js +12 -0
- package/dist/server/external-skills/spec-reader-template.js.map +1 -1
- package/dist/server/index.js +39 -34
- package/dist/server/index.js.map +1 -1
- package/dist/server/routes/agent-turn.d.ts +92 -0
- package/dist/server/routes/agent-turn.js +379 -0
- package/dist/server/routes/agent-turn.js.map +1 -0
- package/dist/server/routes/chat.d.ts +2 -30
- package/dist/server/routes/chat.js +33 -396
- package/dist/server/routes/chat.js.map +1 -1
- package/dist/server/routes/threads.d.ts +2 -2
- package/dist/server/routes/threads.js +51 -1
- package/dist/server/routes/threads.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.0.5] - 2026-05-19
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- `c4s ask` — synchronous CLI Q&A against a running `npx claude4spec` server. Supports `--ct chat | brief | patch`, thread continuation via `--thread <id>`, and explicit server override via `--server <url>`. Skill templates (`c4s-spec-reader`, `c4s-brief-implementer`) document the escalation path as optional — only available when both `c4s` and the server are present.
|
|
12
|
+
- `POST /api/threads/:id/ask` — synchronous JSON sibling of `POST /api/chat` (SSE). Shares the same adapter pool, `pendingInputs` map, and tool whitelist via a new `routes/agent-turn.ts` module extracted from `chat.ts`.
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
- The server now binds to a single, deterministic port (the `port+1` fallback is gone). `EADDRINUSE` fails fast with a clear message so that `c4s ask` can reliably discover the server through `.claude4spec/config.json.port`.
|
|
16
|
+
|
|
8
17
|
## [1.0.4] - 2026-05-18
|
|
9
18
|
|
|
10
19
|
### Added
|
|
@@ -50,6 +59,7 @@ Initial public release.
|
|
|
50
59
|
- Acceptance Criteria entity and tooling.
|
|
51
60
|
- Briefs and patches workflow for spec-driven implementation.
|
|
52
61
|
|
|
62
|
+
[1.0.5]: https://github.com/InHarness/claude4spec/compare/v1.0.4...v1.0.5
|
|
53
63
|
[1.0.4]: https://github.com/InHarness/claude4spec/compare/v1.0.3...v1.0.4
|
|
54
64
|
[1.0.3]: https://github.com/InHarness/claude4spec/compare/v1.0.2...v1.0.3
|
|
55
65
|
[1.0.2]: https://github.com/InHarness/claude4spec/compare/v1.0.1...v1.0.2
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ParsedArgs } from '../args.js';
|
|
2
|
+
/**
|
|
3
|
+
* `c4s ask` — synchroniczny kanal Q&A z agentem specyfikacji (M11).
|
|
4
|
+
*
|
|
5
|
+
* Jedyna komenda `c4s` wymagajaca dzialajacego serwera `npx claude4spec`:
|
|
6
|
+
* nie uruchamia agenta sama, tylko deleguje ture do `POST /api/threads/:id/ask`
|
|
7
|
+
* i kolapsuje ja do `{ threadId, answer }`.
|
|
8
|
+
*
|
|
9
|
+
* c4s ask "<msg>" --ct chat
|
|
10
|
+
* c4s ask "<msg>" --ct brief --brief <path>
|
|
11
|
+
* c4s ask "<msg>" --thread <id>
|
|
12
|
+
*/
|
|
13
|
+
export declare function runAsk(args: ParsedArgs): Promise<void>;
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { optionalString } from '../args.js';
|
|
4
|
+
import { CliError } from '../errors.js';
|
|
5
|
+
import { resolveProjectByConfig } from '../project.js';
|
|
6
|
+
/**
|
|
7
|
+
* `c4s ask` — synchroniczny kanal Q&A z agentem specyfikacji (M11).
|
|
8
|
+
*
|
|
9
|
+
* Jedyna komenda `c4s` wymagajaca dzialajacego serwera `npx claude4spec`:
|
|
10
|
+
* nie uruchamia agenta sama, tylko deleguje ture do `POST /api/threads/:id/ask`
|
|
11
|
+
* i kolapsuje ja do `{ threadId, answer }`.
|
|
12
|
+
*
|
|
13
|
+
* c4s ask "<msg>" --ct chat
|
|
14
|
+
* c4s ask "<msg>" --ct brief --brief <path>
|
|
15
|
+
* c4s ask "<msg>" --thread <id>
|
|
16
|
+
*/
|
|
17
|
+
export async function runAsk(args) {
|
|
18
|
+
const message = args.positional[0];
|
|
19
|
+
if (!message || !message.trim()) {
|
|
20
|
+
throw new CliError('INVALID_ARGS', 'message is required: c4s ask "<msg>" --ct chat');
|
|
21
|
+
}
|
|
22
|
+
const threadFlag = optionalString(args, 'thread');
|
|
23
|
+
const ct = optionalString(args, 'ct');
|
|
24
|
+
const briefFlag = optionalString(args, 'brief');
|
|
25
|
+
const serverOverride = optionalString(args, 'server');
|
|
26
|
+
// --- discovery: adres serwera -------------------------------------------
|
|
27
|
+
// `--server` nadpisuje resolve projektu + budowanie URL z config.json.
|
|
28
|
+
let baseUrl;
|
|
29
|
+
if (serverOverride) {
|
|
30
|
+
baseUrl = serverOverride.replace(/\/+$/, '');
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
const projectDir = resolveProjectByConfig(args.project);
|
|
34
|
+
baseUrl = `http://localhost:${readConfigPort(projectDir)}`;
|
|
35
|
+
}
|
|
36
|
+
// --- health-check tozsamosci --------------------------------------------
|
|
37
|
+
await healthCheck(baseUrl);
|
|
38
|
+
// --- create-thread (context-specific) — pomijany dla --thread -----------
|
|
39
|
+
let threadId;
|
|
40
|
+
if (threadFlag) {
|
|
41
|
+
threadId = threadFlag;
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
if (ct !== 'chat' && ct !== 'brief' && ct !== 'patch') {
|
|
45
|
+
throw new CliError('INVALID_ARGS', '--ct must be chat|brief|patch (or pass --thread <id> to continue a thread)');
|
|
46
|
+
}
|
|
47
|
+
if (ct === 'patch') {
|
|
48
|
+
// Watki patch nie maja CLI route create-thread — tylko kontynuacja.
|
|
49
|
+
throw new CliError('INVALID_ARGS', 'c4s ask cannot create a patch thread; pass --thread <id> to continue one');
|
|
50
|
+
}
|
|
51
|
+
if (ct === 'brief') {
|
|
52
|
+
if (!briefFlag) {
|
|
53
|
+
throw new CliError('INVALID_ARGS', '--ct brief requires --brief <path>');
|
|
54
|
+
}
|
|
55
|
+
const encoded = briefFlag.split('/').map(encodeURIComponent).join('/');
|
|
56
|
+
const created = await postJson(`${baseUrl}/api/briefs/${encoded}/threads`, {});
|
|
57
|
+
threadId = pickThreadId(created);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
const created = await postJson(`${baseUrl}/api/threads`, {});
|
|
61
|
+
threadId = pickThreadId(created);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// --- run-turn (generyczny po context_type) ------------------------------
|
|
65
|
+
const result = await postJson(`${baseUrl}/api/threads/${encodeURIComponent(threadId)}/ask`, {
|
|
66
|
+
message,
|
|
67
|
+
});
|
|
68
|
+
const answer = typeof result.answer === 'string' ? result.answer : '';
|
|
69
|
+
const outThreadId = typeof result.threadId === 'string' ? result.threadId : threadId;
|
|
70
|
+
// --- output --------------------------------------------------------------
|
|
71
|
+
if (args.format === 'text') {
|
|
72
|
+
process.stdout.write(answer + '\n');
|
|
73
|
+
// threadId na stderr — hint do kontynuacji wątku.
|
|
74
|
+
process.stderr.write(`thread: ${outThreadId} (continue: c4s ask "..." --thread ${outThreadId})\n`);
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
process.stdout.write(JSON.stringify({ threadId: outThreadId, answer }, null, 2) + '\n');
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/** Czyta `.claude4spec/config.json` i zwraca `port`. */
|
|
81
|
+
function readConfigPort(projectDir) {
|
|
82
|
+
const file = path.join(projectDir, '.claude4spec', 'config.json');
|
|
83
|
+
let parsed;
|
|
84
|
+
try {
|
|
85
|
+
parsed = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
88
|
+
throw new CliError('PROJECT_NOT_FOUND', `cannot read ${file}: ${err.message}`);
|
|
89
|
+
}
|
|
90
|
+
const port = parsed.port;
|
|
91
|
+
if (typeof port !== 'number') {
|
|
92
|
+
throw new CliError('PROJECT_NOT_FOUND', `config.json has no numeric "port" (${file})`);
|
|
93
|
+
}
|
|
94
|
+
return port;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Health-check tozsamosci: `GET /api/config` musi zwrocic kształt configu
|
|
98
|
+
* claude4spec. Trzy rozlaczne wyniki: connection refused → SERVER_NOT_RUNNING;
|
|
99
|
+
* odpowiedz spoza configu → SERVER_NOT_RECOGNIZED; poprawny config → OK.
|
|
100
|
+
*/
|
|
101
|
+
async function healthCheck(baseUrl) {
|
|
102
|
+
let res;
|
|
103
|
+
try {
|
|
104
|
+
res = await fetch(`${baseUrl}/api/config`);
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
throw new CliError('SERVER_NOT_RUNNING', `no claude4spec server responding at ${baseUrl}`, 'start it with `npx claude4spec` in the project');
|
|
108
|
+
}
|
|
109
|
+
let body;
|
|
110
|
+
try {
|
|
111
|
+
body = await res.json();
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
throw new CliError('SERVER_NOT_RECOGNIZED', `process at ${baseUrl} responded but not with a claude4spec config`);
|
|
115
|
+
}
|
|
116
|
+
if (!isConfigShape(body)) {
|
|
117
|
+
throw new CliError('SERVER_NOT_RECOGNIZED', `process at ${baseUrl} is not a claude4spec server (unexpected GET /api/config shape)`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
function isConfigShape(body) {
|
|
121
|
+
if (!body || typeof body !== 'object')
|
|
122
|
+
return false;
|
|
123
|
+
const c = body;
|
|
124
|
+
return (typeof c.name === 'string' &&
|
|
125
|
+
typeof c.port === 'number' &&
|
|
126
|
+
typeof c.pagesDir === 'string' &&
|
|
127
|
+
typeof c.mode === 'string' &&
|
|
128
|
+
'writingStyle' in c &&
|
|
129
|
+
!!c.onboarding &&
|
|
130
|
+
typeof c.onboarding === 'object');
|
|
131
|
+
}
|
|
132
|
+
/** POST JSON; przy nie-2xx propaguje `{ error: { code, message } }` endpointu. */
|
|
133
|
+
async function postJson(url, payload) {
|
|
134
|
+
let res;
|
|
135
|
+
try {
|
|
136
|
+
res = await fetch(url, {
|
|
137
|
+
method: 'POST',
|
|
138
|
+
headers: { 'content-type': 'application/json' },
|
|
139
|
+
body: JSON.stringify(payload),
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
throw new CliError('SERVER_NOT_RUNNING', `request to ${url} failed (connection refused)`);
|
|
144
|
+
}
|
|
145
|
+
let body = {};
|
|
146
|
+
try {
|
|
147
|
+
body = (await res.json());
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
/* puste/nie-JSON body — obsluzone nizej przez !res.ok */
|
|
151
|
+
}
|
|
152
|
+
if (!res.ok) {
|
|
153
|
+
const err = (body.error ?? {});
|
|
154
|
+
throw new CliError(err.code ?? 'AGENT_ERROR', err.message ?? `request to ${url} failed with HTTP ${res.status}`);
|
|
155
|
+
}
|
|
156
|
+
// create-thread zwraca `{ data: {...} }`; run-turn zwraca obiekt wprost.
|
|
157
|
+
return body.data ?? body;
|
|
158
|
+
}
|
|
159
|
+
function pickThreadId(created) {
|
|
160
|
+
// `POST /api/threads` → `{ id }`; `POST /api/briefs/.../threads` → `{ threadId }`.
|
|
161
|
+
const id = created.threadId ?? created.id;
|
|
162
|
+
if (typeof id !== 'string' || !id) {
|
|
163
|
+
throw new CliError('AGENT_ERROR', 'create-thread response had no thread id');
|
|
164
|
+
}
|
|
165
|
+
return id;
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=ask.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ask.js","sourceRoot":"","sources":["../../../../src/bin/c4s/commands/ask.ts"],"names":[],"mappings":"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"}
|
package/dist/bin/c4s/errors.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type CliErrorCode = 'PROJECT_NOT_FOUND' | 'ENTITY_NOT_FOUND' | 'SECTION_NOT_FOUND' | 'INVALID_TYPE' | 'INVALID_ARGS' | 'AMBIGUOUS_SLUGS' | 'SCHEMA_OUT_OF_DATE' | 'FILE_NOT_FOUND' | 'UNKNOWN_COMMAND';
|
|
1
|
+
export type CliErrorCode = 'PROJECT_NOT_FOUND' | 'ENTITY_NOT_FOUND' | 'SECTION_NOT_FOUND' | 'INVALID_TYPE' | 'INVALID_ARGS' | 'AMBIGUOUS_SLUGS' | 'SCHEMA_OUT_OF_DATE' | 'FILE_NOT_FOUND' | 'UNKNOWN_COMMAND' | 'SERVER_NOT_RUNNING' | 'SERVER_NOT_RECOGNIZED' | 'NOT_FOUND' | 'STREAM_IN_PROGRESS' | 'AGENT_UNAVAILABLE' | 'AGENT_ERROR' | 'TIMEOUT' | 'ABORTED';
|
|
2
2
|
export declare class CliError extends Error {
|
|
3
3
|
code: CliErrorCode;
|
|
4
4
|
hint?: string | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/bin/c4s/errors.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/bin/c4s/errors.ts"],"names":[],"mappings":"AAoBA,MAAM,OAAO,QAAS,SAAQ,KAAK;IACd;IAA4C;IAA/D,YAAmB,IAAkB,EAAE,OAAe,EAAS,IAAa;QAC1E,KAAK,CAAC,OAAO,CAAC,CAAC;QADE,SAAI,GAAJ,IAAI,CAAc;QAA0B,SAAI,GAAJ,IAAI,CAAS;QAE1E,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;IACzB,CAAC;CACF"}
|
|
@@ -1 +1,7 @@
|
|
|
1
1
|
export declare function resolveProject(override?: string): string;
|
|
2
|
+
/**
|
|
3
|
+
* Wariant `resolveProject` dla `c4s ask` — markerem waznosci projektu jest
|
|
4
|
+
* `.claude4spec/config.json` (nie `db.sqlite`). `ask` nie czyta encji, tylko
|
|
5
|
+
* potrzebuje `config.json.port` do discovery serwera.
|
|
6
|
+
*/
|
|
7
|
+
export declare function resolveProjectByConfig(override?: string): string;
|
package/dist/bin/c4s/project.js
CHANGED
|
@@ -20,4 +20,29 @@ export function resolveProject(override) {
|
|
|
20
20
|
dir = parent;
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* Wariant `resolveProject` dla `c4s ask` — markerem waznosci projektu jest
|
|
25
|
+
* `.claude4spec/config.json` (nie `db.sqlite`). `ask` nie czyta encji, tylko
|
|
26
|
+
* potrzebuje `config.json.port` do discovery serwera.
|
|
27
|
+
*/
|
|
28
|
+
export function resolveProjectByConfig(override) {
|
|
29
|
+
const hasConfig = (dir) => fs.existsSync(path.join(dir, '.claude4spec', 'config.json'));
|
|
30
|
+
if (override) {
|
|
31
|
+
const abs = path.resolve(process.cwd(), override);
|
|
32
|
+
if (!hasConfig(abs)) {
|
|
33
|
+
throw new CliError('PROJECT_NOT_FOUND', `no claude4spec project at ${abs}`, 'check the path or run `npx claude4spec` there first');
|
|
34
|
+
}
|
|
35
|
+
return abs;
|
|
36
|
+
}
|
|
37
|
+
let dir = process.cwd();
|
|
38
|
+
while (true) {
|
|
39
|
+
if (hasConfig(dir))
|
|
40
|
+
return dir;
|
|
41
|
+
const parent = path.dirname(dir);
|
|
42
|
+
if (parent === dir) {
|
|
43
|
+
throw new CliError('PROJECT_NOT_FOUND', 'no claude4spec project found in current directory or any parent', 'run `npx claude4spec` first or pass `--project <path>`');
|
|
44
|
+
}
|
|
45
|
+
dir = parent;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
23
48
|
//# sourceMappingURL=project.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project.js","sourceRoot":"","sources":["../../../src/bin/c4s/project.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,MAAM,UAAU,cAAc,CAAC,QAAiB;IAC9C,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,CAAC,CAAC;QAClD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC;YAChE,MAAM,IAAI,QAAQ,CAChB,mBAAmB,EACnB,6BAA6B,GAAG,EAAE,EAClC,qDAAqD,CACtD,CAAC;QACJ,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IACD,IAAI,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IACxB,OAAO,IAAI,EAAE,CAAC;QACZ,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,EAAE,WAAW,CAAC,CAAC;YAAE,OAAO,GAAG,CAAC;QAC3E,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;YACnB,MAAM,IAAI,QAAQ,CAChB,mBAAmB,EACnB,iEAAiE,EACjE,wDAAwD,CACzD,CAAC;QACJ,CAAC;QACD,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;AACH,CAAC"}
|
|
1
|
+
{"version":3,"file":"project.js","sourceRoot":"","sources":["../../../src/bin/c4s/project.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,MAAM,UAAU,cAAc,CAAC,QAAiB;IAC9C,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,CAAC,CAAC;QAClD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC;YAChE,MAAM,IAAI,QAAQ,CAChB,mBAAmB,EACnB,6BAA6B,GAAG,EAAE,EAClC,qDAAqD,CACtD,CAAC;QACJ,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IACD,IAAI,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IACxB,OAAO,IAAI,EAAE,CAAC;QACZ,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,EAAE,WAAW,CAAC,CAAC;YAAE,OAAO,GAAG,CAAC;QAC3E,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;YACnB,MAAM,IAAI,QAAQ,CAChB,mBAAmB,EACnB,iEAAiE,EACjE,wDAAwD,CACzD,CAAC;QACJ,CAAC;QACD,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,QAAiB;IACtD,MAAM,SAAS,GAAG,CAAC,GAAW,EAAE,EAAE,CAChC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,EAAE,aAAa,CAAC,CAAC,CAAC;IAC/D,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,CAAC,CAAC;QAClD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;YACpB,MAAM,IAAI,QAAQ,CAChB,mBAAmB,EACnB,6BAA6B,GAAG,EAAE,EAClC,qDAAqD,CACtD,CAAC;QACJ,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IACD,IAAI,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IACxB,OAAO,IAAI,EAAE,CAAC;QACZ,IAAI,SAAS,CAAC,GAAG,CAAC;YAAE,OAAO,GAAG,CAAC;QAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;YACnB,MAAM,IAAI,QAAQ,CAChB,mBAAmB,EACnB,iEAAiE,EACjE,wDAAwD,CACzD,CAAC;QACJ,CAAC;QACD,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;AACH,CAAC"}
|
package/dist/bin/c4s.js
CHANGED
|
@@ -15,6 +15,7 @@ import { runCatalog } from './c4s/commands/catalog.js';
|
|
|
15
15
|
import { runListTags } from './c4s/commands/list-tags.js';
|
|
16
16
|
import { runListSlugs } from './c4s/commands/list-slugs.js';
|
|
17
17
|
import { runResolve } from './c4s/commands/resolve.js';
|
|
18
|
+
import { runAsk } from './c4s/commands/ask.js';
|
|
18
19
|
const HELP = `Usage: c4s <command> [options]
|
|
19
20
|
|
|
20
21
|
Tag commands (1:1 with XML tag names):
|
|
@@ -30,6 +31,12 @@ Detail view (no XML counterpart):
|
|
|
30
31
|
Utility:
|
|
31
32
|
resolve <file.md> [--format inline|json]
|
|
32
33
|
|
|
34
|
+
Agent Q&A (requires a running \`npx claude4spec\` server):
|
|
35
|
+
ask "<msg>" --ct chat
|
|
36
|
+
ask "<msg>" --ct brief --brief <path>
|
|
37
|
+
ask "<msg>" --thread <id>
|
|
38
|
+
--server <url> override server discovery (remote / one-off --port)
|
|
39
|
+
|
|
33
40
|
Discovery:
|
|
34
41
|
catalog
|
|
35
42
|
list-tags
|
|
@@ -43,7 +50,7 @@ Global flags:
|
|
|
43
50
|
--version print c4s version
|
|
44
51
|
--help show this help
|
|
45
52
|
`;
|
|
46
|
-
function main() {
|
|
53
|
+
async function main() {
|
|
47
54
|
const argv = process.argv.slice(2);
|
|
48
55
|
if (argv.length === 0 || argv[0] === '--help' || argv[0] === '-h') {
|
|
49
56
|
process.stdout.write(HELP);
|
|
@@ -78,6 +85,8 @@ function main() {
|
|
|
78
85
|
return runListTags(args);
|
|
79
86
|
case 'list-slugs':
|
|
80
87
|
return runListSlugs(args);
|
|
88
|
+
case 'ask':
|
|
89
|
+
return runAsk(args);
|
|
81
90
|
default:
|
|
82
91
|
throw new CliError('UNKNOWN_COMMAND', `unknown command '${args.command}'`, 'run `c4s --help`');
|
|
83
92
|
}
|
|
@@ -102,10 +111,7 @@ function readPackageVersion() {
|
|
|
102
111
|
}
|
|
103
112
|
return 'unknown';
|
|
104
113
|
}
|
|
105
|
-
|
|
106
|
-
main();
|
|
107
|
-
}
|
|
108
|
-
catch (err) {
|
|
114
|
+
main().catch((err) => {
|
|
109
115
|
if (err instanceof CliError) {
|
|
110
116
|
writeError(err);
|
|
111
117
|
process.exit(codeToExit(err.code));
|
|
@@ -113,7 +119,7 @@ catch (err) {
|
|
|
113
119
|
const message = err instanceof Error ? err.message : String(err);
|
|
114
120
|
writeError(new CliError('UNKNOWN_COMMAND', message));
|
|
115
121
|
process.exit(1);
|
|
116
|
-
}
|
|
122
|
+
});
|
|
117
123
|
function codeToExit(code) {
|
|
118
124
|
switch (code) {
|
|
119
125
|
case 'PROJECT_NOT_FOUND':
|
package/dist/bin/c4s.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"c4s.js","sourceRoot":"","sources":["../../src/bin/c4s.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AACzE,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"c4s.js","sourceRoot":"","sources":["../../src/bin/c4s.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export declare const BRIEF_IMPLEMENTER_FRONTMATTER = "---\nname: c4s-brief-implementer\ndescription: Implement features described in claude4spec briefs (markdown files in .claude4spec/briefs/). Briefs are self-contained \u2014 they include all context needed for implementation (entity snapshots, section diffs, narrative). After implementation, if you discover drift between the brief and reality (missing details, incorrect assumptions, edge cases not covered), generate a patch file in .claude4spec/patches/ as feedback for the specification author. Use when implementing changes in a code repository that has a .claude4spec/briefs/ directory.\n---\n";
|
|
2
|
-
export declare const BRIEF_IMPLEMENTER_BODY = "# c4s-brief-implementer\n\nThis skill describes how to implement a release brief in **your code repository**\n(not the spec repo). A brief is a self-contained markdown file under\n`.claude4spec/briefs/` that captures everything you need to ship the change:\nentity snapshots, section diffs, narrative, acceptance criteria.\n\n**This skill does NOT assume the `c4s` CLI is installed.** Briefs are designed\nto be self-contained \u2014 you do not need to read the main specification or query\nthe entity database. If the brief references something you cannot find in its\nbody, treat that as drift and file a patch (step 4 below).\n\n## Workflow\n\n### 1. Discover\n\n```sh\nls .claude4spec/briefs/ # list available briefs\ncat .claude4spec/briefs/<slug>.md\n```\n\nIf `.claude4spec/` is not in your current directory, walk up the directory tree\nuntil you find it (similar to how git finds `.git/`).\n\n### 2. Read the brief as self-contained input\n\nEvery brief has YAML frontmatter:\n\n```yaml\n---\ntype: brief\nfrom_release: v0.1.16\nto_release: v0.1.17\ngenerator_version: brief-author@0.1\nimplemented: false\n---\n```\n\nThe body contains everything you need \u2014 entity snapshots, section diffs, the\nnarrative of what changes, and acceptance criteria. **Do not read the main\nspecification.** If the brief omits something, that is drift (see step 4).\n\n### 3. Implement\n\nStandard code flow in your target repository: read existing code, plan, edit,\ntest. Stay focused on what the brief specifies.\n\n### 4. Feedback loop (patches)\n\nWhen you discover that the brief diverges from reality \u2014 a missing detail, an\nincorrect assumption, an edge case not covered, or anything else the\nspec-author should know \u2014 write a patch file:\n\n```sh\nmkdir -p .claude4spec/patches\n```\n\nCreate `.claude4spec/patches/<brief-slug>-<short-desc>.md` with this format:\n\n```markdown\n---\ntype: patch\nbrief: v0-1-16-to-v0-1-17.md # path relative to briefs/\npatch_kind: drift # drift | missing | incorrect | clarification\ncreated_at: 2026-05-11T17:32:00Z\ncreated_by: claude-code # or \"cursor\", \"aider\", ...\n---\n\n# Patch \u2014 short title\n\n## What I found\n\n\u2026description of the drift / missing detail / incorrect assumption\u2026\n\n## Suggestion\n\n\u2026what the spec-author should consider in a follow-up brief or entity edits\u2026\n```\n\nPatch-kind values:\n\n- `drift` \u2014 the brief described behavior X, but the codebase already does Y.\n- `missing` \u2014 the brief is silent on a detail you had to decide yourself.\n- `incorrect` \u2014 the brief is factually wrong about existing code.\n- `clarification` \u2014 the brief is ambiguous; you guessed but it should be made\n explicit for next time.\n\nThe `.claude4spec/patches/` directory is created **lazily** \u2014 only when you\nfile your first patch. The claude4spec server does NOT create it.\n\n### 5. Mark brief as implemented\n\nWhen the implementation is genuinely finished \u2014 code committed, tests green,\nmerged to main / accepted by the user \u2014 flip the brief's frontmatter to\n`implemented: true`:\n\n```bash\n# Option A \u2014 Edit tool: change the line `implemented: false` \u2192 `implemented: true`.\n# Option B \u2014 yq (idempotent; adds the field to legacy briefs that never had it):\nyq -i '.implemented = true' .claude4spec/briefs/<brief-slug>.md\n```\n\n`implemented: true` is a **declaration**, not a computed fact derived from git.\nA revert on main does NOT roll the flag back. Set it ONLY when implementation\nis realistically done \u2014 never proactively or \"just in case\".\n\n### 6. Hand-off\n\nThe spec-author reads patches manually (`ls .claude4spec/patches/`, `cat`)\nand folds them into the next brief or entity edits. There is no UI listing in\nthis release \u2014 patches are raw markdown.\n\n## Notes\n\nThis file is **fully managed** by claude4spec \u2014 it is overwritten on every\nserver start when its rendered content changes. Do not edit it by hand.\n";
|
|
2
|
+
export declare const BRIEF_IMPLEMENTER_BODY = "# c4s-brief-implementer\n\nThis skill describes how to implement a release brief in **your code repository**\n(not the spec repo). A brief is a self-contained markdown file under\n`.claude4spec/briefs/` that captures everything you need to ship the change:\nentity snapshots, section diffs, narrative, acceptance criteria.\n\n**This skill does NOT assume the `c4s` CLI is installed.** Briefs are designed\nto be self-contained \u2014 you do not need to read the main specification or query\nthe entity database. If the brief references something you cannot find in its\nbody, treat that as drift and file a patch (step 4 below).\n\n## Workflow\n\n### 1. Discover\n\n```sh\nls .claude4spec/briefs/ # list available briefs\ncat .claude4spec/briefs/<slug>.md\n```\n\nIf `.claude4spec/` is not in your current directory, walk up the directory tree\nuntil you find it (similar to how git finds `.git/`).\n\n### 2. Read the brief as self-contained input\n\nEvery brief has YAML frontmatter:\n\n```yaml\n---\ntype: brief\nfrom_release: v0.1.16\nto_release: v0.1.17\ngenerator_version: brief-author@0.1\nimplemented: false\n---\n```\n\nThe body contains everything you need \u2014 entity snapshots, section diffs, the\nnarrative of what changes, and acceptance criteria. **Do not read the main\nspecification.** If the brief omits something, that is drift (see step 4).\n\n### 3. Implement\n\nStandard code flow in your target repository: read existing code, plan, edit,\ntest. Stay focused on what the brief specifies.\n\n### 4. Feedback loop (patches)\n\n**Optional \u2014 ask the spec agent first.** When the brief is unclear, you can \u2014\n*before* guessing or writing a speculative patch \u2014 ask the specification agent\nsynchronously and get an answer back in the same terminal:\n\n```bash\nc4s ask \"Brief nie precyzuje X \u2014 czy chodzi o A czy B?\" --ct brief --brief <brief-slug>.md\n```\n\nContinue the same thread with `c4s ask \"...\" --thread <threadId>` (the\n`threadId` is printed with the answer). This escalation path is **optional**:\nit requires `c4s` installed *and* a running `npx claude4spec` server. When\neither is unavailable, skip it \u2014 the async patch loop below still works, and\nthe core workflow never assumes `c4s` is present.\n\nWhen you discover that the brief diverges from reality \u2014 a missing detail, an\nincorrect assumption, an edge case not covered, or anything else the\nspec-author should know \u2014 write a patch file:\n\n```sh\nmkdir -p .claude4spec/patches\n```\n\nCreate `.claude4spec/patches/<brief-slug>-<short-desc>.md` with this format:\n\n```markdown\n---\ntype: patch\nbrief: v0-1-16-to-v0-1-17.md # path relative to briefs/\npatch_kind: drift # drift | missing | incorrect | clarification\ncreated_at: 2026-05-11T17:32:00Z\ncreated_by: claude-code # or \"cursor\", \"aider\", ...\n---\n\n# Patch \u2014 short title\n\n## What I found\n\n\u2026description of the drift / missing detail / incorrect assumption\u2026\n\n## Suggestion\n\n\u2026what the spec-author should consider in a follow-up brief or entity edits\u2026\n```\n\nPatch-kind values:\n\n- `drift` \u2014 the brief described behavior X, but the codebase already does Y.\n- `missing` \u2014 the brief is silent on a detail you had to decide yourself.\n- `incorrect` \u2014 the brief is factually wrong about existing code.\n- `clarification` \u2014 the brief is ambiguous; you guessed but it should be made\n explicit for next time.\n\nThe `.claude4spec/patches/` directory is created **lazily** \u2014 only when you\nfile your first patch. The claude4spec server does NOT create it.\n\n### 5. Mark brief as implemented\n\nWhen the implementation is genuinely finished \u2014 code committed, tests green,\nmerged to main / accepted by the user \u2014 flip the brief's frontmatter to\n`implemented: true`:\n\n```bash\n# Option A \u2014 Edit tool: change the line `implemented: false` \u2192 `implemented: true`.\n# Option B \u2014 yq (idempotent; adds the field to legacy briefs that never had it):\nyq -i '.implemented = true' .claude4spec/briefs/<brief-slug>.md\n```\n\n`implemented: true` is a **declaration**, not a computed fact derived from git.\nA revert on main does NOT roll the flag back. Set it ONLY when implementation\nis realistically done \u2014 never proactively or \"just in case\".\n\n### 6. Hand-off\n\nThe spec-author reads patches manually (`ls .claude4spec/patches/`, `cat`)\nand folds them into the next brief or entity edits. There is no UI listing in\nthis release \u2014 patches are raw markdown.\n\n## Notes\n\nThis file is **fully managed** by claude4spec \u2014 it is overwritten on every\nserver start when its rendered content changes. Do not edit it by hand.\n";
|
|
@@ -52,6 +52,20 @@ test. Stay focused on what the brief specifies.
|
|
|
52
52
|
|
|
53
53
|
### 4. Feedback loop (patches)
|
|
54
54
|
|
|
55
|
+
**Optional — ask the spec agent first.** When the brief is unclear, you can —
|
|
56
|
+
*before* guessing or writing a speculative patch — ask the specification agent
|
|
57
|
+
synchronously and get an answer back in the same terminal:
|
|
58
|
+
|
|
59
|
+
\`\`\`bash
|
|
60
|
+
c4s ask "Brief nie precyzuje X — czy chodzi o A czy B?" --ct brief --brief <brief-slug>.md
|
|
61
|
+
\`\`\`
|
|
62
|
+
|
|
63
|
+
Continue the same thread with \`c4s ask "..." --thread <threadId>\` (the
|
|
64
|
+
\`threadId\` is printed with the answer). This escalation path is **optional**:
|
|
65
|
+
it requires \`c4s\` installed *and* a running \`npx claude4spec\` server. When
|
|
66
|
+
either is unavailable, skip it — the async patch loop below still works, and
|
|
67
|
+
the core workflow never assumes \`c4s\` is present.
|
|
68
|
+
|
|
55
69
|
When you discover that the brief diverges from reality — a missing detail, an
|
|
56
70
|
incorrect assumption, an edge case not covered, or anything else the
|
|
57
71
|
spec-author should know — write a patch file:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"brief-implementer-template.js","sourceRoot":"","sources":["../../../src/server/external-skills/brief-implementer-template.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,6BAA6B,GAAG;;;;CAI5C,CAAC;AAEF,MAAM,CAAC,MAAM,sBAAsB,GAAG
|
|
1
|
+
{"version":3,"file":"brief-implementer-template.js","sourceRoot":"","sources":["../../../src/server/external-skills/brief-implementer-template.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,6BAA6B,GAAG;;;;CAI5C,CAAC;AAEF,MAAM,CAAC,MAAM,sBAAsB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkIrC,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export declare const SPEC_READER_FRONTMATTER = "---\nname: c4s-spec-reader\ndescription: Read claude4spec specification entities (endpoints, DTOs, tables, AC, UI views) referenced from markdown pages through XML tags like <inline_mention/>, <single_element/>, <tagged_list/>. Use when working in a repository whose pages/ contain these tags or whose .claude4spec/ directory exists. Resolves entity slugs to full data via c4s CLI or c4s-reader MCP server.\n---\n";
|
|
2
|
-
export declare const SPEC_READER_BODY = "# c4s-spec-reader\n\nThis repository contains a claude4spec specification. Pages (`*.md`) reference\nentities stored in `.claude4spec/db.sqlite` through XML tags. This skill teaches\nyou how to resolve them.\n\nAll commands below walk up from the agent's cwd to the nearest `.claude4spec/` \u2014\nno absolute paths are required.\n\n## Resolving a tag\n\nInstall `claude4spec` (Node 20+) and use the `c4s` CLI. Subcommand names match\nXML tag names 1:1.\n\n| XML tag | CLI equivalent |\n|---------|----------------|\n| `<inline_mention type=\"endpoint\" slug=\"X\"/>` | `c4s inline_mention --type endpoint --slug X` |\n| `<single_element type=\"dto\" slug=\"X\"/>` | `c4s single_element --type dto --slug X` |\n| `<element_list type=\"endpoint\" slugs=\"a,b,c\"/>` | `c4s element_list --type endpoint --slugs a,b,c` |\n| `<tagged_list type=\"dto\" tags=\"auth\" filter=\"and\"/>` | `c4s tagged_list --type dto --tags auth --filter and` |\n| `<tagged_list_mixed tags=\"public\"/>` | `c4s tagged_list_mixed --tags public` |\n\n## Expanding a whole page\n\n```sh\nc4s resolve some-page.md # writes markdown with tags expanded inline\nc4s resolve some-page.md --format json # writes { content, resolved: [...] }\n```\n\n## Discovery\n\n- `c4s catalog` \u2014 entity types, versions, and JSON Schema per view.\n- `c4s list-tags` \u2014 all tags with per-type counts.\n- `c4s list-slugs --type endpoint` \u2014 all slugs for a given type.\n\nAll output is JSON (pretty) by default. Use `--compact` for pipelines and\n`--format text` for terminal-friendly output. Errors go to stderr as JSON with\nan exit code > 0.\n\nThe database is opened **read-only** \u2014 `c4s` never mutates the project.\n";
|
|
2
|
+
export declare const SPEC_READER_BODY = "# c4s-spec-reader\n\nThis repository contains a claude4spec specification. Pages (`*.md`) reference\nentities stored in `.claude4spec/db.sqlite` through XML tags. This skill teaches\nyou how to resolve them.\n\nAll commands below walk up from the agent's cwd to the nearest `.claude4spec/` \u2014\nno absolute paths are required.\n\n## Resolving a tag\n\nInstall `claude4spec` (Node 20+) and use the `c4s` CLI. Subcommand names match\nXML tag names 1:1.\n\n| XML tag | CLI equivalent |\n|---------|----------------|\n| `<inline_mention type=\"endpoint\" slug=\"X\"/>` | `c4s inline_mention --type endpoint --slug X` |\n| `<single_element type=\"dto\" slug=\"X\"/>` | `c4s single_element --type dto --slug X` |\n| `<element_list type=\"endpoint\" slugs=\"a,b,c\"/>` | `c4s element_list --type endpoint --slugs a,b,c` |\n| `<tagged_list type=\"dto\" tags=\"auth\" filter=\"and\"/>` | `c4s tagged_list --type dto --tags auth --filter and` |\n| `<tagged_list_mixed tags=\"public\"/>` | `c4s tagged_list_mixed --tags public` |\n\n## Expanding a whole page\n\n```sh\nc4s resolve some-page.md # writes markdown with tags expanded inline\nc4s resolve some-page.md --format json # writes { content, resolved: [...] }\n```\n\n## Discovery\n\n- `c4s catalog` \u2014 entity types, versions, and JSON Schema per view.\n- `c4s list-tags` \u2014 all tags with per-type counts.\n- `c4s list-slugs --type endpoint` \u2014 all slugs for a given type.\n\nAll output is JSON (pretty) by default. Use `--compact` for pipelines and\n`--format text` for terminal-friendly output. Errors go to stderr as JSON with\nan exit code > 0.\n\nThe database is opened **read-only** \u2014 `c4s` never mutates the project.\n\n## Asking the spec agent\n\nWhen a question goes beyond resolving entities or pages, `c4s ask` runs a\nsynchronous agent turn against the specification:\n\n```sh\nc4s ask \"<question>\" --ct chat\n```\n\nUnlike the read-only commands above, `c4s ask` requires a running\n`npx claude4spec` server (it delegates the turn to the server's agent).\n";
|
|
@@ -43,5 +43,17 @@ All output is JSON (pretty) by default. Use \`--compact\` for pipelines and
|
|
|
43
43
|
an exit code > 0.
|
|
44
44
|
|
|
45
45
|
The database is opened **read-only** — \`c4s\` never mutates the project.
|
|
46
|
+
|
|
47
|
+
## Asking the spec agent
|
|
48
|
+
|
|
49
|
+
When a question goes beyond resolving entities or pages, \`c4s ask\` runs a
|
|
50
|
+
synchronous agent turn against the specification:
|
|
51
|
+
|
|
52
|
+
\`\`\`sh
|
|
53
|
+
c4s ask "<question>" --ct chat
|
|
54
|
+
\`\`\`
|
|
55
|
+
|
|
56
|
+
Unlike the read-only commands above, \`c4s ask\` requires a running
|
|
57
|
+
\`npx claude4spec\` server (it delegates the turn to the server's agent).
|
|
46
58
|
`;
|
|
47
59
|
//# sourceMappingURL=spec-reader-template.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spec-reader-template.js","sourceRoot":"","sources":["../../../src/server/external-skills/spec-reader-template.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,uBAAuB,GAAG;;;;CAItC,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG
|
|
1
|
+
{"version":3,"file":"spec-reader-template.js","sourceRoot":"","sources":["../../../src/server/external-skills/spec-reader-template.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,uBAAuB,GAAG;;;;CAItC,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoD/B,CAAC"}
|
package/dist/server/index.js
CHANGED
|
@@ -48,31 +48,33 @@ import { pluginHostRouter } from './core/plugin-host/cross-cutting.js';
|
|
|
48
48
|
import './serialization/registerAll.js';
|
|
49
49
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
50
50
|
const DEFAULT_PORT = 3000;
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
51
|
+
// M01: deterministyczny port. Przy zajetym porcie serwer NIE wskakuje juz na
|
|
52
|
+
// `port+1` — failuje z czytelnym bledem i niezerowym exit code. Powod: stały
|
|
53
|
+
// `config.json.port` jest warunkiem discovery serwera przez `c4s ask`.
|
|
54
|
+
async function listenOrExit(server, port) {
|
|
55
|
+
try {
|
|
56
|
+
await new Promise((resolve, reject) => {
|
|
57
|
+
const onError = (err) => {
|
|
58
|
+
server.off('listening', onListening);
|
|
59
|
+
reject(err);
|
|
60
|
+
};
|
|
61
|
+
const onListening = () => {
|
|
62
|
+
server.off('error', onError);
|
|
63
|
+
resolve();
|
|
64
|
+
};
|
|
65
|
+
server.once('error', onError);
|
|
66
|
+
server.once('listening', onListening);
|
|
67
|
+
server.listen(port);
|
|
68
|
+
});
|
|
69
|
+
return port;
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
if (err.code === 'EADDRINUSE') {
|
|
73
|
+
console.error(`port ${port} zajęty — zatrzymaj drugą instancję lub zmień port w config.json / przekaż --port`);
|
|
74
|
+
process.exit(1);
|
|
73
75
|
}
|
|
76
|
+
throw err;
|
|
74
77
|
}
|
|
75
|
-
throw new Error(`No free port in range ${startPort}–${startPort + PORT_FALLBACK_LIMIT}`);
|
|
76
78
|
}
|
|
77
79
|
async function mountDevVite(app, cwd) {
|
|
78
80
|
const { createServer } = await import('vite');
|
|
@@ -366,15 +368,9 @@ export async function startServer(opts) {
|
|
|
366
368
|
app.use('/api/tags', tagsRouter(tagsService, referencesService));
|
|
367
369
|
app.use('/api/references', referencesRouter(referencesService));
|
|
368
370
|
app.use('/api/entities', entitiesRouter(tagsService, versionService));
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
app.use('/api/page-links', pageLinksRouter(pagesLinkIndexer));
|
|
373
|
-
app.use('/api/plans', plansRouter(planService));
|
|
374
|
-
app.use('/api/releases', releasesRouter(releaseService, gateway));
|
|
375
|
-
app.use('/api/briefs', briefsRouter(briefService, pageVersions));
|
|
376
|
-
app.use('/api/patches', patchesRouter(patchService));
|
|
377
|
-
app.use('/api/chat', chatRouter({
|
|
371
|
+
// Wspolne deps tury agenta — `threadsRouter` (POST /:id/ask) i `chatRouter`
|
|
372
|
+
// (POST /api/chat, SSE) dziela ten sam runtime i rejestr `activeAdapters`.
|
|
373
|
+
const agentDeps = {
|
|
378
374
|
chatService,
|
|
379
375
|
pagesService: pages,
|
|
380
376
|
tagsService,
|
|
@@ -390,7 +386,16 @@ export async function startServer(opts) {
|
|
|
390
386
|
pagesDir,
|
|
391
387
|
mode,
|
|
392
388
|
db,
|
|
393
|
-
}
|
|
389
|
+
};
|
|
390
|
+
app.use('/api/threads', threadsRouter(agentDeps));
|
|
391
|
+
app.use('/api/sections', sectionsRouter(sectionsService));
|
|
392
|
+
app.use('/api/todos', todosRouter(todosIndexer));
|
|
393
|
+
app.use('/api/page-links', pageLinksRouter(pagesLinkIndexer));
|
|
394
|
+
app.use('/api/plans', plansRouter(planService));
|
|
395
|
+
app.use('/api/releases', releasesRouter(releaseService, gateway));
|
|
396
|
+
app.use('/api/briefs', briefsRouter(briefService, pageVersions));
|
|
397
|
+
app.use('/api/patches', patchesRouter(patchService));
|
|
398
|
+
app.use('/api/chat', chatRouter(agentDeps));
|
|
394
399
|
app.use(errorHandler);
|
|
395
400
|
watcher.onChange((relPath, kind) => {
|
|
396
401
|
if (kind === 'unlink') {
|
|
@@ -519,7 +524,7 @@ export async function startServer(opts) {
|
|
|
519
524
|
}
|
|
520
525
|
})();
|
|
521
526
|
const closeAssets = mode === 'dev' ? await mountDevVite(app, cwd) : mountProd(app, cwd);
|
|
522
|
-
const port = await
|
|
527
|
+
const port = await listenOrExit(httpServer, portRef.current);
|
|
523
528
|
portRef.current = port;
|
|
524
529
|
const url = `http://localhost:${port}`;
|
|
525
530
|
const writingStyle = initialWritingStyle
|