@xdevops/issue-auto-finish 1.0.86 → 1.0.87

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.
Files changed (129) hide show
  1. package/dist/AIRunnerRegistry-II3WWSFN.js +31 -0
  2. package/dist/PtyRunner-6UGI5STW.js +22 -0
  3. package/dist/TerminalManager-RT2N7N5R.js +8 -0
  4. package/dist/ai-runner/AIRunner.d.ts +9 -1
  5. package/dist/ai-runner/AIRunner.d.ts.map +1 -1
  6. package/dist/ai-runner/AIRunnerRegistry.d.ts +37 -1
  7. package/dist/ai-runner/AIRunnerRegistry.d.ts.map +1 -1
  8. package/dist/ai-runner/PtyRunner.d.ts +114 -0
  9. package/dist/ai-runner/PtyRunner.d.ts.map +1 -0
  10. package/dist/ai-runner/index.d.ts +3 -1
  11. package/dist/ai-runner/index.d.ts.map +1 -1
  12. package/dist/{ai-runner-SVUNA3FX.js → ai-runner-HLA44WI6.js} +12 -3
  13. package/dist/{analyze-SXXPE5XL.js → analyze-ZIXNC5GN.js} +10 -8
  14. package/dist/{analyze-SXXPE5XL.js.map → analyze-ZIXNC5GN.js.map} +1 -1
  15. package/dist/{braindump-4E5SDMSZ.js → braindump-56WAY2RD.js} +10 -8
  16. package/dist/{braindump-4E5SDMSZ.js.map → braindump-56WAY2RD.js.map} +1 -1
  17. package/dist/{chunk-ICXB2WP5.js → chunk-2MESXJEZ.js} +3 -3
  18. package/dist/{chunk-P4O4ZXEC.js → chunk-2YQHKXLL.js} +40 -19
  19. package/dist/chunk-2YQHKXLL.js.map +1 -0
  20. package/dist/chunk-AVGZH64A.js +211 -0
  21. package/dist/chunk-AVGZH64A.js.map +1 -0
  22. package/dist/{chunk-OUPJMHAL.js → chunk-IP3QTP5A.js} +1026 -764
  23. package/dist/chunk-IP3QTP5A.js.map +1 -0
  24. package/dist/chunk-KC5S66OZ.js +177 -0
  25. package/dist/chunk-KC5S66OZ.js.map +1 -0
  26. package/dist/{chunk-4QV6D34Y.js → chunk-M5C2WILQ.js} +8 -6
  27. package/dist/{chunk-4QV6D34Y.js.map → chunk-M5C2WILQ.js.map} +1 -1
  28. package/dist/{chunk-FWEW5E3B.js → chunk-NZHKAPU6.js} +35 -5
  29. package/dist/chunk-NZHKAPU6.js.map +1 -0
  30. package/dist/{chunk-KTYPZTF4.js → chunk-O3WEV5W3.js} +10 -2
  31. package/dist/chunk-O3WEV5W3.js.map +1 -0
  32. package/dist/{chunk-QO5VTSMI.js → chunk-QZZGIZWC.js} +455 -202
  33. package/dist/chunk-QZZGIZWC.js.map +1 -0
  34. package/dist/{chunk-4LFNFRCL.js → chunk-SAMTXC4A.js} +91 -214
  35. package/dist/chunk-SAMTXC4A.js.map +1 -0
  36. package/dist/chunk-U237JSLB.js +1 -0
  37. package/dist/chunk-U237JSLB.js.map +1 -0
  38. package/dist/chunk-U6GWFTKA.js +657 -0
  39. package/dist/chunk-U6GWFTKA.js.map +1 -0
  40. package/dist/{chunk-HOFYJEJ4.js → chunk-UBQLXQ7I.js} +11 -11
  41. package/dist/cli/setup/env-metadata.d.ts.map +1 -1
  42. package/dist/cli.js +8 -7
  43. package/dist/cli.js.map +1 -1
  44. package/dist/{config-QLINHCHD.js → config-WTRSZLOC.js} +4 -3
  45. package/dist/config-WTRSZLOC.js.map +1 -0
  46. package/dist/config-schema.d.ts +17 -1
  47. package/dist/config-schema.d.ts.map +1 -1
  48. package/dist/config.d.ts +20 -0
  49. package/dist/config.d.ts.map +1 -1
  50. package/dist/errors/PhaseAbortedError.d.ts +3 -3
  51. package/dist/errors/PhaseAbortedError.d.ts.map +1 -1
  52. package/dist/errors-S3BWYA4I.js +43 -0
  53. package/dist/errors-S3BWYA4I.js.map +1 -0
  54. package/dist/index.d.ts.map +1 -1
  55. package/dist/index.js +14 -11
  56. package/dist/{init-TDKDC6YP.js → init-QQDXGTPB.js} +7 -6
  57. package/dist/{init-TDKDC6YP.js.map → init-QQDXGTPB.js.map} +1 -1
  58. package/dist/lib.js +9 -7
  59. package/dist/lib.js.map +1 -1
  60. package/dist/orchestrator/IssueProcessingContext.d.ts +39 -21
  61. package/dist/orchestrator/IssueProcessingContext.d.ts.map +1 -1
  62. package/dist/orchestrator/PipelineOrchestrator.d.ts +10 -1
  63. package/dist/orchestrator/PipelineOrchestrator.d.ts.map +1 -1
  64. package/dist/orchestrator/steps/PhaseLoopStep.d.ts +1 -1
  65. package/dist/orchestrator/steps/PhaseLoopStep.d.ts.map +1 -1
  66. package/dist/orchestrator/steps/SetupStep.d.ts.map +1 -1
  67. package/dist/persistence/PlanPersistence.d.ts +7 -1
  68. package/dist/persistence/PlanPersistence.d.ts.map +1 -1
  69. package/dist/phases/BasePhase.d.ts +31 -42
  70. package/dist/phases/BasePhase.d.ts.map +1 -1
  71. package/dist/phases/BuildPhase.d.ts.map +1 -1
  72. package/dist/phases/PhaseFactory.d.ts +2 -3
  73. package/dist/phases/PhaseFactory.d.ts.map +1 -1
  74. package/dist/phases/PhaseOutcome.d.ts +42 -0
  75. package/dist/phases/PhaseOutcome.d.ts.map +1 -0
  76. package/dist/phases/PlanPhase.d.ts +1 -1
  77. package/dist/phases/PlanPhase.d.ts.map +1 -1
  78. package/dist/phases/ReleasePhase.d.ts +8 -18
  79. package/dist/phases/ReleasePhase.d.ts.map +1 -1
  80. package/dist/phases/UatPhase.d.ts +7 -24
  81. package/dist/phases/UatPhase.d.ts.map +1 -1
  82. package/dist/phases/VerifyPhase.d.ts +4 -4
  83. package/dist/phases/VerifyPhase.d.ts.map +1 -1
  84. package/dist/poller/IssuePoller.d.ts.map +1 -1
  85. package/dist/prompts/release-templates.d.ts.map +1 -1
  86. package/dist/prompts/templates.d.ts.map +1 -1
  87. package/dist/{restart-4NSHDOX3.js → restart-BMILTP5X.js} +6 -5
  88. package/dist/{restart-4NSHDOX3.js.map → restart-BMILTP5X.js.map} +1 -1
  89. package/dist/run.js +14 -11
  90. package/dist/run.js.map +1 -1
  91. package/dist/settings/ExperimentalSettings.d.ts +1 -1
  92. package/dist/settings/ExperimentalSettings.d.ts.map +1 -1
  93. package/dist/start-6QRW6IJI.js +15 -0
  94. package/dist/start-6QRW6IJI.js.map +1 -0
  95. package/dist/terminal/TerminalManager.d.ts +62 -0
  96. package/dist/terminal/TerminalManager.d.ts.map +1 -0
  97. package/dist/terminal/TerminalWebSocket.d.ts +9 -0
  98. package/dist/terminal/TerminalWebSocket.d.ts.map +1 -0
  99. package/dist/tracker/ExecutableTask.d.ts +4 -2
  100. package/dist/tracker/ExecutableTask.d.ts.map +1 -1
  101. package/dist/tracker/IssueState.d.ts +11 -1
  102. package/dist/tracker/IssueState.d.ts.map +1 -1
  103. package/dist/tracker/IssueTracker.d.ts +19 -1
  104. package/dist/tracker/IssueTracker.d.ts.map +1 -1
  105. package/dist/web/WebServer.d.ts +4 -0
  106. package/dist/web/WebServer.d.ts.map +1 -1
  107. package/dist/web/routes/terminal.d.ts +11 -0
  108. package/dist/web/routes/terminal.d.ts.map +1 -0
  109. package/dist/webhook/CommandExecutor.d.ts.map +1 -1
  110. package/package.json +7 -1
  111. package/src/web/frontend/dist/assets/index-COYziOhv.css +1 -0
  112. package/src/web/frontend/dist/assets/index-D_oTMuJU.js +151 -0
  113. package/src/web/frontend/dist/index.html +2 -2
  114. package/dist/chunk-4LFNFRCL.js.map +0 -1
  115. package/dist/chunk-DADQSKPL.js +0 -1
  116. package/dist/chunk-FWEW5E3B.js.map +0 -1
  117. package/dist/chunk-KTYPZTF4.js.map +0 -1
  118. package/dist/chunk-OUPJMHAL.js.map +0 -1
  119. package/dist/chunk-P4O4ZXEC.js.map +0 -1
  120. package/dist/chunk-QO5VTSMI.js.map +0 -1
  121. package/dist/start-XZIBPLC2.js +0 -14
  122. package/src/web/frontend/dist/assets/index-BWVpNmFm.js +0 -133
  123. package/src/web/frontend/dist/assets/index-C7lorIa0.css +0 -1
  124. /package/dist/{ai-runner-SVUNA3FX.js.map → AIRunnerRegistry-II3WWSFN.js.map} +0 -0
  125. /package/dist/{chunk-DADQSKPL.js.map → PtyRunner-6UGI5STW.js.map} +0 -0
  126. /package/dist/{config-QLINHCHD.js.map → TerminalManager-RT2N7N5R.js.map} +0 -0
  127. /package/dist/{start-XZIBPLC2.js.map → ai-runner-HLA44WI6.js.map} +0 -0
  128. /package/dist/{chunk-ICXB2WP5.js.map → chunk-2MESXJEZ.js.map} +0 -0
  129. /package/dist/{chunk-HOFYJEJ4.js.map → chunk-UBQLXQ7I.js.map} +0 -0
