@generacy-ai/generacy 0.3.3 → 0.4.0
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/README.md +153 -0
- package/dist/cli/commands/cluster/scaffolder.d.ts.map +1 -1
- package/dist/cli/commands/cluster/scaffolder.js +2 -0
- package/dist/cli/commands/cluster/scaffolder.js.map +1 -1
- package/dist/cli/commands/cockpit/advance.d.ts +42 -0
- package/dist/cli/commands/cockpit/advance.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/advance.js +136 -0
- package/dist/cli/commands/cockpit/advance.js.map +1 -0
- package/dist/cli/commands/cockpit/clarification-comment-finder.d.ts +13 -0
- package/dist/cli/commands/cockpit/clarification-comment-finder.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/clarification-comment-finder.js +31 -0
- package/dist/cli/commands/cockpit/clarification-comment-finder.js.map +1 -0
- package/dist/cli/commands/cockpit/code-references.d.ts +27 -0
- package/dist/cli/commands/cockpit/code-references.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/code-references.js +48 -0
- package/dist/cli/commands/cockpit/code-references.js.map +1 -0
- package/dist/cli/commands/cockpit/context.d.ts +90 -0
- package/dist/cli/commands/cockpit/context.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/context.js +280 -0
- package/dist/cli/commands/cockpit/context.js.map +1 -0
- package/dist/cli/commands/cockpit/exit.d.ts +12 -0
- package/dist/cli/commands/cockpit/exit.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/exit.js +18 -0
- package/dist/cli/commands/cockpit/exit.js.map +1 -0
- package/dist/cli/commands/cockpit/gate-vocabulary.d.ts +48 -0
- package/dist/cli/commands/cockpit/gate-vocabulary.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/gate-vocabulary.js +96 -0
- package/dist/cli/commands/cockpit/gate-vocabulary.js.map +1 -0
- package/dist/cli/commands/cockpit/index.d.ts +20 -0
- package/dist/cli/commands/cockpit/index.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/index.js +40 -0
- package/dist/cli/commands/cockpit/index.js.map +1 -0
- package/dist/cli/commands/cockpit/manual-advance-marker.d.ts +18 -0
- package/dist/cli/commands/cockpit/manual-advance-marker.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/manual-advance-marker.js +43 -0
- package/dist/cli/commands/cockpit/manual-advance-marker.js.map +1 -0
- package/dist/cli/commands/cockpit/mcp/errors.d.ts +54 -0
- package/dist/cli/commands/cockpit/mcp/errors.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/mcp/errors.js +190 -0
- package/dist/cli/commands/cockpit/mcp/errors.js.map +1 -0
- package/dist/cli/commands/cockpit/mcp/event-bus-registry.d.ts +59 -0
- package/dist/cli/commands/cockpit/mcp/event-bus-registry.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/mcp/event-bus-registry.js +305 -0
- package/dist/cli/commands/cockpit/mcp/event-bus-registry.js.map +1 -0
- package/dist/cli/commands/cockpit/mcp/event-bus.d.ts +82 -0
- package/dist/cli/commands/cockpit/mcp/event-bus.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/mcp/event-bus.js +230 -0
- package/dist/cli/commands/cockpit/mcp/event-bus.js.map +1 -0
- package/dist/cli/commands/cockpit/mcp/index.d.ts +17 -0
- package/dist/cli/commands/cockpit/mcp/index.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/mcp/index.js +37 -0
- package/dist/cli/commands/cockpit/mcp/index.js.map +1 -0
- package/dist/cli/commands/cockpit/mcp/ref-input.d.ts +52 -0
- package/dist/cli/commands/cockpit/mcp/ref-input.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/mcp/ref-input.js +132 -0
- package/dist/cli/commands/cockpit/mcp/ref-input.js.map +1 -0
- package/dist/cli/commands/cockpit/mcp/schemas.d.ts +287 -0
- package/dist/cli/commands/cockpit/mcp/schemas.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/mcp/schemas.js +84 -0
- package/dist/cli/commands/cockpit/mcp/schemas.js.map +1 -0
- package/dist/cli/commands/cockpit/mcp/server.d.ts +17 -0
- package/dist/cli/commands/cockpit/mcp/server.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/mcp/server.js +62 -0
- package/dist/cli/commands/cockpit/mcp/server.js.map +1 -0
- package/dist/cli/commands/cockpit/mcp/tools/cockpit_advance.d.ts +42 -0
- package/dist/cli/commands/cockpit/mcp/tools/cockpit_advance.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/mcp/tools/cockpit_advance.js +73 -0
- package/dist/cli/commands/cockpit/mcp/tools/cockpit_advance.js.map +1 -0
- package/dist/cli/commands/cockpit/mcp/tools/cockpit_await_events.d.ts +34 -0
- package/dist/cli/commands/cockpit/mcp/tools/cockpit_await_events.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/mcp/tools/cockpit_await_events.js +115 -0
- package/dist/cli/commands/cockpit/mcp/tools/cockpit_await_events.js.map +1 -0
- package/dist/cli/commands/cockpit/mcp/tools/cockpit_context.d.ts +21 -0
- package/dist/cli/commands/cockpit/mcp/tools/cockpit_context.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/mcp/tools/cockpit_context.js +35 -0
- package/dist/cli/commands/cockpit/mcp/tools/cockpit_context.js.map +1 -0
- package/dist/cli/commands/cockpit/mcp/tools/cockpit_merge.d.ts +43 -0
- package/dist/cli/commands/cockpit/mcp/tools/cockpit_merge.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/mcp/tools/cockpit_merge.js +99 -0
- package/dist/cli/commands/cockpit/mcp/tools/cockpit_merge.js.map +1 -0
- package/dist/cli/commands/cockpit/mcp/tools/cockpit_queue.d.ts +43 -0
- package/dist/cli/commands/cockpit/mcp/tools/cockpit_queue.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/mcp/tools/cockpit_queue.js +68 -0
- package/dist/cli/commands/cockpit/mcp/tools/cockpit_queue.js.map +1 -0
- package/dist/cli/commands/cockpit/mcp/tools/cockpit_resume.d.ts +38 -0
- package/dist/cli/commands/cockpit/mcp/tools/cockpit_resume.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/mcp/tools/cockpit_resume.js +79 -0
- package/dist/cli/commands/cockpit/mcp/tools/cockpit_resume.js.map +1 -0
- package/dist/cli/commands/cockpit/mcp/tools/cockpit_status.d.ts +21 -0
- package/dist/cli/commands/cockpit/mcp/tools/cockpit_status.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/mcp/tools/cockpit_status.js +59 -0
- package/dist/cli/commands/cockpit/mcp/tools/cockpit_status.js.map +1 -0
- package/dist/cli/commands/cockpit/merge.d.ts +42 -0
- package/dist/cli/commands/cockpit/merge.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/merge.js +360 -0
- package/dist/cli/commands/cockpit/merge.js.map +1 -0
- package/dist/cli/commands/cockpit/plan-dependency-extractor.d.ts +30 -0
- package/dist/cli/commands/cockpit/plan-dependency-extractor.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/plan-dependency-extractor.js +135 -0
- package/dist/cli/commands/cockpit/plan-dependency-extractor.js.map +1 -0
- package/dist/cli/commands/cockpit/queue.d.ts +85 -0
- package/dist/cli/commands/cockpit/queue.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/queue.js +438 -0
- package/dist/cli/commands/cockpit/queue.js.map +1 -0
- package/dist/cli/commands/cockpit/resolver.d.ts +70 -0
- package/dist/cli/commands/cockpit/resolver.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/resolver.js +117 -0
- package/dist/cli/commands/cockpit/resolver.js.map +1 -0
- package/dist/cli/commands/cockpit/resume.d.ts +38 -0
- package/dist/cli/commands/cockpit/resume.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/resume.js +167 -0
- package/dist/cli/commands/cockpit/resume.js.map +1 -0
- package/dist/cli/commands/cockpit/shared/classify-issue.d.ts +12 -0
- package/dist/cli/commands/cockpit/shared/classify-issue.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/shared/classify-issue.js +10 -0
- package/dist/cli/commands/cockpit/shared/classify-issue.js.map +1 -0
- package/dist/cli/commands/cockpit/shared/failing-check-json.d.ts +53 -0
- package/dist/cli/commands/cockpit/shared/failing-check-json.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/shared/failing-check-json.js +170 -0
- package/dist/cli/commands/cockpit/shared/failing-check-json.js.map +1 -0
- package/dist/cli/commands/cockpit/shared/identity.d.ts +54 -0
- package/dist/cli/commands/cockpit/shared/identity.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/shared/identity.js +65 -0
- package/dist/cli/commands/cockpit/shared/identity.js.map +1 -0
- package/dist/cli/commands/cockpit/shared/is-done-snapshot.d.ts +16 -0
- package/dist/cli/commands/cockpit/shared/is-done-snapshot.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/shared/is-done-snapshot.js +17 -0
- package/dist/cli/commands/cockpit/shared/is-done-snapshot.js.map +1 -0
- package/dist/cli/commands/cockpit/shared/pagination.d.ts +17 -0
- package/dist/cli/commands/cockpit/shared/pagination.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/shared/pagination.js +50 -0
- package/dist/cli/commands/cockpit/shared/pagination.js.map +1 -0
- package/dist/cli/commands/cockpit/shared/pr-link.d.ts +8 -0
- package/dist/cli/commands/cockpit/shared/pr-link.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/shared/pr-link.js +15 -0
- package/dist/cli/commands/cockpit/shared/pr-link.js.map +1 -0
- package/dist/cli/commands/cockpit/shared/required-checks.d.ts +17 -0
- package/dist/cli/commands/cockpit/shared/required-checks.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/shared/required-checks.js +38 -0
- package/dist/cli/commands/cockpit/shared/required-checks.js.map +1 -0
- package/dist/cli/commands/cockpit/shared/review-context-json.d.ts +29 -0
- package/dist/cli/commands/cockpit/shared/review-context-json.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/shared/review-context-json.js +28 -0
- package/dist/cli/commands/cockpit/shared/review-context-json.js.map +1 -0
- package/dist/cli/commands/cockpit/status/color.d.ts +11 -0
- package/dist/cli/commands/cockpit/status/color.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/status/color.js +33 -0
- package/dist/cli/commands/cockpit/status/color.js.map +1 -0
- package/dist/cli/commands/cockpit/status/group.d.ts +8 -0
- package/dist/cli/commands/cockpit/status/group.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/status/group.js +35 -0
- package/dist/cli/commands/cockpit/status/group.js.map +1 -0
- package/dist/cli/commands/cockpit/status/render-table.d.ts +24 -0
- package/dist/cli/commands/cockpit/status/render-table.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/status/render-table.js +71 -0
- package/dist/cli/commands/cockpit/status/render-table.js.map +1 -0
- package/dist/cli/commands/cockpit/status/row.d.ts +18 -0
- package/dist/cli/commands/cockpit/status/row.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/status/row.js +17 -0
- package/dist/cli/commands/cockpit/status/row.js.map +1 -0
- package/dist/cli/commands/cockpit/status.d.ts +18 -0
- package/dist/cli/commands/cockpit/status.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/status.js +138 -0
- package/dist/cli/commands/cockpit/status.js.map +1 -0
- package/dist/cli/commands/cockpit/watch/actionable.d.ts +15 -0
- package/dist/cli/commands/cockpit/watch/actionable.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/watch/actionable.js +32 -0
- package/dist/cli/commands/cockpit/watch/actionable.js.map +1 -0
- package/dist/cli/commands/cockpit/watch/aggregate-emit.d.ts +107 -0
- package/dist/cli/commands/cockpit/watch/aggregate-emit.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/watch/aggregate-emit.js +41 -0
- package/dist/cli/commands/cockpit/watch/aggregate-emit.js.map +1 -0
- package/dist/cli/commands/cockpit/watch/aggregate.d.ts +25 -0
- package/dist/cli/commands/cockpit/watch/aggregate.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/watch/aggregate.js +67 -0
- package/dist/cli/commands/cockpit/watch/aggregate.js.map +1 -0
- package/dist/cli/commands/cockpit/watch/check-rollup.d.ts +9 -0
- package/dist/cli/commands/cockpit/watch/check-rollup.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/watch/check-rollup.js +22 -0
- package/dist/cli/commands/cockpit/watch/check-rollup.js.map +1 -0
- package/dist/cli/commands/cockpit/watch/diff.d.ts +29 -0
- package/dist/cli/commands/cockpit/watch/diff.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/watch/diff.js +85 -0
- package/dist/cli/commands/cockpit/watch/diff.js.map +1 -0
- package/dist/cli/commands/cockpit/watch/emit.d.ts +58 -0
- package/dist/cli/commands/cockpit/watch/emit.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/watch/emit.js +30 -0
- package/dist/cli/commands/cockpit/watch/emit.js.map +1 -0
- package/dist/cli/commands/cockpit/watch/poll-loop.d.ts +29 -0
- package/dist/cli/commands/cockpit/watch/poll-loop.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/watch/poll-loop.js +81 -0
- package/dist/cli/commands/cockpit/watch/poll-loop.js.map +1 -0
- package/dist/cli/commands/cockpit/watch/pr-state.d.ts +17 -0
- package/dist/cli/commands/cockpit/watch/pr-state.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/watch/pr-state.js +33 -0
- package/dist/cli/commands/cockpit/watch/pr-state.js.map +1 -0
- package/dist/cli/commands/cockpit/watch/snapshot.d.ts +33 -0
- package/dist/cli/commands/cockpit/watch/snapshot.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/watch/snapshot.js +30 -0
- package/dist/cli/commands/cockpit/watch/snapshot.js.map +1 -0
- package/dist/cli/commands/cockpit/watch/stream-event.d.ts +82 -0
- package/dist/cli/commands/cockpit/watch/stream-event.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/watch/stream-event.js +9 -0
- package/dist/cli/commands/cockpit/watch/stream-event.js.map +1 -0
- package/dist/cli/commands/cockpit/watch.d.ts +22 -0
- package/dist/cli/commands/cockpit/watch.d.ts.map +1 -0
- package/dist/cli/commands/cockpit/watch.js +186 -0
- package/dist/cli/commands/cockpit/watch.js.map +1 -0
- package/dist/cli/commands/setup/build.d.ts.map +1 -1
- package/dist/cli/commands/setup/build.js +59 -0
- package/dist/cli/commands/setup/build.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +2 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/package.json +11 -5
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `generacy cockpit resume <issue>` — re-arm a failed phase in place.
|
|
3
|
+
*
|
|
4
|
+
* Engine-owned label surgery: on an issue carrying `failed:<phase>` (with or
|
|
5
|
+
* without `agent:error`), applies the additions `waiting-for:<preceding-gate>`
|
|
6
|
+
* + `completed:<preceding-gate>` + `agent:paused` FIRST, then removes
|
|
7
|
+
* `failed:<phase>` plus defensive `agent:error` / `phase:<phase>` when
|
|
8
|
+
* present. The terminal on-issue state is byte-identical to a
|
|
9
|
+
* naturally-paused-then-completed gate — the label monitor's next poll emits
|
|
10
|
+
* a resume event, and the worker's `PhaseResolver.resolveFromContinue` walks
|
|
11
|
+
* the preserved `completed:<earlier-phase>` chain to pick `<phase>` as the
|
|
12
|
+
* start phase.
|
|
13
|
+
*
|
|
14
|
+
* Side effects (in order):
|
|
15
|
+
* 1. gh addLabels [waiting-for:<G>, completed:<G>, agent:paused]
|
|
16
|
+
* 2. gh removeLabels [failed:<phase>, ...conditional]
|
|
17
|
+
*
|
|
18
|
+
* Idempotent (FR-003): no `failed:*` → no-op with single-line stdout, exit 0.
|
|
19
|
+
* Refuses (FR-004) with evidence and zero mutations when the state is
|
|
20
|
+
* ambiguous or non-re-armable. No `--force` in v1 (parity with `advance`).
|
|
21
|
+
*/
|
|
22
|
+
import { Command } from 'commander';
|
|
23
|
+
import { loadCockpitConfig, type CommandRunner, type GhWrapper } from '@generacy-ai/cockpit';
|
|
24
|
+
export interface ResumeCommandDeps {
|
|
25
|
+
runner?: CommandRunner;
|
|
26
|
+
gh?: GhWrapper;
|
|
27
|
+
loadConfig?: typeof loadCockpitConfig;
|
|
28
|
+
env?: NodeJS.ProcessEnv;
|
|
29
|
+
now?: () => Date;
|
|
30
|
+
stdout?: (line: string) => void;
|
|
31
|
+
stderr?: (line: string) => void;
|
|
32
|
+
}
|
|
33
|
+
export interface ResumeOptions {
|
|
34
|
+
workflow?: string;
|
|
35
|
+
}
|
|
36
|
+
export declare function resumeCommand(deps?: ResumeCommandDeps): Command;
|
|
37
|
+
export declare function runResume(issue: string | undefined, opts: ResumeOptions, deps: ResumeCommandDeps): Promise<void>;
|
|
38
|
+
//# sourceMappingURL=resume.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resume.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/cockpit/resume.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EACL,iBAAiB,EACjB,KAAK,aAAa,EAClB,KAAK,SAAS,EACf,MAAM,sBAAsB,CAAC;AAO9B,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,EAAE,CAAC,EAAE,SAAS,CAAC;IACf,UAAU,CAAC,EAAE,OAAO,iBAAiB,CAAC;IACtC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IACjB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAwFD,wBAAgB,aAAa,CAAC,IAAI,GAAE,iBAAsB,GAAG,OAAO,CAmBnE;AAED,wBAAsB,SAAS,CAC7B,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,IAAI,EAAE,aAAa,EACnB,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,IAAI,CAAC,CA2Ff"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `generacy cockpit resume <issue>` — re-arm a failed phase in place.
|
|
3
|
+
*
|
|
4
|
+
* Engine-owned label surgery: on an issue carrying `failed:<phase>` (with or
|
|
5
|
+
* without `agent:error`), applies the additions `waiting-for:<preceding-gate>`
|
|
6
|
+
* + `completed:<preceding-gate>` + `agent:paused` FIRST, then removes
|
|
7
|
+
* `failed:<phase>` plus defensive `agent:error` / `phase:<phase>` when
|
|
8
|
+
* present. The terminal on-issue state is byte-identical to a
|
|
9
|
+
* naturally-paused-then-completed gate — the label monitor's next poll emits
|
|
10
|
+
* a resume event, and the worker's `PhaseResolver.resolveFromContinue` walks
|
|
11
|
+
* the preserved `completed:<earlier-phase>` chain to pick `<phase>` as the
|
|
12
|
+
* start phase.
|
|
13
|
+
*
|
|
14
|
+
* Side effects (in order):
|
|
15
|
+
* 1. gh addLabels [waiting-for:<G>, completed:<G>, agent:paused]
|
|
16
|
+
* 2. gh removeLabels [failed:<phase>, ...conditional]
|
|
17
|
+
*
|
|
18
|
+
* Idempotent (FR-003): no `failed:*` → no-op with single-line stdout, exit 0.
|
|
19
|
+
* Refuses (FR-004) with evidence and zero mutations when the state is
|
|
20
|
+
* ambiguous or non-re-armable. No `--force` in v1 (parity with `advance`).
|
|
21
|
+
*/
|
|
22
|
+
import { Command } from 'commander';
|
|
23
|
+
import { loadCockpitConfig, } from '@generacy-ai/cockpit';
|
|
24
|
+
import { getLogger } from '../../utils/logger.js';
|
|
25
|
+
import { resolveIssueContext } from './resolver.js';
|
|
26
|
+
import { resolvePrecedingGate } from './gate-vocabulary.js';
|
|
27
|
+
import { CockpitExit, isCockpitExit } from './exit.js';
|
|
28
|
+
const KNOWN_PHASES = [
|
|
29
|
+
'specify',
|
|
30
|
+
'clarify',
|
|
31
|
+
'plan',
|
|
32
|
+
'tasks',
|
|
33
|
+
'implement',
|
|
34
|
+
'validate',
|
|
35
|
+
];
|
|
36
|
+
function isKnownPhase(candidate) {
|
|
37
|
+
return KNOWN_PHASES.includes(candidate);
|
|
38
|
+
}
|
|
39
|
+
function resolveWorkflowFromLabels(labels) {
|
|
40
|
+
const workflowLabel = labels.find((l) => l.startsWith('workflow:'));
|
|
41
|
+
if (workflowLabel) {
|
|
42
|
+
return workflowLabel.slice('workflow:'.length);
|
|
43
|
+
}
|
|
44
|
+
return 'speckit-feature';
|
|
45
|
+
}
|
|
46
|
+
function classify(labels, workflowOverride) {
|
|
47
|
+
const failedLabels = labels.filter((l) => l.startsWith('failed:')).sort();
|
|
48
|
+
if (failedLabels.length === 0) {
|
|
49
|
+
return { kind: 'no-op' };
|
|
50
|
+
}
|
|
51
|
+
if (failedLabels.length > 1) {
|
|
52
|
+
return { kind: 'refuse-multiple-failed', failedLabels };
|
|
53
|
+
}
|
|
54
|
+
const failedLabel = failedLabels[0];
|
|
55
|
+
const phaseSuffix = failedLabel.slice('failed:'.length);
|
|
56
|
+
if (!isKnownPhase(phaseSuffix)) {
|
|
57
|
+
return { kind: 'refuse-unknown-phase', failedLabel, phaseSuffix };
|
|
58
|
+
}
|
|
59
|
+
const failedPhase = phaseSuffix;
|
|
60
|
+
const workflowName = workflowOverride ?? resolveWorkflowFromLabels(labels);
|
|
61
|
+
const gateResult = resolvePrecedingGate(failedPhase, workflowName);
|
|
62
|
+
if (gateResult.kind === 'no-preceding-gate') {
|
|
63
|
+
return { kind: 'refuse-no-preceding-gate', failedPhase, workflowName };
|
|
64
|
+
}
|
|
65
|
+
const gate = gateResult.gate;
|
|
66
|
+
const conflictingWaiting = labels.find((l) => l.startsWith('waiting-for:') && l !== gate.waitingLabel);
|
|
67
|
+
if (conflictingWaiting) {
|
|
68
|
+
return {
|
|
69
|
+
kind: 'refuse-conflicting-waiting',
|
|
70
|
+
failedPhase,
|
|
71
|
+
conflictingLabel: conflictingWaiting,
|
|
72
|
+
expectedLabel: gate.waitingLabel,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
const labelsToAdd = [gate.waitingLabel, gate.completedLabel, 'agent:paused'];
|
|
76
|
+
const labelsToRemove = [failedLabel];
|
|
77
|
+
if (labels.includes('agent:error'))
|
|
78
|
+
labelsToRemove.push('agent:error');
|
|
79
|
+
const phaseLabel = `phase:${failedPhase}`;
|
|
80
|
+
if (labels.includes(phaseLabel))
|
|
81
|
+
labelsToRemove.push(phaseLabel);
|
|
82
|
+
return { kind: 'happy-path', failedPhase, gate, labelsToAdd, labelsToRemove };
|
|
83
|
+
}
|
|
84
|
+
export function resumeCommand(deps = {}) {
|
|
85
|
+
const cmd = new Command('resume');
|
|
86
|
+
cmd
|
|
87
|
+
.description('Re-arm a failed phase in place so the next poll re-runs it.')
|
|
88
|
+
.argument('[issue]', 'Issue ref — <number>, <owner>/<repo>#<n>, or full URL.')
|
|
89
|
+
.option('--workflow <name>', 'Workflow name override (defaults to the issue\'s workflow:<name> label).')
|
|
90
|
+
.action(async (issue, opts) => {
|
|
91
|
+
try {
|
|
92
|
+
await runResume(issue, opts, deps);
|
|
93
|
+
}
|
|
94
|
+
catch (err) {
|
|
95
|
+
if (isCockpitExit(err)) {
|
|
96
|
+
const stderr = deps.stderr ?? ((line) => process.stderr.write(`${line}\n`));
|
|
97
|
+
stderr(err.message);
|
|
98
|
+
process.exit(err.code);
|
|
99
|
+
}
|
|
100
|
+
throw err;
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
return cmd;
|
|
104
|
+
}
|
|
105
|
+
export async function runResume(issue, opts, deps) {
|
|
106
|
+
const log = getLogger();
|
|
107
|
+
const print = deps.stdout ?? ((line) => process.stdout.write(`${line}\n`));
|
|
108
|
+
if (issue == null || issue.trim() === '') {
|
|
109
|
+
throw new CockpitExit(2, 'Error: cockpit resume: missing required argument <issue>');
|
|
110
|
+
}
|
|
111
|
+
const loaded = await (deps.loadConfig ?? loadCockpitConfig)({});
|
|
112
|
+
for (const w of loaded.warnings)
|
|
113
|
+
log.warn(w);
|
|
114
|
+
let ref;
|
|
115
|
+
let gh;
|
|
116
|
+
try {
|
|
117
|
+
const resolvedCtx = await resolveIssueContext({ issue, runner: deps.runner });
|
|
118
|
+
ref = resolvedCtx.ref;
|
|
119
|
+
gh = deps.gh ?? resolvedCtx.gh;
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
throw new CockpitExit(2, `Error: cockpit resume: ${err.message}`);
|
|
123
|
+
}
|
|
124
|
+
let labels;
|
|
125
|
+
try {
|
|
126
|
+
labels = (await gh.fetchIssueLabels(ref.nwo, ref.number)).labels;
|
|
127
|
+
}
|
|
128
|
+
catch (err) {
|
|
129
|
+
throw new CockpitExit(1, `Error: cockpit resume: gh issue view: ${err.message}`);
|
|
130
|
+
}
|
|
131
|
+
const decision = classify(labels, opts.workflow);
|
|
132
|
+
switch (decision.kind) {
|
|
133
|
+
case 'no-op':
|
|
134
|
+
print(`issue ${ref.nwo}#${ref.number} is not in a failed state (no failed:<phase> label); nothing to re-arm`);
|
|
135
|
+
return;
|
|
136
|
+
case 'refuse-multiple-failed':
|
|
137
|
+
throw new CockpitExit(3, `Error: cockpit resume: refusing to resume: multiple failed:* labels present: [${decision.failedLabels.join(', ')}]`);
|
|
138
|
+
case 'refuse-unknown-phase':
|
|
139
|
+
throw new CockpitExit(3, `Error: cockpit resume: refusing to resume: unknown phase "${decision.phaseSuffix}" in label "${decision.failedLabel}"`);
|
|
140
|
+
case 'refuse-no-preceding-gate':
|
|
141
|
+
throw new CockpitExit(3, `Error: cockpit resume: refusing to resume: phase "${decision.failedPhase}" has no preceding gate; ` +
|
|
142
|
+
`use \`process:${decision.workflowName}\` label to re-queue from the beginning instead`);
|
|
143
|
+
case 'refuse-conflicting-waiting':
|
|
144
|
+
throw new CockpitExit(3, `Error: cockpit resume: refusing to resume: conflicting ${decision.conflictingLabel} already present; ` +
|
|
145
|
+
`derived preceding-gate is ${decision.expectedLabel.slice('waiting-for:'.length)}`);
|
|
146
|
+
case 'happy-path': {
|
|
147
|
+
try {
|
|
148
|
+
await gh.addLabels(ref.nwo, ref.number, decision.labelsToAdd);
|
|
149
|
+
}
|
|
150
|
+
catch (err) {
|
|
151
|
+
throw new CockpitExit(1, `Error: cockpit resume: gh issue edit (add ${decision.labelsToAdd.join(',')}): ${err.message}`);
|
|
152
|
+
}
|
|
153
|
+
try {
|
|
154
|
+
await gh.removeLabels(ref.nwo, ref.number, decision.labelsToRemove);
|
|
155
|
+
}
|
|
156
|
+
catch (err) {
|
|
157
|
+
throw new CockpitExit(1, `Error: cockpit resume: gh issue edit (remove ${decision.labelsToRemove.join(',')}): ${err.message}`);
|
|
158
|
+
}
|
|
159
|
+
print(`resumed ${ref.nwo}#${ref.number}: re-armed phase=${decision.failedPhase} ` +
|
|
160
|
+
`via preceding-gate=${decision.gate.name}; ` +
|
|
161
|
+
`added=[${decision.labelsToAdd.join(',')}] ` +
|
|
162
|
+
`removed=[${decision.labelsToRemove.join(',')}]`);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=resume.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resume.js","sourceRoot":"","sources":["../../../../src/cli/commands/cockpit/resume.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { CockpitState } from '@generacy-ai/cockpit';
|
|
2
|
+
export interface ClassifiedIssue {
|
|
3
|
+
state: CockpitState;
|
|
4
|
+
sourceLabel: string;
|
|
5
|
+
labels: string[];
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Thin wrapper over `classify(labels)` — always returns `{ state, sourceLabel, labels }`
|
|
9
|
+
* with `labels` preserved alongside the classification.
|
|
10
|
+
*/
|
|
11
|
+
export declare function classifyIssue(labels: string[]): ClassifiedIssue;
|
|
12
|
+
//# sourceMappingURL=classify-issue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classify-issue.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/cockpit/shared/classify-issue.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGzD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,YAAY,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,eAAe,CAG/D"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { classify } from '@generacy-ai/cockpit';
|
|
2
|
+
/**
|
|
3
|
+
* Thin wrapper over `classify(labels)` — always returns `{ state, sourceLabel, labels }`
|
|
4
|
+
* with `labels` preserved alongside the classification.
|
|
5
|
+
*/
|
|
6
|
+
export function classifyIssue(labels) {
|
|
7
|
+
const { state, sourceLabel } = classify(labels);
|
|
8
|
+
return { state, sourceLabel, labels: [...labels] };
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=classify-issue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classify-issue.js","sourceRoot":"","sources":["../../../../../src/cli/commands/cockpit/shared/classify-issue.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAQhD;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,MAAgB;IAC5C,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;IAChD,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC;AACrD,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { LinkMethod, PrCandidate } from '@generacy-ai/cockpit';
|
|
2
|
+
import type { FailingCheck } from './required-checks.js';
|
|
3
|
+
export type { LinkMethod, PrCandidate } from '@generacy-ai/cockpit';
|
|
4
|
+
export type RedReason = 'checks-failing' | 'missing-label' | 'unresolved' | 'pr-is-draft' | 'ambiguous-resolution' | 'pr-flag-linkage-refused' | 'pr-flag-closed-unmerged' | 'pr-number';
|
|
5
|
+
/** FR-006a — sub-kind for `pr-flag-linkage-refused` refusals. */
|
|
6
|
+
export type PrFlagLinkageKind = 'empty-refs' | 'mismatch';
|
|
7
|
+
export interface IssueRefWithState {
|
|
8
|
+
owner: string;
|
|
9
|
+
repo: string;
|
|
10
|
+
number: number;
|
|
11
|
+
state?: 'OPEN' | 'CLOSED';
|
|
12
|
+
stateReason?: string | null;
|
|
13
|
+
}
|
|
14
|
+
export interface FailingCheckPayload {
|
|
15
|
+
status: 'red';
|
|
16
|
+
reason: RedReason;
|
|
17
|
+
pr: {
|
|
18
|
+
number: number;
|
|
19
|
+
url: string;
|
|
20
|
+
linkMethod?: LinkMethod;
|
|
21
|
+
} | null;
|
|
22
|
+
candidates?: PrCandidate[];
|
|
23
|
+
linkMethod?: LinkMethod;
|
|
24
|
+
failingChecks: FailingCheck[];
|
|
25
|
+
issue?: IssueRefWithState;
|
|
26
|
+
/** FR-006a — sub-kind for `pr-flag-linkage-refused` refusals. */
|
|
27
|
+
kind?: PrFlagLinkageKind;
|
|
28
|
+
/** Human-readable remediation string for pr-flag refusals. */
|
|
29
|
+
message?: string;
|
|
30
|
+
/** #928 — human-readable remediation string for `reason: 'pr-number'`. */
|
|
31
|
+
hint?: string;
|
|
32
|
+
}
|
|
33
|
+
export interface BuildFailingCheckInput {
|
|
34
|
+
reason: RedReason;
|
|
35
|
+
pr: {
|
|
36
|
+
number: number;
|
|
37
|
+
url: string;
|
|
38
|
+
linkMethod?: LinkMethod;
|
|
39
|
+
} | null;
|
|
40
|
+
candidates?: PrCandidate[];
|
|
41
|
+
linkMethod?: LinkMethod;
|
|
42
|
+
failingChecks?: FailingCheck[];
|
|
43
|
+
issue?: IssueRefWithState;
|
|
44
|
+
/** Only for `pr-flag-linkage-refused`. */
|
|
45
|
+
kind?: PrFlagLinkageKind;
|
|
46
|
+
/** Only for `pr-flag-linkage-refused` and `pr-flag-closed-unmerged`. */
|
|
47
|
+
message?: string;
|
|
48
|
+
/** #928 — required for `reason: 'pr-number'`. Guidance copy for the caller. */
|
|
49
|
+
hint?: string;
|
|
50
|
+
}
|
|
51
|
+
export declare function buildFailingCheckPayload(input: BuildFailingCheckInput): FailingCheckPayload;
|
|
52
|
+
export declare function serializeFailingCheckJson(payload: FailingCheckPayload): string;
|
|
53
|
+
//# sourceMappingURL=failing-check-json.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"failing-check-json.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/cockpit/shared/failing-check-json.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAEpE,MAAM,MAAM,SAAS,GACjB,gBAAgB,GAChB,eAAe,GACf,YAAY,GACZ,aAAa,GACb,sBAAsB,GACtB,yBAAyB,GACzB,yBAAyB,GACzB,WAAW,CAAC;AAEhB,iEAAiE;AACjE,MAAM,MAAM,iBAAiB,GAAG,YAAY,GAAG,UAAU,CAAC;AAE1D,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,KAAK,CAAC;IACd,MAAM,EAAE,SAAS,CAAC;IAClB,EAAE,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,UAAU,CAAA;KAAE,GAAG,IAAI,CAAC;IACpE,UAAU,CAAC,EAAE,WAAW,EAAE,CAAC;IAC3B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,KAAK,CAAC,EAAE,iBAAiB,CAAC;IAC1B,iEAAiE;IACjE,IAAI,CAAC,EAAE,iBAAiB,CAAC;IACzB,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0EAA0E;IAC1E,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,SAAS,CAAC;IAClB,EAAE,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,UAAU,CAAA;KAAE,GAAG,IAAI,CAAC;IACpE,UAAU,CAAC,EAAE,WAAW,EAAE,CAAC;IAC3B,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,aAAa,CAAC,EAAE,YAAY,EAAE,CAAC;IAC/B,KAAK,CAAC,EAAE,iBAAiB,CAAC;IAC1B,0CAA0C;IAC1C,IAAI,CAAC,EAAE,iBAAiB,CAAC;IACzB,wEAAwE;IACxE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+EAA+E;IAC/E,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,sBAAsB,GAC5B,mBAAmB,CA2OrB;AAED,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,mBAAmB,GAC3B,MAAM,CAER"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
export function buildFailingCheckPayload(input) {
|
|
2
|
+
const { reason, pr, candidates, linkMethod, failingChecks = [], issue, kind, message, hint } = input;
|
|
3
|
+
if (issue !== undefined) {
|
|
4
|
+
// I-6: state and stateReason are paired — if state is set, stateReason
|
|
5
|
+
// must also be present (may be null). Guards against callers accidentally
|
|
6
|
+
// dropping stateReason when they intend to carry state.
|
|
7
|
+
const hasState = 'state' in issue;
|
|
8
|
+
const hasStateReason = 'stateReason' in issue;
|
|
9
|
+
if (hasState !== hasStateReason) {
|
|
10
|
+
throw new Error("FailingCheckPayload invariant I-6: issue.state and issue.stateReason must be set together");
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
const applyIssue = (payload) => issue === undefined ? payload : { ...payload, issue };
|
|
14
|
+
// I-10/I-11: `candidates` and top-level `linkMethod` MUST NOT be set for
|
|
15
|
+
// single-PR reasons.
|
|
16
|
+
const isSinglePrReason = reason === 'unresolved' ||
|
|
17
|
+
reason === 'missing-label' ||
|
|
18
|
+
reason === 'checks-failing' ||
|
|
19
|
+
reason === 'pr-flag-linkage-refused' ||
|
|
20
|
+
reason === 'pr-flag-closed-unmerged' ||
|
|
21
|
+
reason === 'pr-number';
|
|
22
|
+
if (isSinglePrReason && candidates !== undefined) {
|
|
23
|
+
throw new Error(`FailingCheckPayload invariant I-10: candidates MUST NOT be set for reason='${reason}'`);
|
|
24
|
+
}
|
|
25
|
+
if (isSinglePrReason && linkMethod !== undefined) {
|
|
26
|
+
throw new Error(`FailingCheckPayload invariant I-11: top-level linkMethod MUST NOT be set for reason='${reason}'`);
|
|
27
|
+
}
|
|
28
|
+
if (reason === 'unresolved') {
|
|
29
|
+
if (failingChecks.length !== 0) {
|
|
30
|
+
throw new Error("FailingCheckPayload invariant: reason='unresolved' must have empty failingChecks");
|
|
31
|
+
}
|
|
32
|
+
return applyIssue({ status: 'red', reason, pr, failingChecks: [] });
|
|
33
|
+
}
|
|
34
|
+
if (reason === 'missing-label') {
|
|
35
|
+
if (pr == null) {
|
|
36
|
+
throw new Error("FailingCheckPayload invariant: reason='missing-label' requires non-null pr");
|
|
37
|
+
}
|
|
38
|
+
if (pr.linkMethod === undefined) {
|
|
39
|
+
throw new Error("FailingCheckPayload invariant I-9: reason='missing-label' requires pr.linkMethod to be set");
|
|
40
|
+
}
|
|
41
|
+
if (failingChecks.length !== 0) {
|
|
42
|
+
throw new Error("FailingCheckPayload invariant: reason='missing-label' must have empty failingChecks");
|
|
43
|
+
}
|
|
44
|
+
return applyIssue({ status: 'red', reason, pr, failingChecks: [] });
|
|
45
|
+
}
|
|
46
|
+
if (reason === 'checks-failing') {
|
|
47
|
+
if (pr == null) {
|
|
48
|
+
throw new Error("FailingCheckPayload invariant: reason='checks-failing' requires non-null pr");
|
|
49
|
+
}
|
|
50
|
+
if (pr.linkMethod === undefined) {
|
|
51
|
+
throw new Error("FailingCheckPayload invariant I-9: reason='checks-failing' requires pr.linkMethod to be set");
|
|
52
|
+
}
|
|
53
|
+
if (failingChecks.length === 0) {
|
|
54
|
+
throw new Error("FailingCheckPayload invariant: reason='checks-failing' requires non-empty failingChecks");
|
|
55
|
+
}
|
|
56
|
+
return applyIssue({ status: 'red', reason, pr, failingChecks });
|
|
57
|
+
}
|
|
58
|
+
if (reason === 'pr-is-draft') {
|
|
59
|
+
if (pr !== null) {
|
|
60
|
+
throw new Error("FailingCheckPayload invariant I-7: reason='pr-is-draft' requires pr === null");
|
|
61
|
+
}
|
|
62
|
+
if (!candidates || candidates.length < 1) {
|
|
63
|
+
throw new Error("FailingCheckPayload invariant I-7: reason='pr-is-draft' requires candidates.length >= 1");
|
|
64
|
+
}
|
|
65
|
+
if (candidates.some((c) => c.isDraft !== true)) {
|
|
66
|
+
throw new Error("FailingCheckPayload invariant I-7: reason='pr-is-draft' requires every candidate.isDraft === true");
|
|
67
|
+
}
|
|
68
|
+
if (linkMethod === undefined) {
|
|
69
|
+
throw new Error("FailingCheckPayload invariant I-7: reason='pr-is-draft' requires top-level linkMethod");
|
|
70
|
+
}
|
|
71
|
+
if (failingChecks.length !== 0) {
|
|
72
|
+
throw new Error("FailingCheckPayload invariant I-7: reason='pr-is-draft' must have empty failingChecks");
|
|
73
|
+
}
|
|
74
|
+
return applyIssue({
|
|
75
|
+
status: 'red',
|
|
76
|
+
reason,
|
|
77
|
+
pr: null,
|
|
78
|
+
candidates,
|
|
79
|
+
linkMethod,
|
|
80
|
+
failingChecks: [],
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
if (reason === 'ambiguous-resolution') {
|
|
84
|
+
if (pr !== null) {
|
|
85
|
+
throw new Error("FailingCheckPayload invariant I-8: reason='ambiguous-resolution' requires pr === null");
|
|
86
|
+
}
|
|
87
|
+
if (!candidates || candidates.length < 2) {
|
|
88
|
+
throw new Error("FailingCheckPayload invariant I-8: reason='ambiguous-resolution' requires candidates.length >= 2");
|
|
89
|
+
}
|
|
90
|
+
if (candidates.some((c) => c.isDraft !== false)) {
|
|
91
|
+
throw new Error("FailingCheckPayload invariant I-8: reason='ambiguous-resolution' requires every candidate.isDraft === false");
|
|
92
|
+
}
|
|
93
|
+
if (linkMethod === undefined) {
|
|
94
|
+
throw new Error("FailingCheckPayload invariant I-8: reason='ambiguous-resolution' requires top-level linkMethod");
|
|
95
|
+
}
|
|
96
|
+
if (failingChecks.length !== 0) {
|
|
97
|
+
throw new Error("FailingCheckPayload invariant I-8: reason='ambiguous-resolution' must have empty failingChecks");
|
|
98
|
+
}
|
|
99
|
+
return applyIssue({
|
|
100
|
+
status: 'red',
|
|
101
|
+
reason,
|
|
102
|
+
pr: null,
|
|
103
|
+
candidates,
|
|
104
|
+
linkMethod,
|
|
105
|
+
failingChecks: [],
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
if (reason === 'pr-flag-linkage-refused') {
|
|
109
|
+
if (pr == null) {
|
|
110
|
+
throw new Error("FailingCheckPayload invariant: reason='pr-flag-linkage-refused' requires non-null pr");
|
|
111
|
+
}
|
|
112
|
+
if (kind !== 'empty-refs' && kind !== 'mismatch') {
|
|
113
|
+
throw new Error("FailingCheckPayload invariant: reason='pr-flag-linkage-refused' requires kind ∈ { 'empty-refs' | 'mismatch' }");
|
|
114
|
+
}
|
|
115
|
+
if (failingChecks.length !== 0) {
|
|
116
|
+
throw new Error("FailingCheckPayload invariant: reason='pr-flag-linkage-refused' must have empty failingChecks");
|
|
117
|
+
}
|
|
118
|
+
const base = {
|
|
119
|
+
status: 'red',
|
|
120
|
+
reason,
|
|
121
|
+
pr,
|
|
122
|
+
failingChecks: [],
|
|
123
|
+
kind,
|
|
124
|
+
};
|
|
125
|
+
if (message !== undefined)
|
|
126
|
+
base.message = message;
|
|
127
|
+
return applyIssue(base);
|
|
128
|
+
}
|
|
129
|
+
if (reason === 'pr-number') {
|
|
130
|
+
// #928 — the caller's `<issue>` argument is itself a PR node.
|
|
131
|
+
if (pr !== null) {
|
|
132
|
+
throw new Error("FailingCheckPayload invariant: reason='pr-number' requires pr === null");
|
|
133
|
+
}
|
|
134
|
+
if (typeof hint !== 'string' || hint.length === 0) {
|
|
135
|
+
throw new Error("FailingCheckPayload invariant: reason='pr-number' requires a non-empty hint");
|
|
136
|
+
}
|
|
137
|
+
if (failingChecks.length !== 0) {
|
|
138
|
+
throw new Error("FailingCheckPayload invariant: reason='pr-number' must have empty failingChecks");
|
|
139
|
+
}
|
|
140
|
+
return applyIssue({
|
|
141
|
+
status: 'red',
|
|
142
|
+
reason,
|
|
143
|
+
pr: null,
|
|
144
|
+
failingChecks: [],
|
|
145
|
+
hint,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
if (reason === 'pr-flag-closed-unmerged') {
|
|
149
|
+
if (pr == null) {
|
|
150
|
+
throw new Error("FailingCheckPayload invariant: reason='pr-flag-closed-unmerged' requires non-null pr");
|
|
151
|
+
}
|
|
152
|
+
if (failingChecks.length !== 0) {
|
|
153
|
+
throw new Error("FailingCheckPayload invariant: reason='pr-flag-closed-unmerged' must have empty failingChecks");
|
|
154
|
+
}
|
|
155
|
+
const base = {
|
|
156
|
+
status: 'red',
|
|
157
|
+
reason,
|
|
158
|
+
pr,
|
|
159
|
+
failingChecks: [],
|
|
160
|
+
};
|
|
161
|
+
if (message !== undefined)
|
|
162
|
+
base.message = message;
|
|
163
|
+
return applyIssue(base);
|
|
164
|
+
}
|
|
165
|
+
throw new Error(`FailingCheckPayload: unknown reason ${reason}`);
|
|
166
|
+
}
|
|
167
|
+
export function serializeFailingCheckJson(payload) {
|
|
168
|
+
return JSON.stringify(payload) + '\n';
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=failing-check-json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"failing-check-json.js","sourceRoot":"","sources":["../../../../../src/cli/commands/cockpit/shared/failing-check-json.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `resolveCockpitIdentity` — resolve the GitHub identity used by cockpit
|
|
3
|
+
* subcommands (queue, advance), mirroring `packages/orchestrator/src/services/
|
|
4
|
+
* identity.ts` precedence so App-credentialed clusters don't 403 on `gh api user`.
|
|
5
|
+
*
|
|
6
|
+
* Precedence (first non-null / non-empty / non-throwing tier wins):
|
|
7
|
+
* 1a. `flag` — `--assignee <login>` CLI flag
|
|
8
|
+
* 1b. `configAssignee` — `cockpit.assignee` in `.generacy/config.yaml`
|
|
9
|
+
* 2a. `env.CLUSTER_GITHUB_USERNAME` — cluster-wide env
|
|
10
|
+
* 2b. `env.GH_USERNAME` — cluster-wide env (wizard-delivered)
|
|
11
|
+
* 3. `gh.getCurrentUser()` — `gh api user`
|
|
12
|
+
*
|
|
13
|
+
* Two modes:
|
|
14
|
+
* - `required` — throws `LoudIdentityError` naming all four knobs on all-miss.
|
|
15
|
+
* - `optional` — logs a warning naming all four knobs and returns
|
|
16
|
+
* `{ login: undefined, source: 'none' }`.
|
|
17
|
+
*/
|
|
18
|
+
import type { GhWrapper } from '@generacy-ai/cockpit';
|
|
19
|
+
export type IdentitySource = 'flag' | 'config' | 'CLUSTER_GITHUB_USERNAME' | 'GH_USERNAME' | 'gh-api' | 'none';
|
|
20
|
+
export interface ResolveCockpitIdentityInput {
|
|
21
|
+
flag?: string;
|
|
22
|
+
configAssignee?: string;
|
|
23
|
+
gh: Pick<GhWrapper, 'getCurrentUser'>;
|
|
24
|
+
logger: {
|
|
25
|
+
warn(msg: string): void;
|
|
26
|
+
info?(msg: string): void;
|
|
27
|
+
};
|
|
28
|
+
verb: string;
|
|
29
|
+
mode: 'required' | 'optional';
|
|
30
|
+
env?: NodeJS.ProcessEnv;
|
|
31
|
+
}
|
|
32
|
+
export type ResolveCockpitIdentityResult = {
|
|
33
|
+
login: string;
|
|
34
|
+
source: Exclude<IdentitySource, 'none'>;
|
|
35
|
+
} | {
|
|
36
|
+
login: undefined;
|
|
37
|
+
source: 'none';
|
|
38
|
+
};
|
|
39
|
+
export declare class LoudIdentityError extends Error {
|
|
40
|
+
readonly code: "IDENTITY_UNRESOLVED";
|
|
41
|
+
readonly verb: string;
|
|
42
|
+
constructor(verb: string, message: string);
|
|
43
|
+
}
|
|
44
|
+
export declare function resolveCockpitIdentity(input: ResolveCockpitIdentityInput & {
|
|
45
|
+
mode: 'required';
|
|
46
|
+
}): Promise<{
|
|
47
|
+
login: string;
|
|
48
|
+
source: Exclude<IdentitySource, 'none'>;
|
|
49
|
+
}>;
|
|
50
|
+
export declare function resolveCockpitIdentity(input: ResolveCockpitIdentityInput & {
|
|
51
|
+
mode: 'optional';
|
|
52
|
+
}): Promise<ResolveCockpitIdentityResult>;
|
|
53
|
+
export declare function resolveCockpitIdentity(input: ResolveCockpitIdentityInput): Promise<ResolveCockpitIdentityResult>;
|
|
54
|
+
//# sourceMappingURL=identity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../../../../src/cli/commands/cockpit/shared/identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEtD,MAAM,MAAM,cAAc,GACtB,MAAM,GACN,QAAQ,GACR,yBAAyB,GACzB,aAAa,GACb,QAAQ,GACR,MAAM,CAAC;AAEX,MAAM,WAAW,2BAA2B;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,EAAE,EAAE,IAAI,CAAC,SAAS,EAAE,gBAAgB,CAAC,CAAC;IACtC,MAAM,EAAE;QAAE,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,IAAI,CAAC,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IAC9D,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,UAAU,GAAG,UAAU,CAAC;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB;AAED,MAAM,MAAM,4BAA4B,GACpC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC,cAAc,EAAE,MAAM,CAAC,CAAA;CAAE,GAC1D;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzC,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,IAAI,EAAG,qBAAqB,CAAU;IAC/C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBACV,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAK1C;AAkBD,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,2BAA2B,GAAG;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,GACxD,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC,cAAc,EAAE,MAAM,CAAC,CAAA;CAAE,CAAC,CAAC;AACvE,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,2BAA2B,GAAG;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,GACxD,OAAO,CAAC,4BAA4B,CAAC,CAAC;AACzC,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,2BAA2B,GACjC,OAAO,CAAC,4BAA4B,CAAC,CAAC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
export class LoudIdentityError extends Error {
|
|
2
|
+
code = 'IDENTITY_UNRESOLVED';
|
|
3
|
+
verb;
|
|
4
|
+
constructor(verb, message) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.name = 'LoudIdentityError';
|
|
7
|
+
this.verb = verb;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
function buildFourKnobMessage(verb) {
|
|
11
|
+
return (`cockpit ${verb}: unable to resolve GitHub identity.\n` +
|
|
12
|
+
'Set one of the following:\n' +
|
|
13
|
+
' --assignee <login> (flag, per-invocation)\n' +
|
|
14
|
+
' cockpit.assignee in .generacy/config.yaml (per-repo)\n' +
|
|
15
|
+
' CLUSTER_GITHUB_USERNAME (env, cluster-wide)\n' +
|
|
16
|
+
' GH_USERNAME (env, cluster-wide)\n' +
|
|
17
|
+
'Or authenticate `gh` for a user-token (gh auth login) so `gh api user` can resolve.');
|
|
18
|
+
}
|
|
19
|
+
function nonEmpty(v) {
|
|
20
|
+
return typeof v === 'string' && v.length > 0;
|
|
21
|
+
}
|
|
22
|
+
export async function resolveCockpitIdentity(input) {
|
|
23
|
+
const env = input.env ?? process.env;
|
|
24
|
+
const { flag, configAssignee, gh, logger, verb, mode } = input;
|
|
25
|
+
if (nonEmpty(flag)) {
|
|
26
|
+
logger.info?.(`cockpit ${verb}: identity resolved from --assignee flag (${flag})`);
|
|
27
|
+
return { login: flag, source: 'flag' };
|
|
28
|
+
}
|
|
29
|
+
if (nonEmpty(configAssignee)) {
|
|
30
|
+
logger.info?.(`cockpit ${verb}: identity resolved from cockpit.assignee config (${configAssignee})`);
|
|
31
|
+
return { login: configAssignee, source: 'config' };
|
|
32
|
+
}
|
|
33
|
+
const clusterEnv = env['CLUSTER_GITHUB_USERNAME'];
|
|
34
|
+
if (nonEmpty(clusterEnv)) {
|
|
35
|
+
logger.info?.(`cockpit ${verb}: identity resolved from CLUSTER_GITHUB_USERNAME (${clusterEnv})`);
|
|
36
|
+
return { login: clusterEnv, source: 'CLUSTER_GITHUB_USERNAME' };
|
|
37
|
+
}
|
|
38
|
+
const ghEnv = env['GH_USERNAME'];
|
|
39
|
+
if (nonEmpty(ghEnv)) {
|
|
40
|
+
logger.info?.(`cockpit ${verb}: identity resolved from GH_USERNAME (${ghEnv})`);
|
|
41
|
+
return { login: ghEnv, source: 'GH_USERNAME' };
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
const login = await gh.getCurrentUser();
|
|
45
|
+
if (nonEmpty(login)) {
|
|
46
|
+
logger.info?.(`cockpit ${verb}: identity resolved from gh api user (${login})`);
|
|
47
|
+
return { login, source: 'gh-api' };
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
if (mode === 'optional') {
|
|
52
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
53
|
+
logger.info?.(`cockpit ${verb}: gh api user failed: ${msg}`);
|
|
54
|
+
}
|
|
55
|
+
// Fall through to the four-knob failure branch. The individual error is
|
|
56
|
+
// not surfaced in the loud message — the four knobs are the actionable fix.
|
|
57
|
+
}
|
|
58
|
+
const message = buildFourKnobMessage(verb);
|
|
59
|
+
if (mode === 'required') {
|
|
60
|
+
throw new LoudIdentityError(verb, message);
|
|
61
|
+
}
|
|
62
|
+
logger.warn(`warning: ${message}`);
|
|
63
|
+
return { login: undefined, source: 'none' };
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=identity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity.js","sourceRoot":"","sources":["../../../../../src/cli/commands/cockpit/shared/identity.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Snapshot } from '../watch/snapshot.js';
|
|
2
|
+
/**
|
|
3
|
+
* Issue state: closed dominates any label-derived actionability tier.
|
|
4
|
+
*
|
|
5
|
+
* A closed issue carrying `completed:validate` (or any other actionable-label
|
|
6
|
+
* residue) is done, not actionable. This helper is the single decision
|
|
7
|
+
* surface: both `isActionableSnapshot` (watch) and the status renderer route
|
|
8
|
+
* through it. If you need to expand actionability tiers, extend
|
|
9
|
+
* `isActionableSnapshot` — do not add a second done-gate.
|
|
10
|
+
*
|
|
11
|
+
* The predicate reads raw `snap.state`, NOT `snap.classified.state`. The
|
|
12
|
+
* classified `'terminal'` tier is exactly the label residue this fix stops
|
|
13
|
+
* trusting; reading it would perpetuate the bug pattern (#873).
|
|
14
|
+
*/
|
|
15
|
+
export declare function isDoneSnapshot(snap: Snapshot): boolean;
|
|
16
|
+
//# sourceMappingURL=is-done-snapshot.d.ts.map
|