@entelligentsia/forgecli 1.0.10 → 1.0.14
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 +49 -0
- package/dist/CHANGELOG-forge-plugin.md +150 -0
- package/dist/bin/forge.js +0 -0
- package/dist/extensions/forgecli/config-layer.d.ts +16 -0
- package/dist/extensions/forgecli/config-layer.js +5 -0
- package/dist/extensions/forgecli/config-layer.js.map +1 -1
- package/dist/extensions/forgecli/dashboard/component.d.ts +102 -0
- package/dist/extensions/forgecli/dashboard/component.js +882 -0
- package/dist/extensions/forgecli/dashboard/component.js.map +1 -0
- package/dist/extensions/forgecli/dashboard/register.d.ts +2 -0
- package/dist/extensions/forgecli/dashboard/register.js +45 -0
- package/dist/extensions/forgecli/dashboard/register.js.map +1 -0
- package/dist/extensions/forgecli/dashboard/view-model.d.ts +35 -0
- package/dist/extensions/forgecli/dashboard/view-model.js +54 -0
- package/dist/extensions/forgecli/dashboard/view-model.js.map +1 -0
- package/dist/extensions/forgecli/fix-bug.js +72 -7
- package/dist/extensions/forgecli/fix-bug.js.map +1 -1
- package/dist/extensions/forgecli/forge-cli-schema.json +4 -0
- package/dist/extensions/forgecli/forge-commands.js +1 -0
- package/dist/extensions/forgecli/forge-commands.js.map +1 -1
- package/dist/extensions/forgecli/forge-init/phase4-register.js +53 -0
- package/dist/extensions/forgecli/forge-init/phase4-register.js.map +1 -1
- package/dist/extensions/forgecli/forge-subagent.js +6 -4
- package/dist/extensions/forgecli/forge-subagent.js.map +1 -1
- package/dist/extensions/forgecli/index.js +5 -0
- package/dist/extensions/forgecli/index.js.map +1 -1
- package/dist/extensions/forgecli/lib/halt-advisor.d.ts +54 -0
- package/dist/extensions/forgecli/lib/halt-advisor.js +90 -0
- package/dist/extensions/forgecli/lib/halt-advisor.js.map +1 -0
- package/dist/extensions/forgecli/migration-engine.js +25 -12
- package/dist/extensions/forgecli/migration-engine.js.map +1 -1
- package/dist/extensions/forgecli/orchestrator-status-bar.d.ts +25 -0
- package/dist/extensions/forgecli/orchestrator-status-bar.js +183 -0
- package/dist/extensions/forgecli/orchestrator-status-bar.js.map +1 -0
- package/dist/extensions/forgecli/orchestrator-tree.d.ts +96 -0
- package/dist/extensions/forgecli/orchestrator-tree.js +390 -0
- package/dist/extensions/forgecli/orchestrator-tree.js.map +1 -0
- package/dist/extensions/forgecli/project-orientation.js +12 -8
- package/dist/extensions/forgecli/project-orientation.js.map +1 -1
- package/dist/extensions/forgecli/regenerate.d.ts +16 -0
- package/dist/extensions/forgecli/regenerate.js +110 -0
- package/dist/extensions/forgecli/regenerate.js.map +1 -1
- package/dist/extensions/forgecli/run-sprint.js +33 -3
- package/dist/extensions/forgecli/run-sprint.js.map +1 -1
- package/dist/extensions/forgecli/run-task.d.ts +32 -0
- package/dist/extensions/forgecli/run-task.js +185 -12
- package/dist/extensions/forgecli/run-task.js.map +1 -1
- package/dist/extensions/forgecli/thread-switcher.js +105 -764
- package/dist/extensions/forgecli/thread-switcher.js.map +1 -1
- package/dist/extensions/forgecli/viewport-events.js +32 -0
- package/dist/extensions/forgecli/viewport-events.js.map +1 -1
- package/dist/forge-payload/.base-pack/commands/fix-bug.md +1 -1
- package/dist/forge-payload/.base-pack/commands/run-sprint.md +1 -1
- package/dist/forge-payload/.base-pack/commands/run-task.md +1 -1
- package/dist/forge-payload/.base-pack/personas/architect.md +1 -1
- package/dist/forge-payload/.base-pack/personas/bug-fixer.md +1 -1
- package/dist/forge-payload/.base-pack/personas/collator.md +3 -3
- package/dist/forge-payload/.base-pack/personas/engineer.md +1 -1
- package/dist/forge-payload/.base-pack/personas/librarian.md +1 -1
- package/dist/forge-payload/.base-pack/personas/orchestrator.md +1 -1
- package/dist/forge-payload/.base-pack/personas/product-manager.md +1 -1
- package/dist/forge-payload/.base-pack/personas/qa-engineer.md +1 -1
- package/dist/forge-payload/.base-pack/personas/supervisor.md +1 -1
- package/dist/forge-payload/.base-pack/workflows/_fragments/event-emission-schema.md +1 -1
- package/dist/forge-payload/.base-pack/workflows/_fragments/friction-emit.md +1 -1
- package/dist/forge-payload/.base-pack/workflows/_fragments/iron-laws.md +1 -1
- package/dist/forge-payload/.base-pack/workflows/_fragments/progress-reporting.md +2 -2
- package/dist/forge-payload/.base-pack/workflows/_fragments/store-cli-verbs.md +11 -2
- package/dist/forge-payload/.base-pack/workflows/architect_approve.md +6 -7
- package/dist/forge-payload/.base-pack/workflows/architect_review_sprint_completion.md +2 -2
- package/dist/forge-payload/.base-pack/workflows/architect_sprint_intake.md +2 -2
- package/dist/forge-payload/.base-pack/workflows/architect_sprint_plan.md +5 -5
- package/dist/forge-payload/.base-pack/workflows/collator_agent.md +4 -6
- package/dist/forge-payload/.base-pack/workflows/commit_task.md +5 -6
- package/dist/forge-payload/.base-pack/workflows/enhance.md +5 -5
- package/dist/forge-payload/.base-pack/workflows/implement_plan.md +6 -7
- package/dist/forge-payload/.base-pack/workflows/migrate_structural.md +12 -13
- package/dist/forge-payload/.base-pack/workflows/plan_task.md +5 -6
- package/dist/forge-payload/.base-pack/workflows/review_code.md +8 -8
- package/dist/forge-payload/.base-pack/workflows/review_plan.md +8 -8
- package/dist/forge-payload/.base-pack/workflows/sprint_retrospective.md +3 -3
- package/dist/forge-payload/.base-pack/workflows/triage.md +12 -9
- package/dist/forge-payload/.base-pack/workflows/update_implementation.md +2 -2
- package/dist/forge-payload/.base-pack/workflows/update_plan.md +2 -2
- package/dist/forge-payload/.base-pack/workflows/validate_task.md +5 -6
- package/dist/forge-payload/.base-pack/workflows-js/wfl-fix-bug.js +490 -0
- package/dist/forge-payload/.base-pack/workflows-js/wfl-run-sprint.js +416 -0
- package/dist/forge-payload/.base-pack/workflows-js/wfl-run-task.js +608 -0
- package/dist/forge-payload/.claude-plugin/plugin.json +1 -1
- package/dist/forge-payload/.schemas/config.schema.json +2 -3
- package/dist/forge-payload/.schemas/enum-catalog.json +2 -2
- package/dist/forge-payload/.schemas/event.schema.json +16 -0
- package/dist/forge-payload/.schemas/migrations.json +236 -0
- package/dist/forge-payload/commands/health.md +29 -0
- package/dist/forge-payload/commands/rebuild.md +143 -15
- package/dist/forge-payload/commands/update.md +28 -27
- package/dist/forge-payload/hooks/preflight-session.cjs +99 -0
- package/dist/forge-payload/init/phases/phase-3-materialize.md +18 -5
- package/dist/forge-payload/integrity.json +7 -6
- package/dist/forge-payload/meta/fragments/tool-discipline.md +1 -1
- package/dist/forge-payload/meta/personas/meta-architect.md +1 -1
- package/dist/forge-payload/meta/personas/meta-bug-fixer.md +1 -1
- package/dist/forge-payload/meta/personas/meta-collator.md +7 -7
- package/dist/forge-payload/meta/personas/meta-engineer.md +1 -1
- package/dist/forge-payload/meta/personas/meta-orchestrator.md +1 -1
- package/dist/forge-payload/meta/personas/meta-supervisor.md +1 -1
- package/dist/forge-payload/meta/tool-specs/store-cli.spec.md +1 -1
- package/dist/forge-payload/meta/workflows/_fragments/event-emission-schema.md +1 -1
- package/dist/forge-payload/meta/workflows/_fragments/friction-emit.md +1 -1
- package/dist/forge-payload/meta/workflows/_fragments/iron-laws.md +1 -1
- package/dist/forge-payload/meta/workflows/_fragments/progress-reporting.md +2 -2
- package/dist/forge-payload/meta/workflows/_fragments/store-cli-verbs.md +11 -2
- package/dist/forge-payload/meta/workflows/meta-approve.md +6 -7
- package/dist/forge-payload/meta/workflows/meta-bug-triage.md +12 -9
- package/dist/forge-payload/meta/workflows/meta-collate.md +5 -7
- package/dist/forge-payload/meta/workflows/meta-commit.md +5 -6
- package/dist/forge-payload/meta/workflows/meta-enhance.md +5 -5
- package/dist/forge-payload/meta/workflows/meta-fix-bug.md +35 -11
- package/dist/forge-payload/meta/workflows/meta-implement.md +15 -7
- package/dist/forge-payload/meta/workflows/meta-migrate.md +13 -14
- package/dist/forge-payload/meta/workflows/meta-new-sprint.md +3 -3
- package/dist/forge-payload/meta/workflows/meta-orchestrate.md +138 -39
- package/dist/forge-payload/meta/workflows/meta-plan-sprint.md +6 -6
- package/dist/forge-payload/meta/workflows/meta-plan-task.md +12 -6
- package/dist/forge-payload/meta/workflows/meta-retro.md +4 -4
- package/dist/forge-payload/meta/workflows/meta-retrospective.md +4 -4
- package/dist/forge-payload/meta/workflows/meta-review-implementation.md +8 -8
- package/dist/forge-payload/meta/workflows/meta-review-plan.md +8 -8
- package/dist/forge-payload/meta/workflows/meta-review-sprint-completion.md +3 -3
- package/dist/forge-payload/meta/workflows/meta-sprint-intake.md +3 -3
- package/dist/forge-payload/meta/workflows/meta-sprint-plan.md +6 -6
- package/dist/forge-payload/meta/workflows/meta-update-implementation.md +2 -2
- package/dist/forge-payload/meta/workflows/meta-update-plan.md +2 -2
- package/dist/forge-payload/meta/workflows/meta-validate.md +5 -6
- package/dist/forge-payload/schemas/config.schema.json +2 -3
- package/dist/forge-payload/schemas/enum-catalog.json +2 -2
- package/dist/forge-payload/schemas/event.schema.json +16 -0
- package/dist/forge-payload/schemas/structure-manifest.json +75 -73
- package/dist/forge-payload/skills/refresh-kb-links/SKILL.md +14 -7
- package/dist/forge-payload/tools/banners.cjs +29 -10
- package/dist/forge-payload/tools/check-structure.cjs +88 -7
- package/dist/forge-payload/tools/collate.cjs +16 -2
- package/dist/forge-payload/tools/manage-config.cjs +5 -7
- package/dist/forge-payload/tools/parse-gates.cjs +73 -1
- package/dist/forge-payload/tools/postflight-gate.cjs +252 -0
- package/dist/forge-payload/tools/preflight-gate.cjs +47 -0
- package/dist/forge-payload/tools/substitute-placeholders.cjs +5 -4
- package/dist/forge-payload/tools/verify-phase.cjs +17 -0
- package/package.json +1 -1
- package/dist/bin/forgecli.d.ts +0 -2
- package/dist/bin/forgecli.js +0 -6
- package/dist/bin/forgecli.js.map +0 -1
- package/dist/extensions/forgecli/config-tui/index.d.ts +0 -5
- package/dist/extensions/forgecli/config-tui/index.js +0 -5
- package/dist/extensions/forgecli/config-tui/index.js.map +0 -1
- package/dist/extensions/forgecli/loaders/persona-skill-loader.d.ts +0 -45
- package/dist/extensions/forgecli/loaders/persona-skill-loader.js +0 -227
- package/dist/extensions/forgecli/loaders/persona-skill-loader.js.map +0 -1
- package/dist/extensions/forgecli/loaders/template-render.d.ts +0 -20
- package/dist/extensions/forgecli/loaders/template-render.js +0 -85
- package/dist/extensions/forgecli/loaders/template-render.js.map +0 -1
- package/dist/extensions/forgecli/loaders/workflow-loader.d.ts +0 -41
- package/dist/extensions/forgecli/loaders/workflow-loader.js +0 -164
- package/dist/extensions/forgecli/loaders/workflow-loader.js.map +0 -1
- package/dist/forge-payload/.base-pack/workflows/fix_bug.md +0 -446
- package/dist/forge-payload/.base-pack/workflows/orchestrate_task.md +0 -928
- package/dist/forge-payload/.base-pack/workflows/run_sprint.md +0 -225
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { type Static, Type } from "typebox";
|
|
2
|
-
export declare const PersonaSchema: Type.TObject<{
|
|
3
|
-
name: Type.TString;
|
|
4
|
-
filePath: Type.TString;
|
|
5
|
-
identity: Type.TString;
|
|
6
|
-
body: Type.TString;
|
|
7
|
-
capabilities: Type.TArray<Type.TString>;
|
|
8
|
-
frontmatter: Type.TRecord<"^.*$", Type.TUnknown>;
|
|
9
|
-
}>;
|
|
10
|
-
export type Persona = Static<typeof PersonaSchema>;
|
|
11
|
-
export declare const SkillSchema: Type.TObject<{
|
|
12
|
-
name: Type.TString;
|
|
13
|
-
filePath: Type.TString;
|
|
14
|
-
body: Type.TString;
|
|
15
|
-
capabilities: Type.TArray<Type.TString>;
|
|
16
|
-
frontmatter: Type.TRecord<"^.*$", Type.TUnknown>;
|
|
17
|
-
}>;
|
|
18
|
-
export type Skill = Static<typeof SkillSchema>;
|
|
19
|
-
export type PersonaSkillLoaderErrorCode = "missing_file" | "invalid_frontmatter" | "path_traversal" | "no_project_root" | "validation_failed";
|
|
20
|
-
export declare class PersonaSkillLoaderError extends Error {
|
|
21
|
-
readonly code: PersonaSkillLoaderErrorCode;
|
|
22
|
-
constructor(code: PersonaSkillLoaderErrorCode, message: string);
|
|
23
|
-
}
|
|
24
|
-
export interface LoaderOptions {
|
|
25
|
-
/** Override project root (the directory containing `.forge/`). */
|
|
26
|
-
projectRoot?: string;
|
|
27
|
-
/** cwd to start `.forge/config.json` discovery from. Defaults to `process.cwd()`. */
|
|
28
|
-
cwd?: string;
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Load a Persona record from `<projectRoot>/.forge/personas/<name>.md`.
|
|
32
|
-
*
|
|
33
|
-
* `name` is the filename stem (e.g. `"engineer"` for `engineer.md`). It must
|
|
34
|
-
* not contain path separators or traversal segments — invalid names raise
|
|
35
|
-
* `PersonaSkillLoaderError` with `code: "path_traversal"`.
|
|
36
|
-
*/
|
|
37
|
-
export declare function loadPersona(name: string, opts?: LoaderOptions): Persona;
|
|
38
|
-
/**
|
|
39
|
-
* Load a Skill record from `<projectRoot>/.forge/skills/<name>.md`.
|
|
40
|
-
*
|
|
41
|
-
* `name` is the filename stem. The Forge convention names skill files
|
|
42
|
-
* `<noun>-skills.md` (e.g. `engineer-skills.md`); callers pass the full stem
|
|
43
|
-
* including the `-skills` suffix. The loader does not auto-append it.
|
|
44
|
-
*/
|
|
45
|
-
export declare function loadSkill(name: string, opts?: LoaderOptions): Skill;
|
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
// Central persona/skill loader — FORGE-S20-T02.
|
|
2
|
-
//
|
|
3
|
-
// Single canonical surface for reading persona and skill markdown files from
|
|
4
|
-
// the user's `.forge/personas/` and `.forge/skills/` directories. Future
|
|
5
|
-
// kickoff handlers (T04 /forge:enhance, T05 /forge:plan, T06 /forge:implement)
|
|
6
|
-
// load typed Persona/Skill records through this module instead of issuing
|
|
7
|
-
// ad-hoc fs.readFile calls. The smoke gate locks the invariant in place.
|
|
8
|
-
//
|
|
9
|
-
// Path resolution anchors at the **project root** containing `.forge/`, not
|
|
10
|
-
// at `forgeRoot` (which points at the bundled plugin source — `.forge/personas/`
|
|
11
|
-
// is a project-local generated directory).
|
|
12
|
-
//
|
|
13
|
-
// Iron Law 6 (no shell-string interpolation): all I/O is via fs synchronous
|
|
14
|
-
// APIs with absolute paths constructed by `path.join`/`path.resolve`. No
|
|
15
|
-
// external process invocation.
|
|
16
|
-
// Iron Law 7 (no silent continuation): every failure mode raises a typed
|
|
17
|
-
// `PersonaSkillLoaderError` with an explicit `code`.
|
|
18
|
-
import * as fs from "node:fs";
|
|
19
|
-
import * as path from "node:path";
|
|
20
|
-
import { Type } from "typebox";
|
|
21
|
-
import { Value } from "typebox/value";
|
|
22
|
-
import { discoverForgeConfig } from "../forge-root.js";
|
|
23
|
-
// ── TypeBox schemas ──────────────────────────────────────────────────────
|
|
24
|
-
export const PersonaSchema = Type.Object({
|
|
25
|
-
name: Type.String(),
|
|
26
|
-
filePath: Type.String(),
|
|
27
|
-
identity: Type.String(),
|
|
28
|
-
body: Type.String(),
|
|
29
|
-
capabilities: Type.Array(Type.String()),
|
|
30
|
-
frontmatter: Type.Record(Type.String(), Type.Unknown()),
|
|
31
|
-
});
|
|
32
|
-
export const SkillSchema = Type.Object({
|
|
33
|
-
name: Type.String(),
|
|
34
|
-
filePath: Type.String(),
|
|
35
|
-
body: Type.String(),
|
|
36
|
-
capabilities: Type.Array(Type.String()),
|
|
37
|
-
frontmatter: Type.Record(Type.String(), Type.Unknown()),
|
|
38
|
-
});
|
|
39
|
-
export class PersonaSkillLoaderError extends Error {
|
|
40
|
-
code;
|
|
41
|
-
constructor(code, message) {
|
|
42
|
-
super(message);
|
|
43
|
-
this.name = "PersonaSkillLoaderError";
|
|
44
|
-
this.code = code;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
// ── Project-root discovery ───────────────────────────────────────────────
|
|
48
|
-
function resolveProjectRoot(opts) {
|
|
49
|
-
if (opts?.projectRoot)
|
|
50
|
-
return opts.projectRoot;
|
|
51
|
-
const cwd = opts?.cwd ?? process.cwd();
|
|
52
|
-
const cfg = discoverForgeConfig(cwd);
|
|
53
|
-
if (!cfg) {
|
|
54
|
-
throw new PersonaSkillLoaderError("no_project_root", `No .forge/config.json found walking up from ${cwd}. ` +
|
|
55
|
-
"Run /forge:init to scaffold the project, or pass `projectRoot` explicitly.");
|
|
56
|
-
}
|
|
57
|
-
// configPath = <projectDir>/.forge/config.json → projectDir = parent of .forge/
|
|
58
|
-
return path.dirname(path.dirname(cfg.configPath));
|
|
59
|
-
}
|
|
60
|
-
// ── Name validation (defence in depth) ───────────────────────────────────
|
|
61
|
-
function validateName(name, kind) {
|
|
62
|
-
if (typeof name !== "string" || name.length === 0) {
|
|
63
|
-
throw new PersonaSkillLoaderError("path_traversal", `${kind} name must be a non-empty string`);
|
|
64
|
-
}
|
|
65
|
-
if (name.includes("/") || name.includes("\\") || name.includes("\0")) {
|
|
66
|
-
throw new PersonaSkillLoaderError("path_traversal", `${kind} name contains path separators: ${JSON.stringify(name)}`);
|
|
67
|
-
}
|
|
68
|
-
const parts = name.split(/[/\\]/);
|
|
69
|
-
for (const p of parts) {
|
|
70
|
-
if (p === ".." || p === "." || p === "") {
|
|
71
|
-
throw new PersonaSkillLoaderError("path_traversal", `${kind} name contains traversal segment: ${JSON.stringify(name)}`);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
// ── Realpath confinement check ───────────────────────────────────────────
|
|
76
|
-
function assertWithinDir(realFile, realDir, kind) {
|
|
77
|
-
const prefix = realDir.endsWith(path.sep) ? realDir : realDir + path.sep;
|
|
78
|
-
if (!realFile.startsWith(prefix)) {
|
|
79
|
-
throw new PersonaSkillLoaderError("path_traversal", `${kind} path escapes ${realDir}: resolved to ${realFile}`);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
function parseFrontmatter(content) {
|
|
83
|
-
// Normalise CRLF for line-based parsing while preserving body intact below.
|
|
84
|
-
const lines = content.split(/\r?\n/);
|
|
85
|
-
if (lines.length === 0 || lines[0] !== "---") {
|
|
86
|
-
return { frontmatter: {}, body: content };
|
|
87
|
-
}
|
|
88
|
-
const fm = {};
|
|
89
|
-
let i = 1;
|
|
90
|
-
let closed = false;
|
|
91
|
-
for (; i < lines.length; i++) {
|
|
92
|
-
const line = lines[i];
|
|
93
|
-
if (line === "---") {
|
|
94
|
-
closed = true;
|
|
95
|
-
i++;
|
|
96
|
-
break;
|
|
97
|
-
}
|
|
98
|
-
// Allow blank lines inside frontmatter.
|
|
99
|
-
if (line.trim() === "")
|
|
100
|
-
continue;
|
|
101
|
-
const m = /^([A-Za-z0-9_.-]+):\s*(.*)$/.exec(line);
|
|
102
|
-
if (!m) {
|
|
103
|
-
throw new PersonaSkillLoaderError("invalid_frontmatter", `Malformed frontmatter line ${i + 1}: ${JSON.stringify(line)}`);
|
|
104
|
-
}
|
|
105
|
-
const value = m[2].trim();
|
|
106
|
-
// Strip matching surrounding quotes if present.
|
|
107
|
-
let parsed = value;
|
|
108
|
-
if ((value.startsWith('"') && value.endsWith('"') && value.length >= 2) ||
|
|
109
|
-
(value.startsWith("'") && value.endsWith("'") && value.length >= 2)) {
|
|
110
|
-
parsed = value.slice(1, -1);
|
|
111
|
-
}
|
|
112
|
-
fm[m[1]] = parsed;
|
|
113
|
-
}
|
|
114
|
-
if (!closed) {
|
|
115
|
-
throw new PersonaSkillLoaderError("invalid_frontmatter", "Frontmatter block opened with `---` but never closed");
|
|
116
|
-
}
|
|
117
|
-
const body = lines.slice(i).join("\n");
|
|
118
|
-
return { frontmatter: fm, body };
|
|
119
|
-
}
|
|
120
|
-
// ── Capability + identity extraction ─────────────────────────────────────
|
|
121
|
-
function extractCapabilities(body) {
|
|
122
|
-
const lines = body.split(/\r?\n/);
|
|
123
|
-
const heading = /^##\s+Capabilities\s*$/;
|
|
124
|
-
const nextSection = /^##\s+\S/;
|
|
125
|
-
const bullet = /^[-*]\s+(.+)$/;
|
|
126
|
-
const out = [];
|
|
127
|
-
let inSection = false;
|
|
128
|
-
for (const line of lines) {
|
|
129
|
-
if (!inSection) {
|
|
130
|
-
if (heading.test(line))
|
|
131
|
-
inSection = true;
|
|
132
|
-
continue;
|
|
133
|
-
}
|
|
134
|
-
if (nextSection.test(line))
|
|
135
|
-
break;
|
|
136
|
-
const m = bullet.exec(line);
|
|
137
|
-
if (m)
|
|
138
|
-
out.push(m[1].trim());
|
|
139
|
-
}
|
|
140
|
-
return out;
|
|
141
|
-
}
|
|
142
|
-
function extractIdentity(body) {
|
|
143
|
-
for (const line of body.split(/\r?\n/)) {
|
|
144
|
-
if (line.trim().length > 0)
|
|
145
|
-
return line.trim();
|
|
146
|
-
}
|
|
147
|
-
return "";
|
|
148
|
-
}
|
|
149
|
-
// ── Internal generic load ────────────────────────────────────────────────
|
|
150
|
-
function loadFile(kind, subdir, name, opts) {
|
|
151
|
-
validateName(name, kind);
|
|
152
|
-
const projectRoot = resolveProjectRoot(opts);
|
|
153
|
-
const baseDir = path.join(projectRoot, ".forge", subdir);
|
|
154
|
-
const candidate = path.join(baseDir, `${name}.md`);
|
|
155
|
-
// Realpath the *directory* first — it must exist for confinement check.
|
|
156
|
-
let realDir;
|
|
157
|
-
try {
|
|
158
|
-
realDir = fs.realpathSync(baseDir);
|
|
159
|
-
}
|
|
160
|
-
catch {
|
|
161
|
-
throw new PersonaSkillLoaderError("missing_file", `${kind} directory does not exist: ${baseDir}`);
|
|
162
|
-
}
|
|
163
|
-
let realFile;
|
|
164
|
-
try {
|
|
165
|
-
realFile = fs.realpathSync(candidate);
|
|
166
|
-
}
|
|
167
|
-
catch {
|
|
168
|
-
throw new PersonaSkillLoaderError("missing_file", `${kind} file not found: ${candidate}`);
|
|
169
|
-
}
|
|
170
|
-
assertWithinDir(realFile, realDir, kind);
|
|
171
|
-
let raw;
|
|
172
|
-
try {
|
|
173
|
-
raw = fs.readFileSync(realFile, "utf8");
|
|
174
|
-
}
|
|
175
|
-
catch (err) {
|
|
176
|
-
const e = err;
|
|
177
|
-
throw new PersonaSkillLoaderError("missing_file", `Failed to read ${kind} file ${realFile}: ${e.message ?? "unknown"}`);
|
|
178
|
-
}
|
|
179
|
-
return { filePath: realFile, doc: parseFrontmatter(raw) };
|
|
180
|
-
}
|
|
181
|
-
// ── Public API ───────────────────────────────────────────────────────────
|
|
182
|
-
/**
|
|
183
|
-
* Load a Persona record from `<projectRoot>/.forge/personas/<name>.md`.
|
|
184
|
-
*
|
|
185
|
-
* `name` is the filename stem (e.g. `"engineer"` for `engineer.md`). It must
|
|
186
|
-
* not contain path separators or traversal segments — invalid names raise
|
|
187
|
-
* `PersonaSkillLoaderError` with `code: "path_traversal"`.
|
|
188
|
-
*/
|
|
189
|
-
export function loadPersona(name, opts) {
|
|
190
|
-
const { filePath, doc } = loadFile("persona", "personas", name, opts);
|
|
191
|
-
const persona = {
|
|
192
|
-
name,
|
|
193
|
-
filePath,
|
|
194
|
-
identity: extractIdentity(doc.body),
|
|
195
|
-
body: doc.body,
|
|
196
|
-
capabilities: extractCapabilities(doc.body),
|
|
197
|
-
frontmatter: doc.frontmatter,
|
|
198
|
-
};
|
|
199
|
-
if (!Value.Check(PersonaSchema, persona)) {
|
|
200
|
-
const errs = [...Value.Errors(PersonaSchema, persona)].map((e) => e.message);
|
|
201
|
-
throw new PersonaSkillLoaderError("validation_failed", `Persona ${name} failed schema validation: ${errs.join("; ")}`);
|
|
202
|
-
}
|
|
203
|
-
return persona;
|
|
204
|
-
}
|
|
205
|
-
/**
|
|
206
|
-
* Load a Skill record from `<projectRoot>/.forge/skills/<name>.md`.
|
|
207
|
-
*
|
|
208
|
-
* `name` is the filename stem. The Forge convention names skill files
|
|
209
|
-
* `<noun>-skills.md` (e.g. `engineer-skills.md`); callers pass the full stem
|
|
210
|
-
* including the `-skills` suffix. The loader does not auto-append it.
|
|
211
|
-
*/
|
|
212
|
-
export function loadSkill(name, opts) {
|
|
213
|
-
const { filePath, doc } = loadFile("skill", "skills", name, opts);
|
|
214
|
-
const skill = {
|
|
215
|
-
name,
|
|
216
|
-
filePath,
|
|
217
|
-
body: doc.body,
|
|
218
|
-
capabilities: extractCapabilities(doc.body),
|
|
219
|
-
frontmatter: doc.frontmatter,
|
|
220
|
-
};
|
|
221
|
-
if (!Value.Check(SkillSchema, skill)) {
|
|
222
|
-
const errs = [...Value.Errors(SkillSchema, skill)].map((e) => e.message);
|
|
223
|
-
throw new PersonaSkillLoaderError("validation_failed", `Skill ${name} failed schema validation: ${errs.join("; ")}`);
|
|
224
|
-
}
|
|
225
|
-
return skill;
|
|
226
|
-
}
|
|
227
|
-
//# sourceMappingURL=persona-skill-loader.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"persona-skill-loader.js","sourceRoot":"","sources":["../../../../src/extensions/forgecli/loaders/persona-skill-loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
export type TemplateRenderErrorCode = "missing_template_file" | "missing_var" | "invalid_args";
|
|
2
|
-
export declare class TemplateRenderError extends Error {
|
|
3
|
-
readonly code: TemplateRenderErrorCode;
|
|
4
|
-
constructor(code: TemplateRenderErrorCode, message: string);
|
|
5
|
-
}
|
|
6
|
-
/**
|
|
7
|
-
* Render a template file by substituting `{NAME}` tokens with values from `vars`.
|
|
8
|
-
*
|
|
9
|
-
* @param templatePath Absolute or cwd-relative path to a UTF-8 template file.
|
|
10
|
-
* @param vars Map from identifier name to substitution value (string).
|
|
11
|
-
* @returns The rendered template as a string.
|
|
12
|
-
*
|
|
13
|
-
* @throws TemplateRenderError({ code: "missing_template_file" }) if the file
|
|
14
|
-
* does not exist or cannot be read.
|
|
15
|
-
* @throws TemplateRenderError({ code: "missing_var" }) if the template
|
|
16
|
-
* references a token whose name is not a key in `vars`.
|
|
17
|
-
* @throws TemplateRenderError({ code: "invalid_args" }) if `templatePath` is
|
|
18
|
-
* not a non-empty string or any value in `vars` is not a string.
|
|
19
|
-
*/
|
|
20
|
-
export declare function renderTemplate(templatePath: string, vars: Record<string, string>): string;
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
// Shared template-render helper — FORGE-S20-T03.
|
|
2
|
-
//
|
|
3
|
-
// Tiny, dependency-free `{NAME}` substitution helper used by kickoff-message
|
|
4
|
-
// composition in forge-cli command handlers (T05 /forge:plan, T06
|
|
5
|
-
// /forge:implement, and any future kickoff shim that needs argv-driven seed
|
|
6
|
-
// substitution).
|
|
7
|
-
//
|
|
8
|
-
// API:
|
|
9
|
-
// renderTemplate(templatePath: string, vars: Record<string, string>): string
|
|
10
|
-
//
|
|
11
|
-
// Substitution rule (frozen):
|
|
12
|
-
// - Token syntax: `{NAME}` where NAME matches /[A-Za-z_][A-Za-z0-9_]*/.
|
|
13
|
-
// Anything else — `{}`, `{ NAME }`, `{1NAME}`, `{lowercase-dashed}` — is
|
|
14
|
-
// a literal and passes through unchanged.
|
|
15
|
-
// - Missing var (token in template, key absent from `vars`): throws
|
|
16
|
-
// TemplateRenderError("missing_var", ...). Never silently renders "".
|
|
17
|
-
// (Iron Law 7: no silent continuation.)
|
|
18
|
-
// - Extra vars (key in `vars` not referenced in template): ignored.
|
|
19
|
-
// - Values are inserted literally — no HTML/regex escaping. Callers handle
|
|
20
|
-
// downstream sanitisation.
|
|
21
|
-
// - Missing template file: throws TemplateRenderError("missing_template_file", ...).
|
|
22
|
-
//
|
|
23
|
-
// Iron Law 6 (no shell-string interpolation): pure fs.readFileSync, no
|
|
24
|
-
// child_process. Iron Law 7 (no silent continuation): every failure mode
|
|
25
|
-
// raises a typed TemplateRenderError with an explicit code.
|
|
26
|
-
import * as fs from "node:fs";
|
|
27
|
-
export class TemplateRenderError extends Error {
|
|
28
|
-
code;
|
|
29
|
-
constructor(code, message) {
|
|
30
|
-
super(message);
|
|
31
|
-
this.name = "TemplateRenderError";
|
|
32
|
-
this.code = code;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
// ── Token grammar ────────────────────────────────────────────────────────
|
|
36
|
-
//
|
|
37
|
-
// Single regex, global, captures the bare identifier. Anchored on `{` and `}`
|
|
38
|
-
// with no whitespace tolerance — `{ NAME }` is a literal, by design.
|
|
39
|
-
const TOKEN_RE = /\{([A-Za-z_][A-Za-z0-9_]*)\}/g;
|
|
40
|
-
// ── Internal: substitute over an in-memory string ────────────────────────
|
|
41
|
-
function substitute(template, vars) {
|
|
42
|
-
return template.replace(TOKEN_RE, (_match, name) => {
|
|
43
|
-
if (!Object.hasOwn(vars, name)) {
|
|
44
|
-
throw new TemplateRenderError("missing_var", `template references {${name}} but no value was supplied in vars`);
|
|
45
|
-
}
|
|
46
|
-
const value = vars[name];
|
|
47
|
-
if (typeof value !== "string") {
|
|
48
|
-
throw new TemplateRenderError("invalid_args", `vars[${JSON.stringify(name)}] must be a string, got ${typeof value}`);
|
|
49
|
-
}
|
|
50
|
-
return value;
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
// ── Public API ───────────────────────────────────────────────────────────
|
|
54
|
-
/**
|
|
55
|
-
* Render a template file by substituting `{NAME}` tokens with values from `vars`.
|
|
56
|
-
*
|
|
57
|
-
* @param templatePath Absolute or cwd-relative path to a UTF-8 template file.
|
|
58
|
-
* @param vars Map from identifier name to substitution value (string).
|
|
59
|
-
* @returns The rendered template as a string.
|
|
60
|
-
*
|
|
61
|
-
* @throws TemplateRenderError({ code: "missing_template_file" }) if the file
|
|
62
|
-
* does not exist or cannot be read.
|
|
63
|
-
* @throws TemplateRenderError({ code: "missing_var" }) if the template
|
|
64
|
-
* references a token whose name is not a key in `vars`.
|
|
65
|
-
* @throws TemplateRenderError({ code: "invalid_args" }) if `templatePath` is
|
|
66
|
-
* not a non-empty string or any value in `vars` is not a string.
|
|
67
|
-
*/
|
|
68
|
-
export function renderTemplate(templatePath, vars) {
|
|
69
|
-
if (typeof templatePath !== "string" || templatePath.length === 0) {
|
|
70
|
-
throw new TemplateRenderError("invalid_args", "templatePath must be a non-empty string");
|
|
71
|
-
}
|
|
72
|
-
if (vars === null || typeof vars !== "object") {
|
|
73
|
-
throw new TemplateRenderError("invalid_args", "vars must be an object");
|
|
74
|
-
}
|
|
75
|
-
let raw;
|
|
76
|
-
try {
|
|
77
|
-
raw = fs.readFileSync(templatePath, "utf8");
|
|
78
|
-
}
|
|
79
|
-
catch (err) {
|
|
80
|
-
const e = err;
|
|
81
|
-
throw new TemplateRenderError("missing_template_file", `failed to read template at ${templatePath}: ${e.code ?? ""} ${e.message ?? "unknown error"}`.trim());
|
|
82
|
-
}
|
|
83
|
-
return substitute(raw, vars);
|
|
84
|
-
}
|
|
85
|
-
//# sourceMappingURL=template-render.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"template-render.js","sourceRoot":"","sources":["../../../../src/extensions/forgecli/loaders/template-render.ts"],"names":[],"mappings":"AAAA,iDAAiD;AACjD,EAAE;AACF,6EAA6E;AAC7E,kEAAkE;AAClE,4EAA4E;AAC5E,iBAAiB;AACjB,EAAE;AACF,OAAO;AACP,+EAA+E;AAC/E,EAAE;AACF,8BAA8B;AAC9B,0EAA0E;AAC1E,6EAA6E;AAC7E,8CAA8C;AAC9C,sEAAsE;AACtE,0EAA0E;AAC1E,4CAA4C;AAC5C,sEAAsE;AACtE,6EAA6E;AAC7E,+BAA+B;AAC/B,uFAAuF;AACvF,EAAE;AACF,uEAAuE;AACvE,yEAAyE;AACzE,4DAA4D;AAE5D,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAM9B,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAC7B,IAAI,CAA0B;IAC9C,YAAY,IAA6B,EAAE,OAAe;QACzD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;QAClC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IAClB,CAAC;CACD;AAED,4EAA4E;AAC5E,EAAE;AACF,8EAA8E;AAC9E,qEAAqE;AACrE,MAAM,QAAQ,GAAG,+BAA+B,CAAC;AAEjD,4EAA4E;AAE5E,SAAS,UAAU,CAAC,QAAgB,EAAE,IAA4B;IACjE,OAAO,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,IAAY,EAAE,EAAE;QAC1D,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,mBAAmB,CAC5B,aAAa,EACb,wBAAwB,IAAI,qCAAqC,CACjE,CAAC;QACH,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;QACzB,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC/B,MAAM,IAAI,mBAAmB,CAC5B,cAAc,EACd,QAAQ,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,2BAA2B,OAAO,KAAK,EAAE,CACrE,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAC;IACd,CAAC,CAAC,CAAC;AACJ,CAAC;AAED,4EAA4E;AAE5E;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,cAAc,CAAC,YAAoB,EAAE,IAA4B;IAChF,IAAI,OAAO,YAAY,KAAK,QAAQ,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACnE,MAAM,IAAI,mBAAmB,CAAC,cAAc,EAAE,yCAAyC,CAAC,CAAC;IAC1F,CAAC;IACD,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC/C,MAAM,IAAI,mBAAmB,CAAC,cAAc,EAAE,wBAAwB,CAAC,CAAC;IACzE,CAAC;IAED,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACJ,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IAC7C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,MAAM,CAAC,GAAG,GAA0C,CAAC;QACrD,MAAM,IAAI,mBAAmB,CAC5B,uBAAuB,EACvB,8BAA8B,YAAY,KAAK,CAAC,CAAC,IAAI,IAAI,EAAE,IAAI,CAAC,CAAC,OAAO,IAAI,eAAe,EAAE,CAAC,IAAI,EAAE,CACpG,CAAC;IACH,CAAC;IAED,OAAO,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AAC9B,CAAC"}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { type Static, Type } from "typebox";
|
|
2
|
-
export declare const AUDIENCE_VALUES: readonly ["orchestrator-only", "subagent", "any"];
|
|
3
|
-
export type AudienceValue = (typeof AUDIENCE_VALUES)[number];
|
|
4
|
-
export declare const WorkflowFrontmatterSchema: Type.TObject<{
|
|
5
|
-
audience: Type.TOptional<Type.TUnion<[Type.TLiteral<"orchestrator-only">, Type.TLiteral<"subagent">, Type.TLiteral<"any">]>>;
|
|
6
|
-
deps: Type.TOptional<Type.TObject<{
|
|
7
|
-
personas: Type.TOptional<Type.TArray<Type.TString>>;
|
|
8
|
-
}>>;
|
|
9
|
-
}>;
|
|
10
|
-
export type WorkflowFrontmatter = Static<typeof WorkflowFrontmatterSchema>;
|
|
11
|
-
export interface LoadedWorkflow {
|
|
12
|
-
filePath: string;
|
|
13
|
-
rawMarkdown: string;
|
|
14
|
-
frontmatter: WorkflowFrontmatter;
|
|
15
|
-
/** Resolved audience; defaults to "any" when the key is absent. */
|
|
16
|
-
audience: AudienceValue;
|
|
17
|
-
}
|
|
18
|
-
export type WorkflowLoaderErrorCode = "missing_file" | "invalid_frontmatter" | "validation_failed";
|
|
19
|
-
export declare class WorkflowLoaderError extends Error {
|
|
20
|
-
readonly code: WorkflowLoaderErrorCode;
|
|
21
|
-
constructor(code: WorkflowLoaderErrorCode, message: string);
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Parse the YAML-like frontmatter of a workflow markdown file.
|
|
25
|
-
*
|
|
26
|
-
* Returns `{}` if the file does not start with `---`.
|
|
27
|
-
* Throws `WorkflowLoaderError("invalid_frontmatter", ...)` on malformed YAML.
|
|
28
|
-
*/
|
|
29
|
-
export declare function parseWorkflowFrontmatter(rawMarkdown: string): WorkflowFrontmatter;
|
|
30
|
-
/**
|
|
31
|
-
* Extract the audience value from a parsed WorkflowFrontmatter.
|
|
32
|
-
* Returns "any" when the key is absent or has an unrecognised value.
|
|
33
|
-
*/
|
|
34
|
-
export declare function extractAudience(frontmatter: WorkflowFrontmatter): AudienceValue;
|
|
35
|
-
/**
|
|
36
|
-
* Load and parse a materialized workflow markdown file.
|
|
37
|
-
*
|
|
38
|
-
* Throws `WorkflowLoaderError("missing_file", ...)` if the file is absent or unreadable.
|
|
39
|
-
* Throws `WorkflowLoaderError("invalid_frontmatter", ...)` if frontmatter is malformed.
|
|
40
|
-
*/
|
|
41
|
-
export declare function loadWorkflow(workflowPath: string): LoadedWorkflow;
|
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
// workflow-loader.ts — Parses a materialized workflow markdown file.
|
|
2
|
-
// Exports WorkflowFrontmatter (TypeBox), loadWorkflow(), extractAudience(),
|
|
3
|
-
// and parseWorkflowFrontmatter() (FORGE-S21-T01).
|
|
4
|
-
//
|
|
5
|
-
// Iron Laws:
|
|
6
|
-
// IL1 — code only under forge-cli/src/extensions/forgecli/.
|
|
7
|
-
// IL6 — no shell-string interpolation; all I/O via fs synchronous APIs.
|
|
8
|
-
// IL7 — no silent continuation; malformed state throws typed errors.
|
|
9
|
-
import * as fs from "node:fs";
|
|
10
|
-
import { Type } from "typebox";
|
|
11
|
-
// ── Types ─────────────────────────────────────────────────────────────────
|
|
12
|
-
export const AUDIENCE_VALUES = ["orchestrator-only", "subagent", "any"];
|
|
13
|
-
export const WorkflowFrontmatterSchema = Type.Object({
|
|
14
|
-
audience: Type.Optional(Type.Union([
|
|
15
|
-
Type.Literal("orchestrator-only"),
|
|
16
|
-
Type.Literal("subagent"),
|
|
17
|
-
Type.Literal("any"),
|
|
18
|
-
])),
|
|
19
|
-
deps: Type.Optional(Type.Object({
|
|
20
|
-
personas: Type.Optional(Type.Array(Type.String())),
|
|
21
|
-
}, { additionalProperties: true })),
|
|
22
|
-
}, { additionalProperties: true });
|
|
23
|
-
export class WorkflowLoaderError extends Error {
|
|
24
|
-
code;
|
|
25
|
-
constructor(code, message) {
|
|
26
|
-
super(message);
|
|
27
|
-
this.name = "WorkflowLoaderError";
|
|
28
|
-
this.code = code;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
// ── Frontmatter parser ────────────────────────────────────────────────────
|
|
32
|
-
function parseInlineArray(raw) {
|
|
33
|
-
const trimmed = raw.trim();
|
|
34
|
-
if (!trimmed.startsWith("[") || !trimmed.endsWith("]"))
|
|
35
|
-
return null;
|
|
36
|
-
const inner = trimmed.slice(1, -1);
|
|
37
|
-
if (inner.trim() === "")
|
|
38
|
-
return [];
|
|
39
|
-
return inner
|
|
40
|
-
.split(",")
|
|
41
|
-
.map((s) => {
|
|
42
|
-
const t = s.trim();
|
|
43
|
-
if ((t.startsWith('"') && t.endsWith('"') && t.length >= 2) ||
|
|
44
|
-
(t.startsWith("'") && t.endsWith("'") && t.length >= 2)) {
|
|
45
|
-
return t.slice(1, -1);
|
|
46
|
-
}
|
|
47
|
-
return t;
|
|
48
|
-
})
|
|
49
|
-
.filter((s) => s.length > 0);
|
|
50
|
-
}
|
|
51
|
-
function stripQuotes(value) {
|
|
52
|
-
const v = value.trim();
|
|
53
|
-
if ((v.startsWith('"') && v.endsWith('"') && v.length >= 2) ||
|
|
54
|
-
(v.startsWith("'") && v.endsWith("'") && v.length >= 2)) {
|
|
55
|
-
return v.slice(1, -1);
|
|
56
|
-
}
|
|
57
|
-
return v;
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Parse the YAML-like frontmatter of a workflow markdown file.
|
|
61
|
-
*
|
|
62
|
-
* Returns `{}` if the file does not start with `---`.
|
|
63
|
-
* Throws `WorkflowLoaderError("invalid_frontmatter", ...)` on malformed YAML.
|
|
64
|
-
*/
|
|
65
|
-
export function parseWorkflowFrontmatter(rawMarkdown) {
|
|
66
|
-
const lines = rawMarkdown.split(/\r?\n/);
|
|
67
|
-
if (lines.length === 0 || lines[0] !== "---") {
|
|
68
|
-
return {};
|
|
69
|
-
}
|
|
70
|
-
const fm = {};
|
|
71
|
-
let currentBlock = null;
|
|
72
|
-
let blockChildren = {};
|
|
73
|
-
let closed = false;
|
|
74
|
-
for (let i = 1; i < lines.length; i++) {
|
|
75
|
-
const line = lines[i];
|
|
76
|
-
if (line === "---") {
|
|
77
|
-
if (currentBlock !== null) {
|
|
78
|
-
fm[currentBlock] = blockChildren;
|
|
79
|
-
currentBlock = null;
|
|
80
|
-
blockChildren = {};
|
|
81
|
-
}
|
|
82
|
-
closed = true;
|
|
83
|
-
break;
|
|
84
|
-
}
|
|
85
|
-
if (line.trim() === "")
|
|
86
|
-
continue;
|
|
87
|
-
// Indented line → child of current block.
|
|
88
|
-
if (/^\s/.test(line)) {
|
|
89
|
-
if (currentBlock === null) {
|
|
90
|
-
throw new WorkflowLoaderError("invalid_frontmatter", `Indented frontmatter line ${i + 1} with no parent block: ${JSON.stringify(line)}`);
|
|
91
|
-
}
|
|
92
|
-
const childMatch = /^\s+([A-Za-z0-9_.-]+):\s*(.*)$/.exec(line);
|
|
93
|
-
if (!childMatch) {
|
|
94
|
-
throw new WorkflowLoaderError("invalid_frontmatter", `Malformed indented frontmatter line ${i + 1}: ${JSON.stringify(line)}`);
|
|
95
|
-
}
|
|
96
|
-
const childKey = childMatch[1];
|
|
97
|
-
const childRaw = childMatch[2].trim();
|
|
98
|
-
const arr = parseInlineArray(childRaw);
|
|
99
|
-
blockChildren[childKey] = arr !== null ? arr : stripQuotes(childRaw);
|
|
100
|
-
continue;
|
|
101
|
-
}
|
|
102
|
-
// Top-level key:value or bare block key.
|
|
103
|
-
const topMatch = /^([A-Za-z0-9_.-]+):\s*(.*)$/.exec(line);
|
|
104
|
-
if (!topMatch) {
|
|
105
|
-
throw new WorkflowLoaderError("invalid_frontmatter", `Malformed frontmatter line ${i + 1}: ${JSON.stringify(line)}`);
|
|
106
|
-
}
|
|
107
|
-
if (currentBlock !== null) {
|
|
108
|
-
fm[currentBlock] = blockChildren;
|
|
109
|
-
currentBlock = null;
|
|
110
|
-
blockChildren = {};
|
|
111
|
-
}
|
|
112
|
-
const key = topMatch[1];
|
|
113
|
-
const rawValue = topMatch[2].trim();
|
|
114
|
-
if (rawValue === "") {
|
|
115
|
-
currentBlock = key;
|
|
116
|
-
blockChildren = {};
|
|
117
|
-
}
|
|
118
|
-
else {
|
|
119
|
-
const arr = parseInlineArray(rawValue);
|
|
120
|
-
fm[key] = arr !== null ? arr : stripQuotes(rawValue);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
if (!closed) {
|
|
124
|
-
throw new WorkflowLoaderError("invalid_frontmatter", "Workflow frontmatter block opened with `---` but never closed");
|
|
125
|
-
}
|
|
126
|
-
return fm;
|
|
127
|
-
}
|
|
128
|
-
// ── Audience extraction ───────────────────────────────────────────────────
|
|
129
|
-
/**
|
|
130
|
-
* Extract the audience value from a parsed WorkflowFrontmatter.
|
|
131
|
-
* Returns "any" when the key is absent or has an unrecognised value.
|
|
132
|
-
*/
|
|
133
|
-
export function extractAudience(frontmatter) {
|
|
134
|
-
const raw = frontmatter.audience;
|
|
135
|
-
if (!raw)
|
|
136
|
-
return "any";
|
|
137
|
-
if (AUDIENCE_VALUES.includes(raw))
|
|
138
|
-
return raw;
|
|
139
|
-
return "any";
|
|
140
|
-
}
|
|
141
|
-
// ── loadWorkflow ──────────────────────────────────────────────────────────
|
|
142
|
-
/**
|
|
143
|
-
* Load and parse a materialized workflow markdown file.
|
|
144
|
-
*
|
|
145
|
-
* Throws `WorkflowLoaderError("missing_file", ...)` if the file is absent or unreadable.
|
|
146
|
-
* Throws `WorkflowLoaderError("invalid_frontmatter", ...)` if frontmatter is malformed.
|
|
147
|
-
*/
|
|
148
|
-
export function loadWorkflow(workflowPath) {
|
|
149
|
-
if (!fs.existsSync(workflowPath)) {
|
|
150
|
-
throw new WorkflowLoaderError("missing_file", `Workflow not found: ${workflowPath}`);
|
|
151
|
-
}
|
|
152
|
-
let rawMarkdown;
|
|
153
|
-
try {
|
|
154
|
-
rawMarkdown = fs.readFileSync(workflowPath, "utf8");
|
|
155
|
-
}
|
|
156
|
-
catch (err) {
|
|
157
|
-
const e = err;
|
|
158
|
-
throw new WorkflowLoaderError("missing_file", `Failed to read workflow ${workflowPath}: ${e.message ?? "unknown"}`);
|
|
159
|
-
}
|
|
160
|
-
const frontmatter = parseWorkflowFrontmatter(rawMarkdown);
|
|
161
|
-
const audience = extractAudience(frontmatter);
|
|
162
|
-
return { filePath: workflowPath, rawMarkdown, frontmatter, audience };
|
|
163
|
-
}
|
|
164
|
-
//# sourceMappingURL=workflow-loader.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"workflow-loader.js","sourceRoot":"","sources":["../../../../src/extensions/forgecli/loaders/workflow-loader.ts"],"names":[],"mappings":"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"}
|