@@ -0,0 +1,31 @@
1
+ import {
2
+ createAIRunner,
3
+ getBinaryEnvKey,
4
+ getDefaultBinary,
5
+ getPtyProfile,
6
+ getRegisteredRunnerModes,
7
+ getRegistryEntry,
8
+ getRunnerCapabilities,
9
+ isBinaryAvailable,
10
+ isRegisteredRunner,
11
+ registerAIRunner,
12
+ resolveRunnerMode,
13
+ validateRunnerRegistry
14
+ } from "./chunk-SAMTXC4A.js";
15
+ import "./chunk-AVGZH64A.js";
16
+ import "./chunk-GF2RRYHB.js";
17
+ export {
18
+ createAIRunner,
19
+ getBinaryEnvKey,
20
+ getDefaultBinary,
21
+ getPtyProfile,
22
+ getRegisteredRunnerModes,
23
+ getRegistryEntry,
24
+ getRunnerCapabilities,
25
+ isBinaryAvailable,
26
+ isRegisteredRunner,
27
+ registerAIRunner,
28
+ resolveRunnerMode,
29
+ validateRunnerRegistry
30
+ };
31
+ //# sourceMappingURL=AIRunnerRegistry-II3WWSFN.js.map
@@ -0,0 +1,22 @@
1
+ import {
2
+ PERMISSION_DIALOG_RE,
3
+ PtyRunner,
4
+ TRUST_DIALOG_RE,
5
+ containsActiveWork,
6
+ isIdlePrompt,
7
+ isTuiNoise,
8
+ stripAnsi
9
+ } from "./chunk-U6GWFTKA.js";
10
+ import "./chunk-SAMTXC4A.js";
11
+ import "./chunk-AVGZH64A.js";
12
+ import "./chunk-GF2RRYHB.js";
13
+ export {
14
+ PERMISSION_DIALOG_RE,
15
+ PtyRunner,
16
+ TRUST_DIALOG_RE,
17
+ containsActiveWork,
18
+ isIdlePrompt,
19
+ isTuiNoise,
20
+ stripAnsi
21
+ };
22
+ //# sourceMappingURL=PtyRunner-6UGI5STW.js.map
@@ -0,0 +1,8 @@
1
+ import {
2
+ TerminalManager
3
+ } from "./chunk-KC5S66OZ.js";
4
+ import "./chunk-GF2RRYHB.js";
5
+ export {
6
+ TerminalManager
7
+ };
8
+ //# sourceMappingURL=TerminalManager-RT2N7N5R.js.map
@@ -17,7 +17,13 @@ export interface RunOptions {
17
17
  idleTimeoutMs?: number;
18
18
  sessionId?: string;
19
19
  continueSession?: boolean;
20
- mode?: 'plan' | 'agent';
20
+ mode?: string;
21
+ /** Current pipeline phase name — used by PtyRunner for per-phase agent selection */
22
+ phaseName?: string;
23
+ /** PTY 产物门控:返回 true 表示预期产物已就绪,false 时 PtyRunner 不会声明完成 */
24
+ artifactCheck?: () => boolean;
25
+ /** 预期产物文件的完整路径列表(用于 PtyRunner 原生 plan mode 的 commit 步骤) */
26
+ artifactPaths?: string[];
21
27
  onStreamEvent?: (event: StreamEvent) => void;
22
28
  onInputRequired?: (request: InputRequest) => Promise<string>;
23
29
  }
@@ -34,5 +40,7 @@ export interface AIRunner {
34
40
  run(options: RunOptions): Promise<RunResult>;
35
41
  killAll(): void;
36
42
  killByWorkDir(targetWorkDir: string): number;
43
+ /** Interrupt the running task in a session without destroying it (PTY only). */
44
+ interruptByWorkDir?(targetWorkDir: string): boolean;
37
45
  }
38
46
  //# sourceMappingURL=AIRunner.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AIRunner.d.ts","sourceRoot":"","sources":["../../src/ai-runner/AIRunner.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,eAAe,GAAG,SAAS,CAAC;IAClC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACxB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IAC7C,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CAC9D;AAED,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,qDAAqD;IACrD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,CAAC,EAAE,YAAY,GAAG,MAAM,CAAC;CACrC;AAED,MAAM,WAAW,QAAQ;IACvB,GAAG,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAC7C,OAAO,IAAI,IAAI,CAAC;IAChB,aAAa,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAAC;CAC9C"}
