File size: 2,285 Bytes
3f76ff4
837e3ac
3f76ff4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
837e3ac
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import { describe, expect, it } from "vitest";
import { applyComposerSuggestion, getComposerSuggestions } from "./composer-autocomplete";
import { parseCommand } from "./command-parser";
import seedWorkPackages from "../agentic_pm_demo_codex_plans/data/work-packages.seed.json";
import type { WorkPackage } from "./work-package-types";

const wps = seedWorkPackages as WorkPackage[];

describe("parseCommand", () => {
  it("matches shortName and mode", () => {
    const r = parseCommand("@SRS ask Which components are needed?", wps);
    expect(r.error).toBeUndefined();
    expect(r.matchedWorkPackageId).toBe("wp-srs");
    expect(r.parsed.mode).toBe("ask");
    expect(r.parsed.instruction).toContain("Which components");
  });

  it("matches multi-token title with execute", () => {
    const r = parseCommand(
      "@Final Engineering Concept execute Generate BOM and SBOM.",
      wps,
    );
    expect(r.error).toBeUndefined();
    expect(r.matchedWorkPackageId).toBe("wp-final-engineering-concept");
    expect(r.parsed.mode).toBe("execute");
  });

  it("suggests close matches for unknown package", () => {
    const r = parseCommand("@Foo execute Do something", wps);
    expect(r.error).toBeTruthy();
    expect(r.suggestions?.length || 0).toBeGreaterThanOrEqual(0);
  });

  it("defaults to ask when mode is missing and package matches", () => {
    const r = parseCommand("@CRS Which components are needed?", wps);
    expect(r.error).toBeUndefined();
    expect(r.matchedWorkPackageId).toBe("wp-crs");
    expect(r.parsed.mode).toBe("ask");
  });

  it("treats slash text as plain input until autocomplete expands it", () => {
    const slashInput = parseCommand("/plan", wps);
    expect(slashInput.parsed.mode).toBeUndefined();

    const suggestion = getComposerSuggestions("/pl", wps).find(
      (item) => item.kind === "command" && item.mode === "plan",
    );
    const expanded = applyComposerSuggestion({
      draft: "/pl",
      suggestion: suggestion!,
      selectedWorkPackage: wps.find((wp) => wp.shortName === "SRS"),
    });
    const parsedExpanded = parseCommand(expanded, wps);

    expect(expanded).toBe("@SRS plan ");
    expect(parsedExpanded.matchedWorkPackageId).toBe("wp-srs");
    expect(parsedExpanded.parsed.mode).toBe("plan");
  });
});