@harness-engineering/cli 1.25.2 → 1.25.4
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/dist/bin/harness-mcp.js +1 -1
- package/dist/bin/harness.js +2 -2
- package/dist/{chunk-5I3W4J5X.js → chunk-2KZAXESR.js} +9 -4
- package/dist/{chunk-TBGIHPNA.js → chunk-BUYW3SA2.js} +201 -200
- package/dist/index.js +2 -2
- package/dist/{mcp-W3FLXSFF.js → mcp-JZ7YB7TD.js} +1 -1
- package/dist/templates/orchestrator/template.json +1 -1
- package/package.json +5 -5
- /package/dist/templates/orchestrator/{WORKFLOW.md → harness.orchestrator.md} +0 -0
package/dist/bin/harness-mcp.js
CHANGED
package/dist/bin/harness.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
createProgram,
|
|
4
4
|
printFirstRunWelcome
|
|
5
|
-
} from "../chunk-
|
|
5
|
+
} from "../chunk-2KZAXESR.js";
|
|
6
6
|
import "../chunk-5BQ5BOJL.js";
|
|
7
7
|
import "../chunk-EHRZMOQ2.js";
|
|
8
8
|
import "../chunk-XTITAVUR.js";
|
|
@@ -19,7 +19,7 @@ import "../chunk-P7PANON5.js";
|
|
|
19
19
|
import "../chunk-4NK7Z3BP.js";
|
|
20
20
|
import {
|
|
21
21
|
dispatchSkillsFromGit
|
|
22
|
-
} from "../chunk-
|
|
22
|
+
} from "../chunk-BUYW3SA2.js";
|
|
23
23
|
import "../chunk-FES2YEQU.js";
|
|
24
24
|
import "../chunk-UV3BZMGT.js";
|
|
25
25
|
import "../chunk-F23H3U5U.js";
|
|
@@ -56,7 +56,7 @@ import {
|
|
|
56
56
|
loadOrRebuildIndex,
|
|
57
57
|
persistToolingConfig,
|
|
58
58
|
recommend
|
|
59
|
-
} from "./chunk-
|
|
59
|
+
} from "./chunk-BUYW3SA2.js";
|
|
60
60
|
import {
|
|
61
61
|
findConfigFile,
|
|
62
62
|
resolveConfig
|
|
@@ -2162,6 +2162,11 @@ function runDashboard(opts) {
|
|
|
2162
2162
|
DASHBOARD_CLIENT_PORT: String(clientPort),
|
|
2163
2163
|
HARNESS_PROJECT_PATH: projectPath
|
|
2164
2164
|
};
|
|
2165
|
+
if (opts.orchestratorUrl) {
|
|
2166
|
+
env["ORCHESTRATOR_URL"] = opts.orchestratorUrl;
|
|
2167
|
+
} else if (!env["ORCHESTRATOR_URL"] && !env["ORCHESTRATOR_PORT"]) {
|
|
2168
|
+
env["ORCHESTRATOR_PORT"] = "8080";
|
|
2169
|
+
}
|
|
2165
2170
|
spawnDashboardServer(server, env);
|
|
2166
2171
|
console.log(`Dashboard API starting on http://localhost:${apiPort}`);
|
|
2167
2172
|
console.log(`Open ${url} (pass --no-open to suppress)`);
|
|
@@ -2170,7 +2175,7 @@ function runDashboard(opts) {
|
|
|
2170
2175
|
}
|
|
2171
2176
|
}
|
|
2172
2177
|
function createDashboardCommand() {
|
|
2173
|
-
return new Command19("dashboard").description("Start the Harness local web dashboard").option("--port <port>", "Client dev server port", String(DEFAULT_CLIENT_PORT)).option("--api-port <port>", "API server port", String(DEFAULT_API_PORT)).option("--no-open", "Do not automatically open browser").option("--cwd <path>", "Project directory (defaults to cwd)").action((opts) => runDashboard(opts));
|
|
2178
|
+
return new Command19("dashboard").description("Start the Harness local web dashboard").option("--port <port>", "Client dev server port", String(DEFAULT_CLIENT_PORT)).option("--api-port <port>", "API server port", String(DEFAULT_API_PORT)).option("--orchestrator-url <url>", "Orchestrator URL (default: http://localhost:8080)").option("--no-open", "Do not automatically open browser").option("--cwd <path>", "Project directory (defaults to cwd)").action((opts) => runDashboard(opts));
|
|
2174
2179
|
}
|
|
2175
2180
|
|
|
2176
2181
|
// src/commands/doctor.ts
|
|
@@ -5423,7 +5428,7 @@ function createMcpCommand() {
|
|
|
5423
5428
|
parseBudget
|
|
5424
5429
|
).action(async (opts) => {
|
|
5425
5430
|
const [{ startServer: startServer2, getToolDefinitions: getToolDefinitions2 }, { selectTier }] = await Promise.all([
|
|
5426
|
-
import("./mcp-
|
|
5431
|
+
import("./mcp-JZ7YB7TD.js"),
|
|
5427
5432
|
import("./tool-tiers-7QGZ3FKY.js")
|
|
5428
5433
|
]);
|
|
5429
5434
|
if (opts.tools && opts.tools.length > 0) {
|
|
@@ -5449,7 +5454,7 @@ import * as path39 from "path";
|
|
|
5449
5454
|
import { Orchestrator, WorkflowLoader, launchTUI } from "@harness-engineering/orchestrator";
|
|
5450
5455
|
function createOrchestratorCommand() {
|
|
5451
5456
|
const orchestrator = new Command47("orchestrator");
|
|
5452
|
-
orchestrator.command("run").description("Run the orchestrator daemon").option("-w, --workflow <path>", "Path to
|
|
5457
|
+
orchestrator.command("run").description("Run the orchestrator daemon").option("-w, --workflow <path>", "Path to harness.orchestrator.md", "harness.orchestrator.md").option("--headless", "Run without TUI (server-only mode for use with web dashboard)").action(async (opts) => {
|
|
5453
5458
|
const workflowPath = path39.resolve(process.cwd(), opts.workflow);
|
|
5454
5459
|
const loader = new WorkflowLoader();
|
|
5455
5460
|
const result = await loader.loadWorkflow(workflowPath);
|
|
@@ -122,6 +122,206 @@ import {
|
|
|
122
122
|
ReadResourceRequestSchema
|
|
123
123
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
124
124
|
|
|
125
|
+
// src/templates/post-write.ts
|
|
126
|
+
import * as fs from "fs";
|
|
127
|
+
import * as path from "path";
|
|
128
|
+
|
|
129
|
+
// src/templates/agents-append.ts
|
|
130
|
+
var FRAMEWORK_SECTIONS = {
|
|
131
|
+
nextjs: {
|
|
132
|
+
title: "Next.js Conventions",
|
|
133
|
+
content: [
|
|
134
|
+
"- Use the App Router (`src/app/`) for all routes",
|
|
135
|
+
'- Server Components by default; add `"use client"` only when needed',
|
|
136
|
+
"- Use `next/image` for images and `next/link` for navigation",
|
|
137
|
+
"- API routes go in `src/app/api/`",
|
|
138
|
+
"- Run `next dev` for development, `next build` for production"
|
|
139
|
+
].join("\n")
|
|
140
|
+
},
|
|
141
|
+
"react-vite": {
|
|
142
|
+
title: "React + Vite Conventions",
|
|
143
|
+
content: [
|
|
144
|
+
"- Component files use `.tsx` extension in `src/`",
|
|
145
|
+
"- Use Vite for dev server and bundling (`npm run dev`)",
|
|
146
|
+
"- Prefer function components with hooks",
|
|
147
|
+
"- CSS modules or styled-components for styling",
|
|
148
|
+
"- Tests use Vitest (`npm test`)"
|
|
149
|
+
].join("\n")
|
|
150
|
+
},
|
|
151
|
+
vue: {
|
|
152
|
+
title: "Vue Conventions",
|
|
153
|
+
content: [
|
|
154
|
+
"- Single File Components (`.vue`) in `src/`",
|
|
155
|
+
"- Use `<script setup>` with Composition API",
|
|
156
|
+
"- Vite for dev server and bundling (`npm run dev`)",
|
|
157
|
+
"- Vue Router for routing, Pinia for state management",
|
|
158
|
+
"- Tests use Vitest (`npm test`)"
|
|
159
|
+
].join("\n")
|
|
160
|
+
},
|
|
161
|
+
express: {
|
|
162
|
+
title: "Express Conventions",
|
|
163
|
+
content: [
|
|
164
|
+
"- Entry point at `src/app.ts`",
|
|
165
|
+
"- Routes in `src/routes/`, middleware in `src/middleware/`",
|
|
166
|
+
"- Use `express.json()` for body parsing",
|
|
167
|
+
"- Error handling via centralized error middleware",
|
|
168
|
+
"- Tests use Vitest with supertest (`npm test`)"
|
|
169
|
+
].join("\n")
|
|
170
|
+
},
|
|
171
|
+
nestjs: {
|
|
172
|
+
title: "NestJS Conventions",
|
|
173
|
+
content: [
|
|
174
|
+
"- Module-based architecture: each feature in its own module",
|
|
175
|
+
"- Use decorators (`@Controller`, `@Injectable`, `@Module`)",
|
|
176
|
+
"- Entry point at `src/main.ts`, root module at `src/app.module.ts`",
|
|
177
|
+
"- Use Nest CLI for generating components (`nest g`)",
|
|
178
|
+
"- Tests use Vitest (`npm test`)"
|
|
179
|
+
].join("\n")
|
|
180
|
+
},
|
|
181
|
+
fastapi: {
|
|
182
|
+
title: "FastAPI Conventions",
|
|
183
|
+
content: [
|
|
184
|
+
"- Entry point at `src/main.py` with FastAPI app instance",
|
|
185
|
+
"- Use Pydantic models for request/response validation",
|
|
186
|
+
"- Async endpoints preferred; sync is acceptable for CPU-bound work",
|
|
187
|
+
"- Run with `uvicorn src.main:app --reload` for development",
|
|
188
|
+
"- Tests use pytest (`pytest`)"
|
|
189
|
+
].join("\n")
|
|
190
|
+
},
|
|
191
|
+
django: {
|
|
192
|
+
title: "Django Conventions",
|
|
193
|
+
content: [
|
|
194
|
+
"- Settings at `src/settings.py`, URLs at `src/urls.py`",
|
|
195
|
+
"- Use `manage.py` for management commands",
|
|
196
|
+
"- Apps in `src/` directory; each app has models, views, urls",
|
|
197
|
+
"- Run with `python manage.py runserver` for development",
|
|
198
|
+
"- Tests use pytest with pytest-django (`pytest`)"
|
|
199
|
+
].join("\n")
|
|
200
|
+
},
|
|
201
|
+
gin: {
|
|
202
|
+
title: "Gin Conventions",
|
|
203
|
+
content: [
|
|
204
|
+
"- Entry point at `main.go` with Gin router setup",
|
|
205
|
+
"- Group routes by feature using `router.Group()`",
|
|
206
|
+
"- Use middleware for logging, auth, error recovery",
|
|
207
|
+
"- Run with `go run main.go` for development",
|
|
208
|
+
"- Tests use `go test ./...`"
|
|
209
|
+
].join("\n")
|
|
210
|
+
},
|
|
211
|
+
axum: {
|
|
212
|
+
title: "Axum Conventions",
|
|
213
|
+
content: [
|
|
214
|
+
"- Entry point at `src/main.rs` with Axum router",
|
|
215
|
+
"- Use extractors for request parsing (`Path`, `Query`, `Json`)",
|
|
216
|
+
"- Shared state via `Extension` or `State`",
|
|
217
|
+
"- Run with `cargo run` for development",
|
|
218
|
+
"- Tests use `cargo test`"
|
|
219
|
+
].join("\n")
|
|
220
|
+
},
|
|
221
|
+
"spring-boot": {
|
|
222
|
+
title: "Spring Boot Conventions",
|
|
223
|
+
content: [
|
|
224
|
+
"- Entry point annotated with `@SpringBootApplication`",
|
|
225
|
+
"- Controllers in `controller/` package, services in `service/`",
|
|
226
|
+
"- Use constructor injection for dependencies",
|
|
227
|
+
"- Run with `mvn spring-boot:run` for development",
|
|
228
|
+
"- Tests use JUnit 5 with Spring Boot Test (`mvn test`)"
|
|
229
|
+
].join("\n")
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
function buildFrameworkSection(framework) {
|
|
233
|
+
const entry = FRAMEWORK_SECTIONS[framework];
|
|
234
|
+
if (!entry) return "";
|
|
235
|
+
return `## ${entry.title}
|
|
236
|
+
|
|
237
|
+
<!-- framework: ${framework} -->
|
|
238
|
+
${entry.content}
|
|
239
|
+
`;
|
|
240
|
+
}
|
|
241
|
+
function appendFrameworkSection(existingContent, framework, _language) {
|
|
242
|
+
if (!framework) return existingContent;
|
|
243
|
+
const startMarker = `<!-- harness:framework-conventions:${framework} -->`;
|
|
244
|
+
const endMarker = `<!-- /harness:framework-conventions:${framework} -->`;
|
|
245
|
+
if (existingContent.includes(startMarker)) return existingContent;
|
|
246
|
+
const section = buildFrameworkSection(framework);
|
|
247
|
+
if (!section) return existingContent;
|
|
248
|
+
const block = `
|
|
249
|
+
${startMarker}
|
|
250
|
+
${section}${endMarker}
|
|
251
|
+
`;
|
|
252
|
+
return existingContent.trimEnd() + "\n" + block;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// src/templates/post-write.ts
|
|
256
|
+
function persistToolingConfig(targetDir, resolveResult, framework) {
|
|
257
|
+
const configPath = path.join(targetDir, "harness.config.json");
|
|
258
|
+
if (!fs.existsSync(configPath)) return;
|
|
259
|
+
try {
|
|
260
|
+
const config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
|
|
261
|
+
const overlayMeta = resolveResult.overlayMetadata;
|
|
262
|
+
if (framework) {
|
|
263
|
+
config.template = config.template || {};
|
|
264
|
+
config.template.framework = framework;
|
|
265
|
+
}
|
|
266
|
+
if (overlayMeta?.tooling) {
|
|
267
|
+
config.tooling = { ...config.tooling, ...overlayMeta.tooling };
|
|
268
|
+
delete config.tooling.lockFile;
|
|
269
|
+
} else if (resolveResult.metadata.tooling && !config.tooling) {
|
|
270
|
+
config.tooling = { ...resolveResult.metadata.tooling };
|
|
271
|
+
delete config.tooling.lockFile;
|
|
272
|
+
}
|
|
273
|
+
if (config.template?.level === null || config.template?.level === void 0) {
|
|
274
|
+
delete config.template.level;
|
|
275
|
+
}
|
|
276
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
|
|
277
|
+
} catch {
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
function ensureHarnessGitignore(targetDir) {
|
|
281
|
+
const gitignorePath = path.join(targetDir, ".harness", ".gitignore");
|
|
282
|
+
const content = `# Runtime artifacts (generated, ephemeral, session-scoped)
|
|
283
|
+
analyses/
|
|
284
|
+
graph/
|
|
285
|
+
debug/
|
|
286
|
+
hooks/
|
|
287
|
+
interactions/
|
|
288
|
+
security/
|
|
289
|
+
sessions/
|
|
290
|
+
workspaces/
|
|
291
|
+
state.json
|
|
292
|
+
state/
|
|
293
|
+
handoff.json
|
|
294
|
+
handoff-*.json
|
|
295
|
+
autopilot-state.json
|
|
296
|
+
session-taint-*.json
|
|
297
|
+
dispatch-last-head.txt
|
|
298
|
+
health-snapshot.json
|
|
299
|
+
release-readiness.json
|
|
300
|
+
skills-index.json
|
|
301
|
+
stack-profile.json
|
|
302
|
+
metrics/
|
|
303
|
+
events.jsonl
|
|
304
|
+
.install-id
|
|
305
|
+
telemetry.json
|
|
306
|
+
.telemetry-notice-shown
|
|
307
|
+
`;
|
|
308
|
+
fs.mkdirSync(path.dirname(gitignorePath), { recursive: true });
|
|
309
|
+
fs.writeFileSync(gitignorePath, content);
|
|
310
|
+
}
|
|
311
|
+
function appendFrameworkAgents(targetDir, framework, language) {
|
|
312
|
+
if (!framework) return;
|
|
313
|
+
const agentsPath = path.join(targetDir, "AGENTS.md");
|
|
314
|
+
if (!fs.existsSync(agentsPath)) return;
|
|
315
|
+
try {
|
|
316
|
+
const existing = fs.readFileSync(agentsPath, "utf-8");
|
|
317
|
+
const updated = appendFrameworkSection(existing, framework, language);
|
|
318
|
+
if (updated !== existing) {
|
|
319
|
+
fs.writeFileSync(agentsPath, updated);
|
|
320
|
+
}
|
|
321
|
+
} catch {
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
125
325
|
// src/mcp/middleware/injection-guard.ts
|
|
126
326
|
init_dist();
|
|
127
327
|
import { realpathSync } from "fs";
|
|
@@ -402,206 +602,6 @@ async function handleValidateLinterConfig(input) {
|
|
|
402
602
|
// src/mcp/tools/init.ts
|
|
403
603
|
import * as path2 from "path";
|
|
404
604
|
import * as fs2 from "fs";
|
|
405
|
-
|
|
406
|
-
// src/templates/post-write.ts
|
|
407
|
-
import * as fs from "fs";
|
|
408
|
-
import * as path from "path";
|
|
409
|
-
|
|
410
|
-
// src/templates/agents-append.ts
|
|
411
|
-
var FRAMEWORK_SECTIONS = {
|
|
412
|
-
nextjs: {
|
|
413
|
-
title: "Next.js Conventions",
|
|
414
|
-
content: [
|
|
415
|
-
"- Use the App Router (`src/app/`) for all routes",
|
|
416
|
-
'- Server Components by default; add `"use client"` only when needed',
|
|
417
|
-
"- Use `next/image` for images and `next/link` for navigation",
|
|
418
|
-
"- API routes go in `src/app/api/`",
|
|
419
|
-
"- Run `next dev` for development, `next build` for production"
|
|
420
|
-
].join("\n")
|
|
421
|
-
},
|
|
422
|
-
"react-vite": {
|
|
423
|
-
title: "React + Vite Conventions",
|
|
424
|
-
content: [
|
|
425
|
-
"- Component files use `.tsx` extension in `src/`",
|
|
426
|
-
"- Use Vite for dev server and bundling (`npm run dev`)",
|
|
427
|
-
"- Prefer function components with hooks",
|
|
428
|
-
"- CSS modules or styled-components for styling",
|
|
429
|
-
"- Tests use Vitest (`npm test`)"
|
|
430
|
-
].join("\n")
|
|
431
|
-
},
|
|
432
|
-
vue: {
|
|
433
|
-
title: "Vue Conventions",
|
|
434
|
-
content: [
|
|
435
|
-
"- Single File Components (`.vue`) in `src/`",
|
|
436
|
-
"- Use `<script setup>` with Composition API",
|
|
437
|
-
"- Vite for dev server and bundling (`npm run dev`)",
|
|
438
|
-
"- Vue Router for routing, Pinia for state management",
|
|
439
|
-
"- Tests use Vitest (`npm test`)"
|
|
440
|
-
].join("\n")
|
|
441
|
-
},
|
|
442
|
-
express: {
|
|
443
|
-
title: "Express Conventions",
|
|
444
|
-
content: [
|
|
445
|
-
"- Entry point at `src/app.ts`",
|
|
446
|
-
"- Routes in `src/routes/`, middleware in `src/middleware/`",
|
|
447
|
-
"- Use `express.json()` for body parsing",
|
|
448
|
-
"- Error handling via centralized error middleware",
|
|
449
|
-
"- Tests use Vitest with supertest (`npm test`)"
|
|
450
|
-
].join("\n")
|
|
451
|
-
},
|
|
452
|
-
nestjs: {
|
|
453
|
-
title: "NestJS Conventions",
|
|
454
|
-
content: [
|
|
455
|
-
"- Module-based architecture: each feature in its own module",
|
|
456
|
-
"- Use decorators (`@Controller`, `@Injectable`, `@Module`)",
|
|
457
|
-
"- Entry point at `src/main.ts`, root module at `src/app.module.ts`",
|
|
458
|
-
"- Use Nest CLI for generating components (`nest g`)",
|
|
459
|
-
"- Tests use Vitest (`npm test`)"
|
|
460
|
-
].join("\n")
|
|
461
|
-
},
|
|
462
|
-
fastapi: {
|
|
463
|
-
title: "FastAPI Conventions",
|
|
464
|
-
content: [
|
|
465
|
-
"- Entry point at `src/main.py` with FastAPI app instance",
|
|
466
|
-
"- Use Pydantic models for request/response validation",
|
|
467
|
-
"- Async endpoints preferred; sync is acceptable for CPU-bound work",
|
|
468
|
-
"- Run with `uvicorn src.main:app --reload` for development",
|
|
469
|
-
"- Tests use pytest (`pytest`)"
|
|
470
|
-
].join("\n")
|
|
471
|
-
},
|
|
472
|
-
django: {
|
|
473
|
-
title: "Django Conventions",
|
|
474
|
-
content: [
|
|
475
|
-
"- Settings at `src/settings.py`, URLs at `src/urls.py`",
|
|
476
|
-
"- Use `manage.py` for management commands",
|
|
477
|
-
"- Apps in `src/` directory; each app has models, views, urls",
|
|
478
|
-
"- Run with `python manage.py runserver` for development",
|
|
479
|
-
"- Tests use pytest with pytest-django (`pytest`)"
|
|
480
|
-
].join("\n")
|
|
481
|
-
},
|
|
482
|
-
gin: {
|
|
483
|
-
title: "Gin Conventions",
|
|
484
|
-
content: [
|
|
485
|
-
"- Entry point at `main.go` with Gin router setup",
|
|
486
|
-
"- Group routes by feature using `router.Group()`",
|
|
487
|
-
"- Use middleware for logging, auth, error recovery",
|
|
488
|
-
"- Run with `go run main.go` for development",
|
|
489
|
-
"- Tests use `go test ./...`"
|
|
490
|
-
].join("\n")
|
|
491
|
-
},
|
|
492
|
-
axum: {
|
|
493
|
-
title: "Axum Conventions",
|
|
494
|
-
content: [
|
|
495
|
-
"- Entry point at `src/main.rs` with Axum router",
|
|
496
|
-
"- Use extractors for request parsing (`Path`, `Query`, `Json`)",
|
|
497
|
-
"- Shared state via `Extension` or `State`",
|
|
498
|
-
"- Run with `cargo run` for development",
|
|
499
|
-
"- Tests use `cargo test`"
|
|
500
|
-
].join("\n")
|
|
501
|
-
},
|
|
502
|
-
"spring-boot": {
|
|
503
|
-
title: "Spring Boot Conventions",
|
|
504
|
-
content: [
|
|
505
|
-
"- Entry point annotated with `@SpringBootApplication`",
|
|
506
|
-
"- Controllers in `controller/` package, services in `service/`",
|
|
507
|
-
"- Use constructor injection for dependencies",
|
|
508
|
-
"- Run with `mvn spring-boot:run` for development",
|
|
509
|
-
"- Tests use JUnit 5 with Spring Boot Test (`mvn test`)"
|
|
510
|
-
].join("\n")
|
|
511
|
-
}
|
|
512
|
-
};
|
|
513
|
-
function buildFrameworkSection(framework) {
|
|
514
|
-
const entry = FRAMEWORK_SECTIONS[framework];
|
|
515
|
-
if (!entry) return "";
|
|
516
|
-
return `## ${entry.title}
|
|
517
|
-
|
|
518
|
-
<!-- framework: ${framework} -->
|
|
519
|
-
${entry.content}
|
|
520
|
-
`;
|
|
521
|
-
}
|
|
522
|
-
function appendFrameworkSection(existingContent, framework, _language) {
|
|
523
|
-
if (!framework) return existingContent;
|
|
524
|
-
const startMarker = `<!-- harness:framework-conventions:${framework} -->`;
|
|
525
|
-
const endMarker = `<!-- /harness:framework-conventions:${framework} -->`;
|
|
526
|
-
if (existingContent.includes(startMarker)) return existingContent;
|
|
527
|
-
const section = buildFrameworkSection(framework);
|
|
528
|
-
if (!section) return existingContent;
|
|
529
|
-
const block = `
|
|
530
|
-
${startMarker}
|
|
531
|
-
${section}${endMarker}
|
|
532
|
-
`;
|
|
533
|
-
return existingContent.trimEnd() + "\n" + block;
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
// src/templates/post-write.ts
|
|
537
|
-
function persistToolingConfig(targetDir, resolveResult, framework) {
|
|
538
|
-
const configPath = path.join(targetDir, "harness.config.json");
|
|
539
|
-
if (!fs.existsSync(configPath)) return;
|
|
540
|
-
try {
|
|
541
|
-
const config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
|
|
542
|
-
const overlayMeta = resolveResult.overlayMetadata;
|
|
543
|
-
if (framework) {
|
|
544
|
-
config.template = config.template || {};
|
|
545
|
-
config.template.framework = framework;
|
|
546
|
-
}
|
|
547
|
-
if (overlayMeta?.tooling) {
|
|
548
|
-
config.tooling = { ...config.tooling, ...overlayMeta.tooling };
|
|
549
|
-
delete config.tooling.lockFile;
|
|
550
|
-
} else if (resolveResult.metadata.tooling && !config.tooling) {
|
|
551
|
-
config.tooling = { ...resolveResult.metadata.tooling };
|
|
552
|
-
delete config.tooling.lockFile;
|
|
553
|
-
}
|
|
554
|
-
if (config.template?.level === null || config.template?.level === void 0) {
|
|
555
|
-
delete config.template.level;
|
|
556
|
-
}
|
|
557
|
-
fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
|
|
558
|
-
} catch {
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
function ensureHarnessGitignore(targetDir) {
|
|
562
|
-
const gitignorePath = path.join(targetDir, ".harness", ".gitignore");
|
|
563
|
-
if (fs.existsSync(gitignorePath)) return;
|
|
564
|
-
const content = `# Runtime artifacts (generated, ephemeral, session-scoped)
|
|
565
|
-
graph/
|
|
566
|
-
debug/
|
|
567
|
-
hooks/
|
|
568
|
-
security/
|
|
569
|
-
sessions/
|
|
570
|
-
state.json
|
|
571
|
-
state/
|
|
572
|
-
handoff.json
|
|
573
|
-
handoff-*.json
|
|
574
|
-
autopilot-state.json
|
|
575
|
-
session-taint-*.json
|
|
576
|
-
dispatch-last-head.txt
|
|
577
|
-
health-snapshot.json
|
|
578
|
-
release-readiness.json
|
|
579
|
-
skills-index.json
|
|
580
|
-
stack-profile.json
|
|
581
|
-
metrics/
|
|
582
|
-
events.jsonl
|
|
583
|
-
.install-id
|
|
584
|
-
telemetry.json
|
|
585
|
-
.telemetry-notice-shown
|
|
586
|
-
`;
|
|
587
|
-
fs.mkdirSync(path.dirname(gitignorePath), { recursive: true });
|
|
588
|
-
fs.writeFileSync(gitignorePath, content);
|
|
589
|
-
}
|
|
590
|
-
function appendFrameworkAgents(targetDir, framework, language) {
|
|
591
|
-
if (!framework) return;
|
|
592
|
-
const agentsPath = path.join(targetDir, "AGENTS.md");
|
|
593
|
-
if (!fs.existsSync(agentsPath)) return;
|
|
594
|
-
try {
|
|
595
|
-
const existing = fs.readFileSync(agentsPath, "utf-8");
|
|
596
|
-
const updated = appendFrameworkSection(existing, framework, language);
|
|
597
|
-
if (updated !== existing) {
|
|
598
|
-
fs.writeFileSync(agentsPath, updated);
|
|
599
|
-
}
|
|
600
|
-
} catch {
|
|
601
|
-
}
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
// src/mcp/tools/init.ts
|
|
605
605
|
var initProjectDefinition = {
|
|
606
606
|
name: "init_project",
|
|
607
607
|
description: "Scaffold a new harness engineering project from a template",
|
|
@@ -7514,6 +7514,7 @@ async function handleReadResource(uri, resolvedRoot) {
|
|
|
7514
7514
|
}
|
|
7515
7515
|
function createHarnessServer(projectRoot, toolFilter) {
|
|
7516
7516
|
const resolvedRoot = projectRoot ?? process.cwd();
|
|
7517
|
+
ensureHarnessGitignore(resolvedRoot);
|
|
7517
7518
|
const { definitions, handlers } = buildFilteredTools(toolFilter);
|
|
7518
7519
|
const trustedOutputTools = new Set(
|
|
7519
7520
|
definitions.filter((t) => t.trustedOutput === true).map((t) => t.name)
|
package/dist/index.js
CHANGED
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
runSnapshotCapture,
|
|
13
13
|
runUninstall,
|
|
14
14
|
runUninstallConstraints
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-2KZAXESR.js";
|
|
16
16
|
import {
|
|
17
17
|
generateAgentsMd
|
|
18
18
|
} from "./chunk-5BQ5BOJL.js";
|
|
@@ -66,7 +66,7 @@ import {
|
|
|
66
66
|
generateSlashCommands,
|
|
67
67
|
getToolDefinitions,
|
|
68
68
|
startServer
|
|
69
|
-
} from "./chunk-
|
|
69
|
+
} from "./chunk-BUYW3SA2.js";
|
|
70
70
|
import "./chunk-FES2YEQU.js";
|
|
71
71
|
import "./chunk-UV3BZMGT.js";
|
|
72
72
|
import "./chunk-F23H3U5U.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@harness-engineering/cli",
|
|
3
|
-
"version": "1.25.
|
|
3
|
+
"version": "1.25.4",
|
|
4
4
|
"description": "CLI for Harness Engineering toolkit",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -37,12 +37,12 @@
|
|
|
37
37
|
"web-tree-sitter": "^0.24.7",
|
|
38
38
|
"yaml": "^2.8.3",
|
|
39
39
|
"zod": "^3.25.76",
|
|
40
|
-
"@harness-engineering/core": "0.22.0",
|
|
41
|
-
"@harness-engineering/dashboard": "0.1.5",
|
|
42
40
|
"@harness-engineering/graph": "0.4.3",
|
|
41
|
+
"@harness-engineering/orchestrator": "0.2.10",
|
|
42
|
+
"@harness-engineering/types": "0.9.2",
|
|
43
|
+
"@harness-engineering/dashboard": "0.1.6",
|
|
43
44
|
"@harness-engineering/linter-gen": "0.1.6",
|
|
44
|
-
"@harness-engineering/
|
|
45
|
-
"@harness-engineering/types": "0.9.2"
|
|
45
|
+
"@harness-engineering/core": "0.22.0"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@types/node": "^22.19.15",
|
|
File without changes
|