1
+ {"version":3,"file":"AIRunner.d.ts","sourceRoot":"","sources":["../../src/ai-runner/AIRunner.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,eAAe,GAAG,SAAS,CAAC;IAClC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oFAAoF;IACpF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC;IAC9B,2DAA2D;IAC3D,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IAC7C,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CAC9D;AAED,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,qDAAqD;IACrD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,CAAC,EAAE,YAAY,GAAG,MAAM,CAAC;CACrC;AAED,MAAM,WAAW,QAAQ;IACvB,GAAG,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAC7C,OAAO,IAAI,IAAI,CAAC;IAChB,aAAa,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAAC;IAC7C,gFAAgF;IAChF,kBAAkB,CAAC,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC;CACrD"}
@@ -12,11 +12,44 @@ export interface RunnerCapabilities {
12
12
  /** Whether the runner natively supports plan mode (AI enters planning mindset) */
13
13
  nativePlanMode: boolean;
14
14
  }
15
+ /**
16
+ * Describes how to launch this agent inside a PTY session.
17
+ * Only agents supporting interactive terminal mode declare a PtyProfile.
18
+ * Agents using different protocols (e.g. codebuddy-acp with ACP/JSON-RPC) do NOT have one.
19
+ */
20
+ export interface PtyProfile {
21
+ /** Build PTY-mode arguments (no --output-format stream-json, no -p stdin) */
22
+ buildPtyArgs: (opts: {
23
+ model?: string;
24
+ startMode?: string;
25
+ }) => string[];
26
+ /** Key sequence to submit input. Defaults to '\r' (CR).
27
+ * cursor-agent uses Kitty keyboard protocol: '\x1b[13u' */
28
+ enterKey?: string;
29
+ /** If true, text and Enter key must be sent in separate PTY writes with a
30
+ * small delay (≥100ms) between them. Agents whose TUI uses input coalescing
31
+ * (e.g. codebuddy) treat rapid text+Enter as paste, swallowing the Enter. */
32
+ separateEnter?: boolean;
33
+ /** Escape sequence to cycle interactive mode (e.g. '\x1b[Z' = Shift+Tab).
34
+ * If set, PtyRunner can toggle plan mode within a running session. */
35
+ modeCycleKey?: string;
36
+ /** Detect the current interactive mode from PTY output after a modeCycleKey press.
37
+ * Returns a mode name string (e.g. 'plan', 'bypass', 'accept-edits'). */
38
+ detectMode?: (stripped: string) => string | undefined;
39
+ /** The mode name that detectMode returns when plan mode is active */
40
+ planModeName?: string;
41
+ /** The default mode name after agent startup (before any mode switching) */
42
+ defaultModeName?: string;
43
+ }
15
44
  export interface RunnerRegistryEntry {
16
- ctor: RunnerConstructor;
45
+ ctor?: RunnerConstructor;
46
+ /** 自定义工厂函数(优先于 ctor),用于需要额外依赖注入的 runner(如 PtyRunner) */
47
+ factoryFn?: (binary: string, nvmNodeVersion: string, model?: string) => AIRunner;
17
48
  defaultBinary: string;
18
49
  binaryEnvKey: string;
19
50
  capabilities: RunnerCapabilities;
51
+ /** If set, this runner can be used as an agent inside PtyRunner */
52
+ ptyProfile?: PtyProfile;
20
53
  }
21
54
  export declare function registerAIRunner(mode: string, entry: RunnerRegistryEntry): void;
22
55
  export declare function getRegisteredRunnerModes(): string[];
@@ -25,6 +58,9 @@ export declare function resolveRunnerMode(raw: string): string;
25
58
  export declare function getDefaultBinary(mode: string): string;
26
59
  export declare function getBinaryEnvKey(mode: string): string | undefined;
27
60
  export declare function getRunnerCapabilities(mode: string): RunnerCapabilities | undefined;
61
+ export declare function getPtyProfile(agentMode: string): PtyProfile | undefined;
62
+ /** Get registry entry for an agent mode (used by PtyRunner to resolve binary/envKey) */
63
+ export declare function getRegistryEntry(mode: string): RunnerRegistryEntry | undefined;
28
64
  export declare function createAIRunner(ai: AIConfig): AIRunner;
29
65
  export declare function validateRunnerRegistry(modes: string[]): void;
30
66
  /** Check if a binary is available on the system PATH. */
@@ -1 +1 @@
1
- {"version":3,"file":"AIRunnerRegistry.d.ts","sourceRoot":"","sources":["../../src/ai-runner/AIRunnerRegistry.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAQtD,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,KAAK,iBAAiB,GAAG,KAAK,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,YAAY,CAAC;AAEtG,MAAM,WAAW,kBAAkB;IACjC,kFAAkF;IAClF,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,iBAAiB,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,kBAAkB,CAAC;CAClC;AAQD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,mBAAmB,GAAG,IAAI,CAE/E;AAED,wBAAgB,wBAAwB,IAAI,MAAM,EAAE,CAEnD;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAExD;AAMD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGrD;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEhE;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAElF;AAMD,wBAAgB,cAAc,CAAC,EAAE,EAAE,QAAQ,GAAG,QAAQ,CAOrD;AAMD,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAQ5D;AAMD,yDAAyD;AACzD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAMlE"}
1
+ {"version":3,"file":"AIRunnerRegistry.d.ts","sourceRoot":"","sources":["../../src/ai-runner/AIRunnerRegistry.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAQtD,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,KAAK,iBAAiB,GAAG,KAAK,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,YAAY,CAAC;AAEtG,MAAM,WAAW,kBAAkB;IACjC,kFAAkF;IAClF,cAAc,EAAE,OAAO,CAAC;CACzB;AAED;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,6EAA6E;IAC7E,YAAY,EAAE,CAAC,IAAI,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,MAAM,EAAE,CAAC;IACzE;gEAC4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;kFAE8E;IAC9E,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;2EACuE;IACvE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;8EAC0E;IAC1E,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACtD,qEAAqE;IACrE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4EAA4E;IAC5E,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,iBAAiB,CAAC;IACzB,wDAAwD;IACxD,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,QAAQ,CAAC;IACjF,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,kBAAkB,CAAC;IACjC,mEAAmE;IACnE,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB;AAQD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,mBAAmB,GAAG,IAAI,CAE/E;AAED,wBAAgB,wBAAwB,IAAI,MAAM,EAAE,CAEnD;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAExD;AAMD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGrD;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEhE;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAElF;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAEvE;AAED,wFAAwF;AACxF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,mBAAmB,GAAG,SAAS,CAE9E;AAMD,wBAAgB,cAAc,CAAC,EAAE,EAAE,QAAQ,GAAG,QAAQ,CAUrD;AAMD,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAQ5D;AAMD,yDAAyD;AACzD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAMlE"}
@@ -0,0 +1,114 @@
1
+ import type { AIRunner, RunOptions, RunResult } from './AIRunner.js';
2
+ import type { TerminalManager } from '../terminal/TerminalManager.js';
3
+ export declare function stripAnsi(str: string): string;
4
+ /** Claude Code / Codebuddy shows a prompt when idle and waiting for user input.
5
+ * - Claude Code: ❯ (U+276F) — unique character, safe to match broadly
6
+ * - Codebuddy: > — appears between separator lines, above ⏵⏵ status bar
7
+ */
8
+ export declare function isIdlePrompt(stripped: string): boolean;
9
+ /** Workspace trust dialog — TUI strips spaces, so use \s* between words.
10
+ * Claude Code: "trust this folder" / "I trust this"
11
+ * Codebuddy: "Do you trust the files in this folder?"
12
+ */
13
+ export declare const TRUST_DIALOG_RE: RegExp;
14
+ /** Permission / confirmation dialog — Claude Code asks "Do you want to proceed?"
15
+ * when running potentially dangerous commands in plan mode.
16
+ * The dialog shows numbered options with "Yes" pre-selected (❯ 1. Yes).
17
+ * Auto-confirm by sending Enter to select the highlighted option. */
18
+ export declare const PERMISSION_DIALOG_RE: RegExp;
19
+ /**
20
+ * Check if a PTY data frame contains active work content alongside the idle
21
+ * prompt. Claude Code TUI co-renders the ❯ prompt with tool results, file
22
+ * listings, and thinking indicators in a single data frame. When both are
23
+ * present, the frame is a "mixed frame" — the agent is still active.
24
+ *
25
+ * Returns true when the frame has meaningful non-noise, non-prompt content.
26
+ */
27
+ export declare function containsActiveWork(stripped: string): boolean;
28
+ /** True when the line is Claude Code TUI chrome (spinners, status bar, etc.) */
29
+ export declare function isTuiNoise(line: string): boolean;
30
+ /**
31
+ * AIRunner implementation that drives persistent interactive AI agent
32
+ * terminal sessions (PTY) per issue.
33
+ *
34
+ * Supports multiple agent types (claude-internal, codebuddy, cursor-agent).
35
+ * Each phase can use a different agent; sessions are reused when the agent
36
+ * doesn't change between consecutive phases, and recreated when it does.
37
+ */
38
+ export declare class PtyRunner implements AIRunner {
39
+ private readonly nvmNodeVersion;
40
+ private readonly terminalManager;
41
+ private readonly defaultAgentMode;
42
+ private readonly phaseAgentMap;
43
+ private readonly globalModel?;
44
+ private readonly idleDetectMs;
45
+ /** workDir → active session info (sessionId + current agent type) */
46
+ private sessions;
47
+ /** Sessions that were forcefully killed (via killByWorkDir/killAll). Checked by
48
+ * detectCompletion's onExit handler to report failure instead of success. */
49
+ private killedSessions;
50
+ constructor(nvmNodeVersion: string, terminalManager: TerminalManager, defaultAgentMode: string, phaseAgentMap: Record<string, string>, globalModel?: string | undefined, idleDetectMs?: number);
51
+ run(options: RunOptions): Promise<RunResult>;
52
+ killAll(): void;
53
+ killByWorkDir(targetWorkDir: string): number;
54
+ interruptByWorkDir(targetWorkDir: string): boolean;
55
+ /** Get the Enter key sequence for the given agent mode */
56
+ private getEnterKey;
57
+ /**
58
+ * Write a command to the PTY and press Enter.
59
+ *
60
+ * Some agents (codebuddy) use input coalescing in their TUI: when text and
61
+ * Enter arrive in the same PTY write, the Enter is treated as a newline
62
+ * character (paste) instead of triggering message submission. For these
63
+ * agents (PtyProfile.separateEnter=true), text and Enter are sent in
64
+ * separate writes with a 150ms gap so the Enter key is recognized as
65
+ * a standalone key press.
66
+ */
67
+ private writeCommand;
68
+ /** Resolve agent mode for a given phase (fallback to default) */
69
+ private resolveAgentForPhase;
70
+ /** Look up PtyProfile from registry + resolve agent-specific binary and model */
71
+ private resolveProfileAndModel;
72
+ private ensureSession;
73
+ /**
74
+ * Wait for the AI agent to show its idle prompt (❯ or >), indicating
75
+ * it is ready to accept input. Used before sending /clear and instructions
76
+ * to prevent commands from arriving before the agent is initialized.
77
+ */
78
+ private waitForPrompt;
79
+ /**
80
+ * Switch the PTY session to (or away from) plan mode by pressing the mode
81
+ * cycle key (Shift+Tab) until the target mode is detected in the output.
82
+ *
83
+ * This is a no-op when the agent has no modeCycleKey configured, or the
84
+ * session is already in the desired mode.
85
+ */
86
+ private ensurePlanMode;
87
+ /**
88
+ * Briefly subscribe to PTY output and collect all data emitted during a
89
+ * window. Used by ensurePlanMode to read the mode indicator after pressing
90
+ * the cycle key.
91
+ */
92
+ private collectRecentOutput;
93
+ /**
94
+ * Whether the agent supports the two-phase native plan strategy:
95
+ * bypass start → Shift+Tab to plan → execute → Shift+Tab to bypass → commit file.
96
+ *
97
+ * Conditions: runner does NOT natively handle plan mode on its own (nativePlanMode=false)
98
+ * AND the PTY profile supports interactive mode switching (modeCycleKey + planModeName).
99
+ */
100
+ private shouldUseNativePlan;
101
+ /**
102
+ * Two-phase plan execution:
103
+ * Phase 1 — Switch to plan mode, send plan prompt, wait for idle (no artifact gate).
104
+ * Phase 2 — Switch to bypass, send commit prompt, wait for artifact file on disk.
105
+ */
106
+ private runNativePlanMode;
107
+ /** Build the prompt that instructs the agent to write the plan to disk. */
108
+ private buildPlanCommitPrompt;
109
+ /** Map detectCompletion result to RunResult. */
110
+ private buildRunResult;
111
+ private writePromptFile;
112
+ private detectCompletion;
113
+ }
114
+ //# sourceMappingURL=PtyRunner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PtyRunner.d.ts","sourceRoot":"","sources":["../../src/ai-runner/PtyRunner.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAe,MAAM,eAAe,CAAC;AAKlF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAatE,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE7C;AAQD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAgCtD;AAyBD;;;GAGG;AACH,eAAO,MAAM,eAAe,QAAkF,CAAC;AAE/G;;;sEAGsE;AACtE,eAAO,MAAM,oBAAoB,QAC8E,CAAC;AAEhH;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAoB5D;AAED,gFAAgF;AAChF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAmBhD;AA8BD;;;;;;;GAOG;AACH,qBAAa,SAAU,YAAW,QAAQ;IAStC,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAChC,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IACjC,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC;IAC7B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAb/B,qEAAqE;IACrE,OAAO,CAAC,QAAQ,CAAqC;IAErD;kFAC8E;IAC9E,OAAO,CAAC,cAAc,CAAqB;gBAGxB,cAAc,EAAE,MAAM,EACtB,eAAe,EAAE,eAAe,EAChC,gBAAgB,EAAE,MAAM,EACxB,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACrC,WAAW,CAAC,EAAE,MAAM,YAAA,EACpB,YAAY,GAAE,MAAe;IAK1C,GAAG,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC;IA4ElD,OAAO,IAAI,IAAI;IASf,aAAa,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM;IAS5C,kBAAkB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO;IAsBlD,0DAA0D;IAC1D,OAAO,CAAC,WAAW;IAKnB;;;;;;;;;OASG;YACW,YAAY;IAa1B,iEAAiE;IACjE,OAAO,CAAC,oBAAoB;IAO5B,iFAAiF;IACjF,OAAO,CAAC,sBAAsB;IAsB9B,OAAO,CAAC,aAAa;IA2ErB;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAgHrB;;;;;;OAMG;YACW,cAAc;IA4C5B;;;;OAIG;IACH,OAAO,CAAC,mBAAmB;IAe3B;;;;;;OAMG;IACH,OAAO,CAAC,mBAAmB;IAM3B;;;;OAIG;YACW,iBAAiB;IA0D/B,2EAA2E;IAC3E,OAAO,CAAC,qBAAqB;IAgB7B,gDAAgD;IAChD,OAAO,CAAC,cAAc;IAgBtB,OAAO,CAAC,eAAe;IAcvB,OAAO,CAAC,gBAAgB;CAgMzB"}
@@ -4,7 +4,9 @@ export { ClaudeInternalRunner } from './ClaudeInternalRunner.js';
4
4
  export { CodebuddyRunner } from './CodebuddyRunner.js';
5
5
  export { CodebuddyAcpRunner } from './CodebuddyAcpRunner.js';
6
6
  export { CursorAgentRunner } from './CursorAgentRunner.js';
7
+ export { PtyRunner } from './PtyRunner.js';
7
8
  export { resolveModelForRunner } from './ModelMapping.js';
8
9
  export { createAIRunner, registerAIRunner, validateRunnerRegistry, getRegisteredRunnerModes, isRegisteredRunner, resolveRunnerMode, getDefaultBinary, getBinaryEnvKey, getRunnerCapabilities, isBinaryAvailable, } from './AIRunnerRegistry.js';
9
- export type { AIConfig, RunnerRegistryEntry, RunnerCapabilities } from './AIRunnerRegistry.js';
10
+ export type { AIConfig, RunnerRegistryEntry, RunnerCapabilities, PtyProfile } from './AIRunnerRegistry.js';
11
+ export { getPtyProfile, getRegistryEntry } from './AIRunnerRegistry.js';
10
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ai-runner/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAChG,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAG1D,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,sBAAsB,EACtB,wBAAwB,EACxB,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,qBAAqB,EACrB,iBAAiB,GAClB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,QAAQ,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ai-runner/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAChG,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAG1D,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,sBAAsB,EACtB,wBAAwB,EACxB,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,qBAAqB,EACrB,iBAAiB,GAClB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,QAAQ,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAC3G,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC"}
@@ -1,4 +1,7 @@
1
- import "./chunk-DADQSKPL.js";
1
+ import "./chunk-U237JSLB.js";
2
+ import {
3
+ PtyRunner
4
+ } from "./chunk-U6GWFTKA.js";
2
5
  import {
3
6
  BaseAIRunner,
4
7
  ClaudeInternalRunner,
@@ -8,7 +11,9 @@ import {
8
11
  createAIRunner,
9
12
  getBinaryEnvKey,
10
13
  getDefaultBinary,
14
+ getPtyProfile,
11
15
  getRegisteredRunnerModes,
16
+ getRegistryEntry,
12
17
  getRunnerCapabilities,
13
18
  isBinaryAvailable,
14
19
  isRegisteredRunner,
@@ -16,7 +21,8 @@ import {
16
21
  resolveModelForRunner,
17
22
  resolveRunnerMode,
18
23
  validateRunnerRegistry
19
- } from "./chunk-4LFNFRCL.js";
24
+ } from "./chunk-SAMTXC4A.js";
25
+ import "./chunk-AVGZH64A.js";
20
26
  import "./chunk-GF2RRYHB.js";
21
27
  export {
22
28
  BaseAIRunner,
@@ -24,10 +30,13 @@ export {
24
30
  CodebuddyAcpRunner,
25
31
  CodebuddyRunner,
26
32
  CursorAgentRunner,
33
+ PtyRunner,
27
34
  createAIRunner,
28
35
  getBinaryEnvKey,
29
36
  getDefaultBinary,
37
+ getPtyProfile,
30
38
  getRegisteredRunnerModes,
39
+ getRegistryEntry,
31
40
  getRunnerCapabilities,
32
41
  isBinaryAvailable,
33
42
  isRegisteredRunner,
@@ -36,4 +45,4 @@ export {
36
45
  resolveRunnerMode,
37
46
  validateRunnerRegistry
38
47
  };
39
- //# sourceMappingURL=ai-runner-SVUNA3FX.js.map
48
+ //# sourceMappingURL=ai-runner-HLA44WI6.js.map
@@ -1,18 +1,20 @@
1
- import {
2
- loadConfig
3
- } from "./chunk-FWEW5E3B.js";
4
- import "./chunk-AKXDQH25.js";
1
+ import "./chunk-U237JSLB.js";
2
+ import "./chunk-U6GWFTKA.js";
5
3
  import {
6
4
  analyze
7
5
  } from "./chunk-B7TVVODN.js";
6
+ import {
7
+ loadConfig
8
+ } from "./chunk-NZHKAPU6.js";
9
+ import "./chunk-AKXDQH25.js";
8
10
  import {
9
11
  getGlobalDir
10
12
  } from "./chunk-TN2SYADO.js";
11
- import "./chunk-DAX3FD2O.js";
12
- import "./chunk-DADQSKPL.js";
13
13
  import {
14
14
  createAIRunner
15
- } from "./chunk-4LFNFRCL.js";
15
+ } from "./chunk-SAMTXC4A.js";
16
+ import "./chunk-AVGZH64A.js";
17
+ import "./chunk-DAX3FD2O.js";
16
18
  import "./chunk-GF2RRYHB.js";
17
19
 
18
20
  // src/cli/commands/analyze.ts
@@ -73,4 +75,4 @@ async function analyzeCommand(opts) {
73
75
  export {
74
76
  analyzeCommand
75
77
  };
76
- //# sourceMappingURL=analyze-SXXPE5XL.js.map
78
+ //# sourceMappingURL=analyze-ZIXNC5GN.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli/commands/analyze.ts"],"sourcesContent":["import path from 'node:path';\nimport fs from 'node:fs';\nimport { loadConfig } from '../../config.js';\nimport { getGlobalDir } from '../../paths.js';\nimport { createAIRunner } from '../../ai-runner/index.js';\nimport { analyze } from '../../knowledge/KnowledgeAnalyzer.js';\n\ninterface AnalyzeCommandOptions {\n dir?: string;\n output?: string;\n force?: boolean;\n}\n\nfunction resolveOutputPath(explicitOutput?: string): string {\n if (explicitOutput) return path.resolve(explicitOutput);\n\n // Same search order as .env\n const envConfigPath = process.env.IAF_CONFIG_PATH;\n if (envConfigPath) {\n return path.join(path.dirname(envConfigPath), 'knowledge.json');\n }\n\n const cwdCandidate = path.resolve(process.cwd(), 'knowledge.json');\n const globalCandidate = path.join(getGlobalDir(), 'knowledge.json');\n\n // Prefer cwd if .env exists there, otherwise global\n if (fs.existsSync(path.resolve(process.cwd(), '.env'))) {\n return cwdCandidate;\n }\n\n return globalCandidate;\n}\n\nexport async function analyzeCommand(opts: AnalyzeCommandOptions): Promise<void> {\n const config = loadConfig();\n const workDir = opts.dir ? path.resolve(opts.dir) : config.project.workDir;\n const outputPath = resolveOutputPath(opts.output);\n\n if (fs.existsSync(outputPath) && !opts.force) {\n console.log(`\\n knowledge.json already exists at: ${outputPath}`);\n console.log(' Use --force to overwrite.\\n');\n process.exitCode = 1;\n return;\n }\n\n console.log(`\\n Analyzing project: ${workDir}`);\n console.log(` Output: ${outputPath}\\n`);\n\n const aiRunner = createAIRunner(config.ai);\n\n try {\n const knowledge = await analyze({\n workDir,\n aiRunner,\n outputPath,\n });\n\n console.log(' Analysis complete!\\n');\n console.log(` Language: ${knowledge.structure.primaryLanguage}`);\n console.log(` Frameworks: ${knowledge.structure.frameworks.join(', ') || 'none'}`);\n console.log(` Monorepo: ${knowledge.structure.isMonorepo ? 'yes' : 'no'}`);\n console.log(` Pkg Manager: ${knowledge.toolchain.packageManager}`);\n console.log(` Triggers: ${knowledge.ruleTriggers.length} rule(s)`);\n console.log(` Known Issues: ${knowledge.knownIssues.length}`);\n console.log(`\\n Saved to: ${outputPath}\\n`);\n } catch (err) {\n console.error(`\\n Analysis failed: ${(err as Error).message}\\n`);\n process.exitCode = 1;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA,OAAO,UAAU;AACjB,OAAO,QAAQ;AAYf,SAAS,kBAAkB,gBAAiC;AAC1D,MAAI,eAAgB,QAAO,KAAK,QAAQ,cAAc;AAGtD,QAAM,gBAAgB,QAAQ,IAAI;AAClC,MAAI,eAAe;AACjB,WAAO,KAAK,KAAK,KAAK,QAAQ,aAAa,GAAG,gBAAgB;AAAA,EAChE;AAEA,QAAM,eAAe,KAAK,QAAQ,QAAQ,IAAI,GAAG,gBAAgB;AACjE,QAAM,kBAAkB,KAAK,KAAK,aAAa,GAAG,gBAAgB;AAGlE,MAAI,GAAG,WAAW,KAAK,QAAQ,QAAQ,IAAI,GAAG,MAAM,CAAC,GAAG;AACtD,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEA,eAAsB,eAAe,MAA4C;AAC/E,QAAM,SAAS,WAAW;AAC1B,QAAM,UAAU,KAAK,MAAM,KAAK,QAAQ,KAAK,GAAG,IAAI,OAAO,QAAQ;AACnE,QAAM,aAAa,kBAAkB,KAAK,MAAM;AAEhD,MAAI,GAAG,WAAW,UAAU,KAAK,CAAC,KAAK,OAAO;AAC5C,YAAQ,IAAI;AAAA,sCAAyC,UAAU,EAAE;AACjE,YAAQ,IAAI,+BAA+B;AAC3C,YAAQ,WAAW;AACnB;AAAA,EACF;AAEA,UAAQ,IAAI;AAAA,uBAA0B,OAAO,EAAE;AAC/C,UAAQ,IAAI,aAAa,UAAU;AAAA,CAAI;AAEvC,QAAM,WAAW,eAAe,OAAO,EAAE;AAEzC,MAAI;AACF,UAAM,YAAY,MAAM,QAAQ;AAAA,MAC9B;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAED,YAAQ,IAAI,wBAAwB;AACpC,YAAQ,IAAI,kBAAkB,UAAU,UAAU,eAAe,EAAE;AACnE,YAAQ,IAAI,kBAAkB,UAAU,UAAU,WAAW,KAAK,IAAI,KAAK,MAAM,EAAE;AACnF,YAAQ,IAAI,kBAAkB,UAAU,UAAU,aAAa,QAAQ,IAAI,EAAE;AAC7E,YAAQ,IAAI,kBAAkB,UAAU,UAAU,cAAc,EAAE;AAClE,YAAQ,IAAI,kBAAkB,UAAU,aAAa,MAAM,UAAU;AACrE,YAAQ,IAAI,mBAAmB,UAAU,YAAY,MAAM,EAAE;AAC7D,YAAQ,IAAI;AAAA,cAAiB,UAAU;AAAA,CAAI;AAAA,EAC7C,SAAS,KAAK;AACZ,YAAQ,MAAM;AAAA,qBAAyB,IAAc,OAAO;AAAA,CAAI;AAChE,YAAQ,WAAW;AAAA,EACrB;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/cli/commands/analyze.ts"],"sourcesContent":["import path from 'node:path';\nimport fs from 'node:fs';\nimport { loadConfig } from '../../config.js';\nimport { getGlobalDir } from '../../paths.js';\nimport { createAIRunner } from '../../ai-runner/index.js';\nimport { analyze } from '../../knowledge/KnowledgeAnalyzer.js';\n\ninterface AnalyzeCommandOptions {\n dir?: string;\n output?: string;\n force?: boolean;\n}\n\nfunction resolveOutputPath(explicitOutput?: string): string {\n if (explicitOutput) return path.resolve(explicitOutput);\n\n // Same search order as .env\n const envConfigPath = process.env.IAF_CONFIG_PATH;\n if (envConfigPath) {\n return path.join(path.dirname(envConfigPath), 'knowledge.json');\n }\n\n const cwdCandidate = path.resolve(process.cwd(), 'knowledge.json');\n const globalCandidate = path.join(getGlobalDir(), 'knowledge.json');\n\n // Prefer cwd if .env exists there, otherwise global\n if (fs.existsSync(path.resolve(process.cwd(), '.env'))) {\n return cwdCandidate;\n }\n\n return globalCandidate;\n}\n\nexport async function analyzeCommand(opts: AnalyzeCommandOptions): Promise<void> {\n const config = loadConfig();\n const workDir = opts.dir ? path.resolve(opts.dir) : config.project.workDir;\n const outputPath = resolveOutputPath(opts.output);\n\n if (fs.existsSync(outputPath) && !opts.force) {\n console.log(`\\n knowledge.json already exists at: ${outputPath}`);\n console.log(' Use --force to overwrite.\\n');\n process.exitCode = 1;\n return;\n }\n\n console.log(`\\n Analyzing project: ${workDir}`);\n console.log(` Output: ${outputPath}\\n`);\n\n const aiRunner = createAIRunner(config.ai);\n\n try {\n const knowledge = await analyze({\n workDir,\n aiRunner,\n outputPath,\n });\n\n console.log(' Analysis complete!\\n');\n console.log(` Language: ${knowledge.structure.primaryLanguage}`);\n console.log(` Frameworks: ${knowledge.structure.frameworks.join(', ') || 'none'}`);\n console.log(` Monorepo: ${knowledge.structure.isMonorepo ? 'yes' : 'no'}`);\n console.log(` Pkg Manager: ${knowledge.toolchain.packageManager}`);\n console.log(` Triggers: ${knowledge.ruleTriggers.length} rule(s)`);\n console.log(` Known Issues: ${knowledge.knownIssues.length}`);\n console.log(`\\n Saved to: ${outputPath}\\n`);\n } catch (err) {\n console.error(`\\n Analysis failed: ${(err as Error).message}\\n`);\n process.exitCode = 1;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA,OAAO,UAAU;AACjB,OAAO,QAAQ;AAYf,SAAS,kBAAkB,gBAAiC;AAC1D,MAAI,eAAgB,QAAO,KAAK,QAAQ,cAAc;AAGtD,QAAM,gBAAgB,QAAQ,IAAI;AAClC,MAAI,eAAe;AACjB,WAAO,KAAK,KAAK,KAAK,QAAQ,aAAa,GAAG,gBAAgB;AAAA,EAChE;AAEA,QAAM,eAAe,KAAK,QAAQ,QAAQ,IAAI,GAAG,gBAAgB;AACjE,QAAM,kBAAkB,KAAK,KAAK,aAAa,GAAG,gBAAgB;AAGlE,MAAI,GAAG,WAAW,KAAK,QAAQ,QAAQ,IAAI,GAAG,MAAM,CAAC,GAAG;AACtD,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEA,eAAsB,eAAe,MAA4C;AAC/E,QAAM,SAAS,WAAW;AAC1B,QAAM,UAAU,KAAK,MAAM,KAAK,QAAQ,KAAK,GAAG,IAAI,OAAO,QAAQ;AACnE,QAAM,aAAa,kBAAkB,KAAK,MAAM;AAEhD,MAAI,GAAG,WAAW,UAAU,KAAK,CAAC,KAAK,OAAO;AAC5C,YAAQ,IAAI;AAAA,sCAAyC,UAAU,EAAE;AACjE,YAAQ,IAAI,+BAA+B;AAC3C,YAAQ,WAAW;AACnB;AAAA,EACF;AAEA,UAAQ,IAAI;AAAA,uBAA0B,OAAO,EAAE;AAC/C,UAAQ,IAAI,aAAa,UAAU;AAAA,CAAI;AAEvC,QAAM,WAAW,eAAe,OAAO,EAAE;AAEzC,MAAI;AACF,UAAM,YAAY,MAAM,QAAQ;AAAA,MAC9B;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAED,YAAQ,IAAI,wBAAwB;AACpC,YAAQ,IAAI,kBAAkB,UAAU,UAAU,eAAe,EAAE;AACnE,YAAQ,IAAI,kBAAkB,UAAU,UAAU,WAAW,KAAK,IAAI,KAAK,MAAM,EAAE;AACnF,YAAQ,IAAI,kBAAkB,UAAU,UAAU,aAAa,QAAQ,IAAI,EAAE;AAC7E,YAAQ,IAAI,kBAAkB,UAAU,UAAU,cAAc,EAAE;AAClE,YAAQ,IAAI,kBAAkB,UAAU,aAAa,MAAM,UAAU;AACrE,YAAQ,IAAI,mBAAmB,UAAU,YAAY,MAAM,EAAE;AAC7D,YAAQ,IAAI;AAAA,cAAiB,UAAU;AAAA,CAAI;AAAA,EAC7C,SAAS,KAAK;AACZ,YAAQ,MAAM;AAAA,qBAAyB,IAAc,OAAO;AAAA,CAAI;AAChE,YAAQ,WAAW;AAAA,EACrB;AACF;","names":[]}
@@ -9,24 +9,26 @@ import {
9
9
  import {
10
10
  BraindumpOrchestrator,
11
11
  BraindumpTracker
12
- } from "./chunk-4QV6D34Y.js";
12
+ } from "./chunk-M5C2WILQ.js";
13
13
  import {
14
14
  AsyncMutex,
15
15
  GitOperations
16
- } from "./chunk-P4O4ZXEC.js";
16
+ } from "./chunk-2YQHKXLL.js";
17
+ import "./chunk-U237JSLB.js";
18
+ import "./chunk-U6GWFTKA.js";
17
19
  import "./chunk-ACVOOHAR.js";
20
+ import "./chunk-B7TVVODN.js";
18
21
  import "./chunk-YCYVNRLF.js";
19
22
  import {
20
23
  loadConfig
21
- } from "./chunk-FWEW5E3B.js";
24
+ } from "./chunk-NZHKAPU6.js";
22
25
  import "./chunk-AKXDQH25.js";
23
- import "./chunk-B7TVVODN.js";
24
26
  import "./chunk-TN2SYADO.js";
25
- import "./chunk-DAX3FD2O.js";
26
- import "./chunk-DADQSKPL.js";
27
27
  import {
28
28
  createAIRunner
29
- } from "./chunk-4LFNFRCL.js";
29
+ } from "./chunk-SAMTXC4A.js";
30
+ import "./chunk-AVGZH64A.js";
31
+ import "./chunk-DAX3FD2O.js";
30
32
  import "./chunk-GF2RRYHB.js";
31
33
 
32
34
  // src/cli/commands/braindump.ts
@@ -205,4 +207,4 @@ ${bold("\u786E\u8BA4\u6267\u884C\uFF1F")} (${green("y")}=\u786E\u8BA4 / ${red("q
205
207
  export {
206
208
  braindumpCommand
207
209
  };
208
- //# sourceMappingURL=braindump-4E5SDMSZ.js.map
210
+ //# sourceMappingURL=braindump-56WAY2RD.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli/commands/braindump.ts"],"sourcesContent":["import { loadConfig } from '../../config.js';\nimport { GitOperations } from '../../git/GitOperations.js';\nimport { createAIRunner } from '../../ai-runner/index.js';\nimport { AsyncMutex } from '../../utils/AsyncMutex.js';\nimport { BraindumpOrchestrator } from '../../braindump/BraindumpOrchestrator.js';\nimport { BraindumpTracker } from '../../braindump/BraindumpTracker.js';\nimport { BatchStatus } from '../../braindump/BraindumpState.js';\nimport { bold, dim, green, red, cyan, buildServiceUrl } from '../utils/format.js';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport fs from 'node:fs';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nexport interface BraindumpOptions {\n file?: string;\n target?: string;\n concurrency?: number;\n runner?: string;\n auto?: boolean;\n port?: string;\n host?: string;\n}\n\nexport async function braindumpCommand(opts: BraindumpOptions): Promise<void> {\n // 1. Try to proxy to running service\n const baseUrl = buildServiceUrl(opts.host || 'localhost', parseInt(opts.port || '3000', 10));\n try {\n const probe = await fetch(`${baseUrl}/api/status`);\n if (probe.ok) {\n await proxyToService(baseUrl, opts);\n return;\n }\n } catch {\n // Service not running, execute locally\n }\n\n console.log(bold('🧠 Braindump Mode — 批量任务拆分与并行执行\\n'));\n\n // 2. Read input\n let rawInput: string;\n if (opts.file) {\n if (!fs.existsSync(opts.file)) {\n console.error(red(`File not found: ${opts.file}`));\n process.exit(1);\n }\n rawInput = fs.readFileSync(opts.file, 'utf-8');\n } else if (!process.stdin.isTTY) {\n // Read from stdin (pipe)\n rawInput = await readStdin();\n } else {\n console.log(dim('请输入你的想法(按 Ctrl+D 结束输入):'));\n rawInput = await readStdin();\n }\n\n if (!rawInput.trim()) {\n console.error(red('输入为空'));\n process.exit(1);\n }\n\n console.log(dim(`\\n输入内容: ${rawInput.length} 字符\\n`));\n\n // 3. Initialize local orchestrator\n const config = loadConfig();\n const dataDir = path.resolve(__dirname, '../../../data');\n if (!fs.existsSync(dataDir)) fs.mkdirSync(dataDir, { recursive: true });\n\n const mainGit = new GitOperations(config.project.gitRootDir);\n const mainGitMutex = new AsyncMutex();\n const aiRunner = createAIRunner(config.ai);\n const tracker = new BraindumpTracker(dataDir);\n\n const orchestrator = new BraindumpOrchestrator(\n config, mainGit, mainGitMutex, aiRunner, tracker,\n );\n\n // 4. Create batch and split\n const batch = orchestrator.createBatch(rawInput, {\n targetBranch: opts.target,\n maxConcurrent: opts.concurrency,\n defaultAiRunnerMode: opts.runner,\n });\n\n console.log(cyan('正在分析输入内容并拆分任务...\\n'));\n\n await orchestrator.splitBatch(batch.id, (_event) => {\n process.stdout.write(dim('.'));\n });\n console.log('\\n');\n\n // 5. Display tasks\n const currentBatch = tracker.getBatch(batch.id)!;\n console.log(bold(`拆分出 ${currentBatch.tasks.length} 个任务:\\n`));\n console.log(formatTaskTable(currentBatch.tasks));\n\n // 6. Confirm\n if (!opts.auto) {\n const readline = await import('node:readline');\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n const answer = await new Promise<string>((resolve) => {\n rl.question(\n `\\n${bold('确认执行?')} (${green('y')}=确认 / ${red('q')}=取消): `,\n resolve,\n );\n });\n rl.close();\n\n if (answer.trim().toLowerCase() !== 'y') {\n console.log(dim('已取消'));\n process.exit(0);\n }\n }\n\n // 7. Execute\n console.log(cyan('\\n开始并行执行...\\n'));\n orchestrator.confirmBatch(batch.id);\n await orchestrator.executeBatch(batch.id);\n\n const finalBatch = tracker.getBatch(batch.id)!;\n if (finalBatch.status === BatchStatus.Completed) {\n console.log(green(bold('\\n✅ 全部任务完成!')));\n console.log(dim(`Integration 分支: ${finalBatch.integrationBranch}`));\n } else {\n console.log(red(bold('\\n❌ 部分任务失败')));\n for (const task of finalBatch.tasks) {\n if (task.lastError) {\n console.log(red(` - ${task.title}: ${task.lastError}`));\n }\n }\n }\n}\n\nfunction formatTaskTable(tasks: { index: number; title: string; dependsOn: string[]; status: string }[]): string {\n const lines = [' # 标题 依赖 状态', ' ─ ───────────────────────────── ────── ──────'];\n for (const task of tasks) {\n const deps = task.dependsOn.length > 0\n ? task.dependsOn.map((_, i) => `#${i}`).join(',')\n : '-';\n const title = task.title.length > 30 ? task.title.slice(0, 27) + '...' : task.title.padEnd(30);\n lines.push(` ${String(task.index).padEnd(3)}${title} ${deps.padEnd(8)}${task.status}`);\n }\n return lines.join('\\n');\n}\n\nasync function readStdin(): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(Buffer.from(chunk));\n }\n return Buffer.concat(chunks).toString('utf-8');\n}\n\nasync function proxyToService(baseUrl: string, opts: BraindumpOptions): Promise<void> {\n console.log(dim(`代理到运行中的服务 (${baseUrl})\\n`));\n\n let rawInput: string;\n if (opts.file) {\n rawInput = fs.readFileSync(opts.file, 'utf-8');\n } else if (!process.stdin.isTTY) {\n rawInput = await readStdin();\n } else {\n console.log(dim('请输入你的想法(按 Ctrl+D 结束输入):'));\n rawInput = await readStdin();\n }\n\n // Create batch via API\n const createRes = await fetch(`${baseUrl}/api/braindump/batches`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n rawInput,\n targetBranch: opts.target,\n maxConcurrent: opts.concurrency,\n defaultAiRunnerMode: opts.runner,\n }),\n });\n const { batch } = await createRes.json() as { batch: { id: string } };\n\n // Split via API (non-streaming for CLI simplicity)\n console.log(cyan('正在拆分任务...'));\n const splitRes = await fetch(`${baseUrl}/api/braindump/batches/${batch.id}/split`, { method: 'POST' });\n\n // Read SSE stream\n if (splitRes.body) {\n const reader = splitRes.body.getReader();\n const decoder = new TextDecoder();\n let done = false;\n while (!done) {\n const { value, done: streamDone } = await reader.read();\n done = streamDone;\n if (value) {\n const text = decoder.decode(value);\n if (text.includes('event: done')) break;\n }\n }\n }\n\n // Get updated batch\n const detailRes = await fetch(`${baseUrl}/api/braindump/batches/${batch.id}`);\n const detail = await detailRes.json() as { batch: { tasks: Array<{ index: number; title: string; dependsOn: string[]; status: string }> } };\n\n console.log(bold(`\\n拆分出 ${detail.batch.tasks.length} 个任务:\\n`));\n console.log(formatTaskTable(detail.batch.tasks));\n\n if (!opts.auto) {\n const readline = await import('node:readline');\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n const answer = await new Promise<string>((resolve) => {\n rl.question(`\\n${bold('确认执行?')} (${green('y')}=确认 / ${red('q')}=取消): `, resolve);\n });\n rl.close();\n if (answer.trim().toLowerCase() !== 'y') {\n console.log(dim('已取消'));\n process.exit(0);\n }\n }\n\n // Confirm and execute\n await fetch(`${baseUrl}/api/braindump/batches/${batch.id}/confirm`, { method: 'POST' });\n console.log(green('\\n执行已启动,可通过 Web UI 查看进度'));\n console.log(dim(`批次 ID: ${batch.id}`));\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/cli/commands/braindump.ts"],"sourcesContent":["import { loadConfig } from '../../config.js';\nimport { GitOperations } from '../../git/GitOperations.js';\nimport { createAIRunner } from '../../ai-runner/index.js';\nimport { AsyncMutex } from '../../utils/AsyncMutex.js';\nimport { BraindumpOrchestrator } from '../../braindump/BraindumpOrchestrator.js';\nimport { BraindumpTracker } from '../../braindump/BraindumpTracker.js';\nimport { BatchStatus } from '../../braindump/BraindumpState.js';\nimport { bold, dim, green, red, cyan, buildServiceUrl } from '../utils/format.js';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport fs from 'node:fs';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nexport interface BraindumpOptions {\n file?: string;\n target?: string;\n concurrency?: number;\n runner?: string;\n auto?: boolean;\n port?: string;\n host?: string;\n}\n\nexport async function braindumpCommand(opts: BraindumpOptions): Promise<void> {\n // 1. Try to proxy to running service\n const baseUrl = buildServiceUrl(opts.host || 'localhost', parseInt(opts.port || '3000', 10));\n try {\n const probe = await fetch(`${baseUrl}/api/status`);\n if (probe.ok) {\n await proxyToService(baseUrl, opts);\n return;\n }\n } catch {\n // Service not running, execute locally\n }\n\n console.log(bold('🧠 Braindump Mode — 批量任务拆分与并行执行\\n'));\n\n // 2. Read input\n let rawInput: string;\n if (opts.file) {\n if (!fs.existsSync(opts.file)) {\n console.error(red(`File not found: ${opts.file}`));\n process.exit(1);\n }\n rawInput = fs.readFileSync(opts.file, 'utf-8');\n } else if (!process.stdin.isTTY) {\n // Read from stdin (pipe)\n rawInput = await readStdin();\n } else {\n console.log(dim('请输入你的想法(按 Ctrl+D 结束输入):'));\n rawInput = await readStdin();\n }\n\n if (!rawInput.trim()) {\n console.error(red('输入为空'));\n process.exit(1);\n }\n\n console.log(dim(`\\n输入内容: ${rawInput.length} 字符\\n`));\n\n // 3. Initialize local orchestrator\n const config = loadConfig();\n const dataDir = path.resolve(__dirname, '../../../data');\n if (!fs.existsSync(dataDir)) fs.mkdirSync(dataDir, { recursive: true });\n\n const mainGit = new GitOperations(config.project.gitRootDir);\n const mainGitMutex = new AsyncMutex();\n const aiRunner = createAIRunner(config.ai);\n const tracker = new BraindumpTracker(dataDir);\n\n const orchestrator = new BraindumpOrchestrator(\n config, mainGit, mainGitMutex, aiRunner, tracker,\n );\n\n // 4. Create batch and split\n const batch = orchestrator.createBatch(rawInput, {\n targetBranch: opts.target,\n maxConcurrent: opts.concurrency,\n defaultAiRunnerMode: opts.runner,\n });\n\n console.log(cyan('正在分析输入内容并拆分任务...\\n'));\n\n await orchestrator.splitBatch(batch.id, (_event) => {\n process.stdout.write(dim('.'));\n });\n console.log('\\n');\n\n // 5. Display tasks\n const currentBatch = tracker.getBatch(batch.id)!;\n console.log(bold(`拆分出 ${currentBatch.tasks.length} 个任务:\\n`));\n console.log(formatTaskTable(currentBatch.tasks));\n\n // 6. Confirm\n if (!opts.auto) {\n const readline = await import('node:readline');\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n const answer = await new Promise<string>((resolve) => {\n rl.question(\n `\\n${bold('确认执行?')} (${green('y')}=确认 / ${red('q')}=取消): `,\n resolve,\n );\n });\n rl.close();\n\n if (answer.trim().toLowerCase() !== 'y') {\n console.log(dim('已取消'));\n process.exit(0);\n }\n }\n\n // 7. Execute\n console.log(cyan('\\n开始并行执行...\\n'));\n orchestrator.confirmBatch(batch.id);\n await orchestrator.executeBatch(batch.id);\n\n const finalBatch = tracker.getBatch(batch.id)!;\n if (finalBatch.status === BatchStatus.Completed) {\n console.log(green(bold('\\n✅ 全部任务完成!')));\n console.log(dim(`Integration 分支: ${finalBatch.integrationBranch}`));\n } else {\n console.log(red(bold('\\n❌ 部分任务失败')));\n for (const task of finalBatch.tasks) {\n if (task.lastError) {\n console.log(red(` - ${task.title}: ${task.lastError}`));\n }\n }\n }\n}\n\nfunction formatTaskTable(tasks: { index: number; title: string; dependsOn: string[]; status: string }[]): string {\n const lines = [' # 标题 依赖 状态', ' ─ ───────────────────────────── ────── ──────'];\n for (const task of tasks) {\n const deps = task.dependsOn.length > 0\n ? task.dependsOn.map((_, i) => `#${i}`).join(',')\n : '-';\n const title = task.title.length > 30 ? task.title.slice(0, 27) + '...' : task.title.padEnd(30);\n lines.push(` ${String(task.index).padEnd(3)}${title} ${deps.padEnd(8)}${task.status}`);\n }\n return lines.join('\\n');\n}\n\nasync function readStdin(): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(Buffer.from(chunk));\n }\n return Buffer.concat(chunks).toString('utf-8');\n}\n\nasync function proxyToService(baseUrl: string, opts: BraindumpOptions): Promise<void> {\n console.log(dim(`代理到运行中的服务 (${baseUrl})\\n`));\n\n let rawInput: string;\n if (opts.file) {\n rawInput = fs.readFileSync(opts.file, 'utf-8');\n } else if (!process.stdin.isTTY) {\n rawInput = await readStdin();\n } else {\n console.log(dim('请输入你的想法(按 Ctrl+D 结束输入):'));\n rawInput = await readStdin();\n }\n\n // Create batch via API\n const createRes = await fetch(`${baseUrl}/api/braindump/batches`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n rawInput,\n targetBranch: opts.target,\n maxConcurrent: opts.concurrency,\n defaultAiRunnerMode: opts.runner,\n }),\n });\n const { batch } = await createRes.json() as { batch: { id: string } };\n\n // Split via API (non-streaming for CLI simplicity)\n console.log(cyan('正在拆分任务...'));\n const splitRes = await fetch(`${baseUrl}/api/braindump/batches/${batch.id}/split`, { method: 'POST' });\n\n // Read SSE stream\n if (splitRes.body) {\n const reader = splitRes.body.getReader();\n const decoder = new TextDecoder();\n let done = false;\n while (!done) {\n const { value, done: streamDone } = await reader.read();\n done = streamDone;\n if (value) {\n const text = decoder.decode(value);\n if (text.includes('event: done')) break;\n }\n }\n }\n\n // Get updated batch\n const detailRes = await fetch(`${baseUrl}/api/braindump/batches/${batch.id}`);\n const detail = await detailRes.json() as { batch: { tasks: Array<{ index: number; title: string; dependsOn: string[]; status: string }> } };\n\n console.log(bold(`\\n拆分出 ${detail.batch.tasks.length} 个任务:\\n`));\n console.log(formatTaskTable(detail.batch.tasks));\n\n if (!opts.auto) {\n const readline = await import('node:readline');\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n const answer = await new Promise<string>((resolve) => {\n rl.question(`\\n${bold('确认执行?')} (${green('y')}=确认 / ${red('q')}=取消): `, resolve);\n });\n rl.close();\n if (answer.trim().toLowerCase() !== 'y') {\n console.log(dim('已取消'));\n process.exit(0);\n }\n }\n\n // Confirm and execute\n await fetch(`${baseUrl}/api/braindump/batches/${batch.id}/confirm`, { method: 'POST' });\n console.log(green('\\n执行已启动,可通过 Web UI 查看进度'));\n console.log(dim(`批次 ID: ${batch.id}`));\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQA,OAAO,UAAU;AACjB,SAAS,qBAAqB;AAC9B,OAAO,QAAQ;AAEf,IAAM,YAAY,KAAK,QAAQ,cAAc,YAAY,GAAG,CAAC;AAY7D,eAAsB,iBAAiB,MAAuC;AAE5E,QAAM,UAAU,gBAAgB,KAAK,QAAQ,aAAa,SAAS,KAAK,QAAQ,QAAQ,EAAE,CAAC;AAC3F,MAAI;AACF,UAAM,QAAQ,MAAM,MAAM,GAAG,OAAO,aAAa;AACjD,QAAI,MAAM,IAAI;AACZ,YAAM,eAAe,SAAS,IAAI;AAClC;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,UAAQ,IAAI,KAAK,sGAAmC,CAAC;AAGrD,MAAI;AACJ,MAAI,KAAK,MAAM;AACb,QAAI,CAAC,GAAG,WAAW,KAAK,IAAI,GAAG;AAC7B,cAAQ,MAAM,IAAI,mBAAmB,KAAK,IAAI,EAAE,CAAC;AACjD,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA,eAAW,GAAG,aAAa,KAAK,MAAM,OAAO;AAAA,EAC/C,WAAW,CAAC,QAAQ,MAAM,OAAO;AAE/B,eAAW,MAAM,UAAU;AAAA,EAC7B,OAAO;AACL,YAAQ,IAAI,IAAI,oGAAyB,CAAC;AAC1C,eAAW,MAAM,UAAU;AAAA,EAC7B;AAEA,MAAI,CAAC,SAAS,KAAK,GAAG;AACpB,YAAQ,MAAM,IAAI,0BAAM,CAAC;AACzB,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,UAAQ,IAAI,IAAI;AAAA,4BAAW,SAAS,MAAM;AAAA,CAAO,CAAC;AAGlD,QAAM,SAAS,WAAW;AAC1B,QAAM,UAAU,KAAK,QAAQ,WAAW,eAAe;AACvD,MAAI,CAAC,GAAG,WAAW,OAAO,EAAG,IAAG,UAAU,SAAS,EAAE,WAAW,KAAK,CAAC;AAEtE,QAAM,UAAU,IAAI,cAAc,OAAO,QAAQ,UAAU;AAC3D,QAAM,eAAe,IAAI,WAAW;AACpC,QAAM,WAAW,eAAe,OAAO,EAAE;AACzC,QAAM,UAAU,IAAI,iBAAiB,OAAO;AAE5C,QAAM,eAAe,IAAI;AAAA,IACvB;AAAA,IAAQ;AAAA,IAAS;AAAA,IAAc;AAAA,IAAU;AAAA,EAC3C;AAGA,QAAM,QAAQ,aAAa,YAAY,UAAU;AAAA,IAC/C,cAAc,KAAK;AAAA,IACnB,eAAe,KAAK;AAAA,IACpB,qBAAqB,KAAK;AAAA,EAC5B,CAAC;AAED,UAAQ,IAAI,KAAK,qFAAoB,CAAC;AAEtC,QAAM,aAAa,WAAW,MAAM,IAAI,CAAC,WAAW;AAClD,YAAQ,OAAO,MAAM,IAAI,GAAG,CAAC;AAAA,EAC/B,CAAC;AACD,UAAQ,IAAI,IAAI;AAGhB,QAAM,eAAe,QAAQ,SAAS,MAAM,EAAE;AAC9C,UAAQ,IAAI,KAAK,sBAAO,aAAa,MAAM,MAAM;AAAA,CAAS,CAAC;AAC3D,UAAQ,IAAI,gBAAgB,aAAa,KAAK,CAAC;AAG/C,MAAI,CAAC,KAAK,MAAM;AACd,UAAM,WAAW,MAAM,OAAO,UAAe;AAC7C,UAAM,KAAK,SAAS,gBAAgB,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,OAAO,CAAC;AACpF,UAAM,SAAS,MAAM,IAAI,QAAgB,CAAC,YAAY;AACpD,SAAG;AAAA,QACD;AAAA,EAAK,KAAK,gCAAO,CAAC,KAAK,MAAM,GAAG,CAAC,mBAAS,IAAI,GAAG,CAAC;AAAA,QAClD;AAAA,MACF;AAAA,IACF,CAAC;AACD,OAAG,MAAM;AAET,QAAI,OAAO,KAAK,EAAE,YAAY,MAAM,KAAK;AACvC,cAAQ,IAAI,IAAI,oBAAK,CAAC;AACtB,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AAGA,UAAQ,IAAI,KAAK,6CAAe,CAAC;AACjC,eAAa,aAAa,MAAM,EAAE;AAClC,QAAM,aAAa,aAAa,MAAM,EAAE;AAExC,QAAM,aAAa,QAAQ,SAAS,MAAM,EAAE;AAC5C,MAAI,WAAW,wCAAkC;AAC/C,YAAQ,IAAI,MAAM,KAAK,qDAAa,CAAC,CAAC;AACtC,YAAQ,IAAI,IAAI,6BAAmB,WAAW,iBAAiB,EAAE,CAAC;AAAA,EACpE,OAAO;AACL,YAAQ,IAAI,IAAI,KAAK,+CAAY,CAAC,CAAC;AACnC,eAAW,QAAQ,WAAW,OAAO;AACnC,UAAI,KAAK,WAAW;AAClB,gBAAQ,IAAI,IAAI,OAAO,KAAK,KAAK,KAAK,KAAK,SAAS,EAAE,CAAC;AAAA,MACzD;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,gBAAgB,OAAwF;AAC/G,QAAM,QAAQ,CAAC,4EAA8C,sQAAoD;AACjH,aAAW,QAAQ,OAAO;AACxB,UAAM,OAAO,KAAK,UAAU,SAAS,IACjC,KAAK,UAAU,IAAI,CAAC,GAAG,MAAM,IAAI,CAAC,EAAE,EAAE,KAAK,GAAG,IAC9C;AACJ,UAAM,QAAQ,KAAK,MAAM,SAAS,KAAK,KAAK,MAAM,MAAM,GAAG,EAAE,IAAI,QAAQ,KAAK,MAAM,OAAO,EAAE;AAC7F,UAAM,KAAK,KAAK,OAAO,KAAK,KAAK,EAAE,OAAO,CAAC,CAAC,GAAG,KAAK,KAAK,KAAK,OAAO,CAAC,CAAC,GAAG,KAAK,MAAM,EAAE;AAAA,EACzF;AACA,SAAO,MAAM,KAAK,IAAI;AACxB;AAEA,eAAe,YAA6B;AAC1C,QAAM,SAAmB,CAAC;AAC1B,mBAAiB,SAAS,QAAQ,OAAO;AACvC,WAAO,KAAK,OAAO,KAAK,KAAK,CAAC;AAAA,EAChC;AACA,SAAO,OAAO,OAAO,MAAM,EAAE,SAAS,OAAO;AAC/C;AAEA,eAAe,eAAe,SAAiB,MAAuC;AACpF,UAAQ,IAAI,IAAI,2DAAc,OAAO;AAAA,CAAK,CAAC;AAE3C,MAAI;AACJ,MAAI,KAAK,MAAM;AACb,eAAW,GAAG,aAAa,KAAK,MAAM,OAAO;AAAA,EAC/C,WAAW,CAAC,QAAQ,MAAM,OAAO;AAC/B,eAAW,MAAM,UAAU;AAAA,EAC7B,OAAO;AACL,YAAQ,IAAI,IAAI,oGAAyB,CAAC;AAC1C,eAAW,MAAM,UAAU;AAAA,EAC7B;AAGA,QAAM,YAAY,MAAM,MAAM,GAAG,OAAO,0BAA0B;AAAA,IAChE,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,IAC9C,MAAM,KAAK,UAAU;AAAA,MACnB;AAAA,MACA,cAAc,KAAK;AAAA,MACnB,eAAe,KAAK;AAAA,MACpB,qBAAqB,KAAK;AAAA,IAC5B,CAAC;AAAA,EACH,CAAC;AACD,QAAM,EAAE,MAAM,IAAI,MAAM,UAAU,KAAK;AAGvC,UAAQ,IAAI,KAAK,yCAAW,CAAC;AAC7B,QAAM,WAAW,MAAM,MAAM,GAAG,OAAO,0BAA0B,MAAM,EAAE,UAAU,EAAE,QAAQ,OAAO,CAAC;AAGrG,MAAI,SAAS,MAAM;AACjB,UAAM,SAAS,SAAS,KAAK,UAAU;AACvC,UAAM,UAAU,IAAI,YAAY;AAChC,QAAI,OAAO;AACX,WAAO,CAAC,MAAM;AACZ,YAAM,EAAE,OAAO,MAAM,WAAW,IAAI,MAAM,OAAO,KAAK;AACtD,aAAO;AACP,UAAI,OAAO;AACT,cAAM,OAAO,QAAQ,OAAO,KAAK;AACjC,YAAI,KAAK,SAAS,aAAa,EAAG;AAAA,MACpC;AAAA,IACF;AAAA,EACF;AAGA,QAAM,YAAY,MAAM,MAAM,GAAG,OAAO,0BAA0B,MAAM,EAAE,EAAE;AAC5E,QAAM,SAAS,MAAM,UAAU,KAAK;AAEpC,UAAQ,IAAI,KAAK;AAAA,qBAAS,OAAO,MAAM,MAAM,MAAM;AAAA,CAAS,CAAC;AAC7D,UAAQ,IAAI,gBAAgB,OAAO,MAAM,KAAK,CAAC;AAE/C,MAAI,CAAC,KAAK,MAAM;AACd,UAAM,WAAW,MAAM,OAAO,UAAe;AAC7C,UAAM,KAAK,SAAS,gBAAgB,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,OAAO,CAAC;AACpF,UAAM,SAAS,MAAM,IAAI,QAAgB,CAAC,YAAY;AACpD,SAAG,SAAS;AAAA,EAAK,KAAK,gCAAO,CAAC,KAAK,MAAM,GAAG,CAAC,mBAAS,IAAI,GAAG,CAAC,oBAAU,OAAO;AAAA,IACjF,CAAC;AACD,OAAG,MAAM;AACT,QAAI,OAAO,KAAK,EAAE,YAAY,MAAM,KAAK;AACvC,cAAQ,IAAI,IAAI,oBAAK,CAAC;AACtB,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AAGA,QAAM,MAAM,GAAG,OAAO,0BAA0B,MAAM,EAAE,YAAY,EAAE,QAAQ,OAAO,CAAC;AACtF,UAAQ,IAAI,MAAM,0FAAyB,CAAC;AAC5C,UAAQ,IAAI,IAAI,oBAAU,MAAM,EAAE,EAAE,CAAC;AACvC;","names":[]}
@@ -6,10 +6,10 @@ import {
6
6
  import {
7
7
  ConfigGenerator,
8
8
  PreflightChecker
9
- } from "./chunk-KTYPZTF4.js";
9
+ } from "./chunk-O3WEV5W3.js";
10
10
  import {
11
11
  resolveConfigFilePath
12
- } from "./chunk-FWEW5E3B.js";
12
+ } from "./chunk-NZHKAPU6.js";
13
13
  import {
14
14
  ensureDir,
15
15
  resolveLogsDir
@@ -110,4 +110,4 @@ async function startDaemon(configPath) {
110
110
  export {
111
111
  startCommand
112
112
  };
113
- //# sourceMappingURL=chunk-ICXB2WP5.js.map
113
+ //# sourceMappingURL=chunk-2MESXJEZ.js.map
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  getProjectKnowledge
3
3
  } from "./chunk-ACVOOHAR.js";
4
- import {
5
- t
6
- } from "./chunk-YCYVNRLF.js";
7
4
  import {
8
5
  KNOWLEDGE_DEFAULTS
9
6
  } from "./chunk-B7TVVODN.js";
7
+ import {
8
+ t
9
+ } from "./chunk-YCYVNRLF.js";
10
10
  import {
11
11
  logger
12
12
  } from "./chunk-GF2RRYHB.js";
@@ -399,13 +399,24 @@ function issueStateCategory(record, lm) {
399
399
  }
400
400
  function issueToExecutableTask(record, lm) {
401
401
  const actionState = lm.resolve(record.state, record.currentPhase);
402
- const phaseStatusMap = lm.derivePhaseStatuses(record.state, record.currentPhase);
403
402
  const phaseDefs = lm.getPhaseDefs();
404
- const phaseProgress = phaseDefs.map((p) => ({
405
- name: p.name,
406
- label: p.label,
407
- status: phaseStatusMap[p.name] ?? "pending"
408
- }));
403
+ let phaseProgress;
404
+ if (record.phaseProgress) {
405
+ phaseProgress = phaseDefs.map((p) => ({
406
+ name: p.name,
407
+ label: p.label,
408
+ status: record.phaseProgress[p.name]?.status ?? "pending",
409
+ startedAt: record.phaseProgress[p.name]?.startedAt,
410
+ completedAt: record.phaseProgress[p.name]?.completedAt
411
+ }));
412
+ } else {
413
+ const phaseStatusMap = lm.derivePhaseStatuses(record.state, record.currentPhase);
414
+ phaseProgress = phaseDefs.map((p) => ({
415
+ name: p.name,
416
+ label: p.label,
417
+ status: phaseStatusMap[p.name] ?? "pending"
418
+ }));
419
+ }
409
420
  return {
410
421
  kind: "issue",
411
422
  taskId: String(getIid(record)),
@@ -719,19 +730,29 @@ E2E \u9A8C\u8BC1\u5FC5\u987B**\u4E25\u683C\u6309\u987A\u5E8F**\u7ECF\u8FC7\u4E09
719
730
 
720
731
  **Gate 2 \u2014 \u5267\u672C\u751F\u6210\u5B8C\u6210\u68C0\u67E5\u70B9**
721
732
  - \u5FC5\u987B\u5148\u626B\u63CF \`uat-scripts/\` \u5DF2\u6709\u811A\u672C\uFF0C\u5224\u65AD\u589E\u91CF\u9700\u6C42
722
- - \u5BF9\u4E8E\u9700\u8981\u65B0\u589E\u7684\u573A\u666F\uFF0C\u5FC5\u987B\u5B8C\u6210\uFF1A\u7F16\u5199 Markdown \u7528\u4F8B \u2192 \u6267\u884C \`scenario-gen\` \u751F\u6210 result.json \u2192 \u57FA\u4E8E result.json \u7F16\u5199 Python \u811A\u672C
723
- - \u4EA7\u51FA\u7269\uFF1A\u6240\u6709\u9700\u8981\u6267\u884C\u7684 .py \u811A\u672C\u6587\u4EF6\uFF08\u5DF2\u6709 + \u65B0\u589E\uFF09\u5FC5\u987B\u5B9E\u9645\u5B58\u5728\u4E8E\u78C1\u76D8\u4E0A
724
- - \u2705 \u9A8C\u8BC1\u65B9\u5F0F\uFF1A\`ls -la\` \u786E\u8BA4\u6BCF\u4E2A\u811A\u672C\u6587\u4EF6\u5B58\u5728
725
- - \u274C \u5982\u679C\u811A\u672C\u6587\u4EF6\u4E0D\u5B58\u5728\u6216\u672A\u751F\u6210\uFF0C\u7981\u6B62\u8FDB\u5165\u9636\u6BB5 3
733
+ - \u5BF9\u4E8E\u9700\u8981\u65B0\u589E\u7684\u573A\u666F\uFF0C\u5FC5\u987B**\u4E25\u683C\u6309\u987A\u5E8F**\u5B8C\u6210\u4EE5\u4E0B\u4E09\u6B65\uFF0C**\u4E0D\u5141\u8BB8\u8DF3\u8FC7\u4EFB\u4F55\u4E00\u6B65**\uFF1A
734
+ 1. **\u7F16\u5199 Markdown \u7528\u4F8B** \u2192 \u751F\u6210 \`uc{ID}_{\u63CF\u8FF0}.md\` \u6587\u4EF6
735
+ 2. **\u6267\u884C scenario-gen** \u2192 \u751F\u6210 \`result.json\`\uFF08\u5305\u542B\u4E3B\u8DEF\u5F84/\u884C\u4E3A\u9A8C\u8BC1/\u89C4\u5219\u9A8C\u8BC1\u5267\u672C\uFF09
736
+ \`\`\`bash
737
+ cd ${vendorDir}/scenario-gen && npx tsx src/cli.ts --from-md <\u7528\u4F8B.md> -o result.json
738
+ \`\`\`
739
+ 3. **\u57FA\u4E8E result.json \u7F16\u5199 Python \u811A\u672C** \u2192 \u6BCF\u4E2A\u5267\u672C\u5BF9\u5E94\u4E00\u4E2A \`.py\` \u811A\u672C
740
+ - \u26D4 **\u7981\u6B62\u8DF3\u8FC7\u5267\u672C\u751F\u6210\u6B65\u9AA4\u76F4\u63A5\u624B\u5199\u811A\u672C**\u2014\u2014\u5373\u4F7F\u573A\u666F\u7B80\u5355\u4E5F\u5FC5\u987B\u8D70\u5B8C Markdown \u7528\u4F8B \u2192 result.json \u2192 \u811A\u672C\u7684\u5B8C\u6574\u6D41\u7A0B
741
+ - \u4EA7\u51FA\u7269\u68C0\u67E5\uFF08**\u4E09\u8005\u7F3A\u4E00\u4E0D\u53EF**\uFF09\uFF1A
742
+ - \u2705 \`.md\` \u7528\u4F8B\u6587\u4EF6\u5B58\u5728
743
+ - \u2705 \`result.json\` \u5267\u672C\u6587\u4EF6\u5B58\u5728\uFF08\u5305\u542B test_scenarios \u548C coverage_report\uFF09
744
+ - \u2705 \`.py\` \u811A\u672C\u6587\u4EF6\u5B58\u5728
745
+ - \u2705 \u9A8C\u8BC1\u65B9\u5F0F\uFF1A\`ls -la\` \u786E\u8BA4\u4E0A\u8FF0\u4E09\u7C7B\u6587\u4EF6\u5168\u90E8\u5B58\u5728
746
+ - \u274C \u5982\u679C\u7F3A\u5C11 .md \u7528\u4F8B\u6216 result.json \u5267\u672C\uFF0C**\u5373\u4F7F .py \u811A\u672C\u5B58\u5728\u4E5F\u4E0D\u5141\u8BB8\u901A\u8FC7 Gate 2**
726
747
  - \u{1F4E6} **\u4E2D\u95F4\u4EA7\u7269\u5F52\u6863**\uFF08Gate 2 \u901A\u8FC7\u540E\u3001\u8FDB\u5165 Gate 3 \u524D\u6267\u884C\uFF09\uFF1A
727
748
  \`\`\`bash
728
749
  mkdir -p ${vendorDir}/outputs/issue-${ctx.issueIid}/scenarios
729
- # \u5C06 Markdown \u7528\u4F8B\u3001scenario-gen \u7684 result.json\u3001\u751F\u6210\u7684 .py \u811A\u672C\u90FD\u590D\u5236\u5230\u4EA7\u7269\u76EE\u5F55
730
- cp <\u7528\u4F8B.md> ${vendorDir}/outputs/issue-${ctx.issueIid}/scenarios/
731
- cp <result.json> ${vendorDir}/outputs/issue-${ctx.issueIid}/scenarios/
732
- cp <\u751F\u6210\u7684\u811A\u672C.py> ${vendorDir}/outputs/issue-${ctx.issueIid}/scenarios/
750
+ # \u53EA\u590D\u5236\u4EE5\u4E0B\u4E09\u7C7B\u6587\u4EF6\uFF0C\u4E0D\u8981\u590D\u5236 config*.json \u7B49\u914D\u7F6E\u6587\u4EF6
751
+ cp <\u7528\u4F8B.md> ${vendorDir}/outputs/issue-${ctx.issueIid}/scenarios/ # Markdown \u7528\u4F8B\u6587\u6863
752
+ cp <result.json> ${vendorDir}/outputs/issue-${ctx.issueIid}/scenarios/ # scenario-gen \u751F\u6210\u7684\u5267\u672C
753
+ cp <\u751F\u6210\u7684\u811A\u672C.py> ${vendorDir}/outputs/issue-${ctx.issueIid}/scenarios/ # \u9A8C\u8BC1\u811A\u672C
733
754
  \`\`\`
734
- \u786E\u4FDD\u6240\u6709\u4E2D\u95F4\u4EA7\u7269\uFF08\u7528\u4F8B \u2192 \u5267\u672C \u2192 \u811A\u672C\uFF09\u90FD\u53EF\u8FFD\u6EAF\u3002
755
+ \u26A0\uFE0F **\u53EA\u5F52\u6863\u4E0A\u8FF0\u4E09\u7C7B\u6587\u4EF6**\uFF08.md \u7528\u4F8B\u3001result.json \u5267\u672C\u3001.py \u811A\u672C\uFF09\uFF0C**\u4E0D\u8981**\u5C06 config.json / config.storytool.json \u7B49\u914D\u7F6E\u6587\u4EF6\u590D\u5236\u5230 scenarios \u76EE\u5F55\u3002
735
756
 
736
757
  **Gate 3 \u2014 \u6267\u884C\u9636\u6BB5**
737
758
  - \u53EA\u6709 Gate 2 \u901A\u8FC7\u540E\u624D\u53EF\u4EE5\u6267\u884C \`python3 ${vendorDir}/main.py${configArg}${outputDirArg} --script <script.py> --headless\`
@@ -895,4 +916,4 @@ export {
895
916
  AsyncMutex,
896
917
  ConflictResolver
897
918
  };
898
- //# sourceMappingURL=chunk-P4O4ZXEC.js.map
919
+ //# sourceMappingURL=chunk-2YQHKXLL.js.map