codeden 0.5.0 → 0.6.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.
Files changed (28) hide show
  1. package/README.md +6 -6
  2. package/dist/cli.js +1 -1
  3. package/dist/{main-BQwSt6Az.js → main-DC-Gug_o.js} +2315 -923
  4. package/dist/main-DC-Gug_o.js.map +1 -0
  5. package/dist/{main-Drh58zq6.js → main-WrV5I8Jo.js} +2 -2
  6. package/dist/{main-Drh58zq6.js.map → main-WrV5I8Jo.js.map} +1 -1
  7. package/dist/{runner-WAbCC8k2.js → runner-CYnMuxur.js} +378 -83
  8. package/dist/runner-CYnMuxur.js.map +1 -0
  9. package/dist/runner.js +1 -1
  10. package/dist/web/assets/{core-aeJ3srYS.js → core-CDpYIzHw.js} +1 -1
  11. package/dist/web/assets/engine-oniguruma-CJg_T4jE.js +1 -0
  12. package/dist/web/assets/{highlighted-body-JLMTFACH-NhDHKomc.js → highlighted-body-JLMTFACH-C9dm2CW4.js} +1 -1
  13. package/dist/web/assets/{highlights-af6Fohu4.js → highlights-o_P8SnvL.js} +1 -1
  14. package/dist/web/assets/index-BELktH7l.css +1 -0
  15. package/dist/web/assets/{index-iad71iug.js → index-Cc7xqhCW.js} +221 -218
  16. package/dist/web/assets/langs-3J89AXIt.js +1 -0
  17. package/dist/web/assets/mermaid-WFAXDIZX-s7S3p3wW.js +1 -0
  18. package/dist/web/assets/{shiki-Do52T6bJ.js → shiki-BYseDnLo.js} +2 -2
  19. package/dist/web/assets/{stream-tokenizer-DFPcXHG7.js → stream-tokenizer-D8_JNbSS.js} +1 -1
  20. package/dist/web/assets/{themes-B76yFk4c.js → themes-BtxdY48G.js} +2 -2
  21. package/dist/web/index.html +2 -2
  22. package/package.json +1 -1
  23. package/dist/main-BQwSt6Az.js.map +0 -1
  24. package/dist/runner-WAbCC8k2.js.map +0 -1
  25. package/dist/web/assets/engine-oniguruma-CyGcXvAw.js +0 -1
  26. package/dist/web/assets/index-BlGTOYYh.css +0 -1
  27. package/dist/web/assets/langs-DEIJuibn.js +0 -1
  28. package/dist/web/assets/mermaid-WFAXDIZX-RdnNjs5C.js +0 -1
@@ -6836,27 +6836,44 @@ const InboxItem = object({
6836
6836
  });
6837
6837
  // ../../packages/contracts/src/factory.ts
6838
6838
  /**
6839
- * Project autonomy modes and dark-factory mode (§10.1). Types only; the factory loop itself
6840
- * lands in M3b.
6839
+ * Project autonomy modes, the software factory and the dark factory (§10.1). The factory loop
6840
+ * itself lives in `factory-api.ts` and `factory-pipeline.ts`.
6841
6841
  */
6842
+ /** The mode ids, in ladder order. */
6843
+ const AUTONOMY_MODES = [
6844
+ "manual",
6845
+ "assisted",
6846
+ "software_factory",
6847
+ "dark_factory"
6848
+ ];
6849
+ /** The id the software factory had before 0.6 ("autopilot"); still read from old events. */
6850
+ const LEGACY_SOFTWARE_FACTORY = "autopilot";
6842
6851
  /**
6843
6852
  * A ladder climbed one step at a time:
6844
6853
  * - `manual`: you find work and merge; you drive every session.
6845
6854
  * - `assisted` (default): you, the PM and automations find work; you merge.
6846
- * - `autopilot`: the PM finds work; CodeDen merges when every merge check passes.
6847
- * - `dark_factory`: the PM finds work continuously from the vision; CodeDen merges.
6855
+ * - `software_factory`: issues filed on GitHub (by you or trusted people) are classified as a
6856
+ * bug, a feature or a docs change and run through that pipeline by a pool of agents, ending
6857
+ * in a pull request with test results and screenshots. You merge, unless auto-merge is on.
6858
+ * - `dark_factory`: the software factory plus a scheduled scout that reviews the app against
6859
+ * the vision and files the issues itself.
6860
+ *
6861
+ * `autopilot` (the software factory's id before 0.6) is still accepted and read as
6862
+ * `software_factory`, so old events and API clients keep working.
6848
6863
  */
6849
- const AutonomyMode = _enum([
6850
- "manual",
6851
- "assisted",
6852
- "autopilot",
6853
- "dark_factory"
6854
- ]);
6864
+ const AutonomyMode = preprocess((v) => v === LEGACY_SOFTWARE_FACTORY ? "software_factory" : v, _enum(AUTONOMY_MODES));
6855
6865
  /** Default location of a project's vision file, relative to the repo root. */
6856
6866
  const DEFAULT_VISION_PATH = ".codeden/VISION.md";
6857
- /** Limits enforced by the server (never left to agent judgement) for autopilot/dark factory. */
6867
+ /** A GitHub login as typed by a person: trimmed, without a leading `@`. */
6868
+ const GithubLogin = string().trim().transform((s) => s.replace(/^@/, "")).pipe(string().regex(/^[A-Za-z0-9](?:[A-Za-z0-9-]{0,38})(?:\[bot\])?$/, "Not a GitHub login"));
6869
+ /**
6870
+ * Limits and policy of the software and dark factory, enforced by the server (never left to
6871
+ * agent judgement).
6872
+ */
6858
6873
  const FactoryLimits = object({
6874
+ /** Agents working at once (the swarm size): builders, reviewers, the scout and its lenses. */
6859
6875
  maxConcurrentSessions: int().positive().default(2),
6876
+ /** Automatic merges per day (only while `autoMerge` is on). */
6860
6877
  maxMergesPerDay: int().nonnegative().default(5),
6861
6878
  /** Daily spend budget; either or both may be set. */
6862
6879
  dailyBudget: object({
@@ -6865,7 +6882,7 @@ const FactoryLimits = object({
6865
6882
  }).prefault({}),
6866
6883
  /**
6867
6884
  * What counts against the daily budget: `factory` (default) is the factory's own sessions
6868
- * (discovery, builders, reviewers, reverts); `project` is every session in the project.
6885
+ * (builders, reviewers, the scout, reverts); `project` is every session in the project.
6869
6886
  */
6870
6887
  budgetScope: _enum(["factory", "project"]).default("factory"),
6871
6888
  /** Pause the loop after this many failed merge checks or reverts in a row. */
@@ -6873,9 +6890,21 @@ const FactoryLimits = object({
6873
6890
  /** Globs that always escalate to a human (auth, payments, migrations, infra, licensing). */
6874
6891
  protectedPaths: array(string()).default([]),
6875
6892
  /** Deploys/releases are off unless explicitly enabled. */
6876
- allowDeploys: boolean().default(false)
6893
+ allowDeploys: boolean().default(false),
6894
+ /**
6895
+ * Merge pull requests automatically once every merge check passes. Off (the default): the
6896
+ * factory stops at "ready to merge" and you merge on GitHub. Work from an untrusted author
6897
+ * that was let in by hand is never merged automatically, whatever this says.
6898
+ */
6899
+ autoMerge: boolean().default(false),
6900
+ /**
6901
+ * GitHub logins whose issues the factory takes on by itself. The account CodeDen uses on
6902
+ * GitHub is always trusted. Issues from anyone else (on a public repository: anyone at all)
6903
+ * are listed as ignored and only taken on when you, or the PM at your request, let one in.
6904
+ */
6905
+ trustedAuthors: array(GithubLogin).max(200).default([])
6877
6906
  });
6878
- /** State of a project's factory loop (discover -> plan -> build -> verify -> merge -> watch). */
6907
+ /** State of a project's factory loop. */
6879
6908
  const FactoryLoopState = _enum([
6880
6909
  "idle",
6881
6910
  "discovering",
@@ -6911,7 +6940,7 @@ const projectBase = {
6911
6940
  autonomy: AutonomyLevel.nullable(),
6912
6941
  /** Project autonomy mode (§10.1). */
6913
6942
  autonomyMode: AutonomyMode.default("assisted"),
6914
- /** Vision file, relative to the repo root; required for autopilot and dark factory. */
6943
+ /** Vision file, relative to the repo root; required for the software and dark factory. */
6915
6944
  visionPath: string().min(1).default(DEFAULT_VISION_PATH),
6916
6945
  factoryLimits: FactoryLimits.prefault({}),
6917
6946
  /** Stops this project's factory loop and all its sessions. */
@@ -8510,28 +8539,276 @@ const Artifact = object({
8510
8539
  itemId: Id.nullable(),
8511
8540
  createdAt: Timestamp
8512
8541
  });
8513
- // ../../packages/contracts/src/factory-api.ts
8542
+ // ../../packages/contracts/src/factory-pipeline.ts
8543
+ /**
8544
+ * The software factory's pipelines (§10.1): every piece of work is classified as a bug, a
8545
+ * feature or a docs change and runs through that type's steps:
8546
+ *
8547
+ * ```
8548
+ * Issue -> Identify type -+-> Bug: Reproduce -> Create fix -> Review fix -+-> Merge
8549
+ * +-> Feature: Analyze -> Implement -> Review -+
8550
+ * +-> Docs: Implement docs change -----------------+
8551
+ * ```
8552
+ *
8553
+ * A failed review sends the work back to the builder (the revise loop). Merging is yours unless
8554
+ * auto-merge is on. Also the dark factory's scout: its review rounds, lenses and findings.
8555
+ */
8556
+ /** The three pipelines. */
8557
+ const WorkType = _enum([
8558
+ "bug",
8559
+ "feature",
8560
+ "docs"
8561
+ ]);
8562
+ /** Who decided the type: a GitHub label, the utility model, keywords, the scout or a person. */
8563
+ const ClassifiedBy = _enum([
8564
+ "label",
8565
+ "model",
8566
+ "heuristic",
8567
+ "scout",
8568
+ "system",
8569
+ "user",
8570
+ "pm"
8571
+ ]);
8572
+ /** The "Identify type" step's result. */
8573
+ const Classification = object({
8574
+ type: WorkType,
8575
+ confidence: _enum([
8576
+ "high",
8577
+ "medium",
8578
+ "low"
8579
+ ]),
8580
+ rationale: string().max(1e3),
8581
+ by: ClassifiedBy,
8582
+ at: Timestamp
8583
+ });
8514
8584
  /**
8515
- * The factory loop of autopilot and dark-factory projects (§10.1): work items, merge checks,
8516
- * the reviewer's verdict, the loop record, the vision and the HTTP shapes of `/api/.../factory`.
8517
- * Autopilot and dark factory are experimental in v1.
8585
+ * Whether the factory may take work on by itself:
8586
+ * - `trusted`: an issue by a trusted author (or the account CodeDen uses), or work the factory
8587
+ * found itself (the scout, a failed check on the default branch, a revert);
8588
+ * - `untrusted`: an issue by anyone else; it is listed as ignored and nothing runs on it;
8589
+ * - `admitted`: an untrusted issue let in by you or by the PM at your request. It runs through
8590
+ * the pipeline but is never merged automatically.
8518
8591
  */
8519
- /** Modes in which CodeDen finds work and merges automatically. */
8520
- const FACTORY_MODES = ["autopilot", "dark_factory"];
8521
- /** True for autopilot and dark factory. */
8522
- function isFactoryMode(mode) {
8523
- return FACTORY_MODES.includes(mode);
8524
- }
8525
- /** Areas the improvement finders look at (one discovery session per area). */
8592
+ const WorkTrust = _enum([
8593
+ "trusted",
8594
+ "untrusted",
8595
+ "admitted"
8596
+ ]);
8597
+ /** Outcomes of the first step of the bug (reproduce) and feature (analyze) pipelines. */
8598
+ const InvestigationOutcome = _enum([
8599
+ "reproduced",
8600
+ "not_reproduced",
8601
+ "implement",
8602
+ "already_done",
8603
+ "needs_info",
8604
+ "out_of_scope"
8605
+ ]);
8606
+ /** What the builder found before writing the fix or the feature. */
8607
+ const Investigation = object({
8608
+ kind: _enum(["reproduction", "analysis"]),
8609
+ outcome: InvestigationOutcome,
8610
+ summary: string().max(2e3),
8611
+ /** Reproduction steps, or the spec the feature is built to. */
8612
+ details: string().max(12e3).nullable(),
8613
+ /** The failing test or probe that shows the bug. */
8614
+ testPath: string().max(500).nullable(),
8615
+ at: Timestamp
8616
+ });
8617
+ /** `factory_report_reproduction`: the bug pipeline's Reproduce step. */
8618
+ const FactoryReproductionReport = object({
8619
+ reproduced: boolean(),
8620
+ summary: string().trim().min(1).max(2e3).describe("What you found, in a few sentences"),
8621
+ steps: string().max(4e3).optional().describe("How to reproduce it: commands or steps, in order"),
8622
+ evidence: string().max(8e3).optional().describe("The failing output, trimmed to what shows the bug"),
8623
+ testPath: string().max(500).optional().describe("The failing test or probe you wrote, relative to the repository root")
8624
+ });
8625
+ /** `factory_submit_analysis`: the feature pipeline's Analyze step. */
8626
+ const FactoryAnalysisReport = object({
8627
+ decision: _enum([
8628
+ "implement",
8629
+ "already_done",
8630
+ "needs_info",
8631
+ "out_of_scope"
8632
+ ]),
8633
+ summary: string().trim().min(1).max(2e3).describe("Your conclusion, in a few sentences"),
8634
+ spec: string().max(12e3).optional().describe("For `implement`: the spec you will build (API, behaviour, edge cases, docs)"),
8635
+ acceptanceCriteria: array(string().trim().min(1).max(500)).min(1).max(12).optional().describe("For `implement`: testable acceptance criteria")
8636
+ }).refine((r) => r.decision !== "implement" || r.spec && r.acceptanceCriteria, { message: "`implement` needs a spec and acceptance criteria" });
8637
+ /**
8638
+ * Where a work item is in its pipeline (what the dashboard diagram shows):
8639
+ * `intake` (waiting to be classified), `ignored` (untrusted author), `queued` (waiting for a
8640
+ * free agent), `reproduce` / `analyze` (first step of bugs and features), `implement` (fix,
8641
+ * feature or docs change), `review` (merge checks and the independent review), `merge` (ready
8642
+ * for you, merging, or watching the default branch after it), `done`, `stopped`.
8643
+ */
8644
+ const PipelineStep = _enum([
8645
+ "intake",
8646
+ "ignored",
8647
+ "queued",
8648
+ "reproduce",
8649
+ "analyze",
8650
+ "implement",
8651
+ "review",
8652
+ "merge",
8653
+ "done",
8654
+ "stopped"
8655
+ ]);
8656
+ /** Whether the item's merge checks all passed (none pending or failed). */
8657
+ function checksPassed(item) {
8658
+ return item.checks.length > 0 && item.checks.every((c) => c.state === "pass" || c.state === "skipped");
8659
+ }
8660
+ /** The pipeline step of a work item, from its stage and what it has done so far. */
8661
+ function pipelineStep(item) {
8662
+ switch (item.stage) {
8663
+ case "candidate": return "intake";
8664
+ case "ignored": return "ignored";
8665
+ case "backlog": return "queued";
8666
+ case "building":
8667
+ if (!item.investigation && item.type === "bug") return "reproduce";
8668
+ if (!item.investigation && item.type === "feature") return "analyze";
8669
+ return "implement";
8670
+ case "verifying": return checksPassed(item) ? "merge" : "review";
8671
+ case "watching":
8672
+ case "escalated": return "merge";
8673
+ case "merged": return "done";
8674
+ default: return "stopped";
8675
+ }
8676
+ }
8677
+ /** What the scout's lenses review (one long-lived lens session per area). */
8526
8678
  const DiscoveryArea = _enum([
8527
8679
  "features",
8528
8680
  "ux",
8529
8681
  "performance",
8530
8682
  "tech_debt",
8531
8683
  "test_gaps",
8532
- "security"
8684
+ "security",
8685
+ "bugs",
8686
+ "docs"
8533
8687
  ]);
8534
- /** Where a work item came from. */
8688
+ /** `factory_plan_round`: the lenses for this round (none: the scout reviews by itself). */
8689
+ const FactoryPlanRoundRequest = object({ lenses: array(object({
8690
+ area: DiscoveryArea,
8691
+ focus: string().trim().min(1).max(1e3).describe("What this lens should look at this round, specific to this app")
8692
+ })).max(8) });
8693
+ /** One improvement a lens found (`factory_report_findings`). */
8694
+ const FactoryFinding = object({
8695
+ title: string().trim().min(3).max(200),
8696
+ summary: string().trim().min(1).max(4e3).describe("What is wrong or missing, and why it matters for the vision"),
8697
+ type: WorkType,
8698
+ severity: _enum([
8699
+ "high",
8700
+ "medium",
8701
+ "low"
8702
+ ]).default("medium"),
8703
+ acceptanceCriteria: array(string().trim().min(1).max(500)).min(1).max(12),
8704
+ /** Paths the change would touch, when known. */
8705
+ paths: array(string()).max(50).optional()
8706
+ });
8707
+ /** A finding as the round keeps it, for the scout to decide on. */
8708
+ const ScoutFinding = FactoryFinding.extend({
8709
+ id: string().min(1),
8710
+ area: DiscoveryArea
8711
+ });
8712
+ /** `factory_file_issue`: the scout files one piece of work as a GitHub issue. */
8713
+ const FactoryFileIssueRequest = object({
8714
+ title: string().trim().min(3).max(200),
8715
+ summary: string().trim().min(1).max(8e3).describe("The issue body: what and why, grounded in the vision"),
8716
+ type: WorkType,
8717
+ acceptanceCriteria: array(string().trim().min(1).max(500)).min(1).max(12),
8718
+ priority: _enum([
8719
+ "high",
8720
+ "normal",
8721
+ "low"
8722
+ ]).default("normal"),
8723
+ /** Findings this issue covers. */
8724
+ findingIds: array(string()).max(20).optional()
8725
+ });
8726
+ /** One lens of the current round. */
8727
+ const ScoutLensRun = object({
8728
+ area: DiscoveryArea,
8729
+ focus: string(),
8730
+ sessionId: Id,
8731
+ sentAt: Timestamp,
8732
+ reported: boolean(),
8733
+ /** When it was reminded to report (once). */
8734
+ nudgedAt: Timestamp.nullable().default(null)
8735
+ });
8736
+ /**
8737
+ * One review round of the scout: `planning` (the scout picks lenses), `reviewing` (the lenses
8738
+ * work), `filing` (the scout files the issues worth doing).
8739
+ */
8740
+ const ScoutRound = object({
8741
+ id: string().min(1),
8742
+ phase: _enum([
8743
+ "planning",
8744
+ "reviewing",
8745
+ "filing"
8746
+ ]),
8747
+ startedAt: Timestamp,
8748
+ /** When the scout was last sent work in this round (its turn must end after this). */
8749
+ sentAt: Timestamp,
8750
+ nudgedAt: Timestamp.nullable().default(null),
8751
+ lenses: array(ScoutLensRun).default([]),
8752
+ findings: array(ScoutFinding).max(60).default([]),
8753
+ filed: int().nonnegative().default(0)
8754
+ });
8755
+ /** The scout of a dark factory: its long-lived sessions and the round in progress. */
8756
+ const ScoutState = object({
8757
+ sessionId: Id.nullable().default(null),
8758
+ /** One long-lived lens session per area, reused round after round. */
8759
+ lensSessions: partialRecord(DiscoveryArea, Id).default({}),
8760
+ round: ScoutRound.nullable().default(null),
8761
+ lastRoundAt: Timestamp.nullable().default(null),
8762
+ rounds: int().nonnegative().default(0)
8763
+ });
8764
+ /** The scout as the dashboard shows it. */
8765
+ const ScoutStatus = object({
8766
+ phase: _enum([
8767
+ "idle",
8768
+ "planning",
8769
+ "reviewing",
8770
+ "filing"
8771
+ ]),
8772
+ sessionId: Id.nullable(),
8773
+ lenses: array(object({
8774
+ area: DiscoveryArea,
8775
+ sessionId: Id,
8776
+ reported: boolean(),
8777
+ active: boolean()
8778
+ })),
8779
+ findings: int().nonnegative(),
8780
+ filed: int().nonnegative(),
8781
+ lastRoundAt: Timestamp.nullable(),
8782
+ /** When the next round may start (it also waits for the queue to run low). */
8783
+ nextRoundAt: Timestamp.nullable(),
8784
+ rounds: int().nonnegative()
8785
+ });
8786
+ /** Let an ignored issue from an untrusted author in (it is never merged automatically). */
8787
+ const FactoryAdmitRequest = object({
8788
+ itemId: Id,
8789
+ /** Skip classification with a type you chose. */
8790
+ type: WorkType.optional()
8791
+ });
8792
+ /** Correct the type of an item that has not started yet. */
8793
+ const FactorySetTypeRequest = object({
8794
+ itemId: Id,
8795
+ type: WorkType,
8796
+ reason: string().trim().max(500).optional()
8797
+ });
8798
+ // ../../packages/contracts/src/factory-api.ts
8799
+ /**
8800
+ * The factory loop of software-factory and dark-factory projects (§10.1): work items, merge
8801
+ * checks, the reviewer's verdict, the loop record, the vision and the HTTP shapes of
8802
+ * `/api/.../factory`. Both modes are experimental. The pipelines themselves are in
8803
+ * `factory-pipeline.ts`.
8804
+ */
8805
+ /** Modes in which the factory loop runs. */
8806
+ const FACTORY_MODES = ["software_factory", "dark_factory"];
8807
+ /** True for the software factory and the dark factory. */
8808
+ function isFactoryMode(mode) {
8809
+ return FACTORY_MODES.includes(mode);
8810
+ }
8811
+ /** Where a work item came from: an issue, the scout, a failed check on main, a revert. */
8535
8812
  const FactoryItemSource = _enum([
8536
8813
  "discovery",
8537
8814
  "issue",
@@ -8539,15 +8816,18 @@ const FactoryItemSource = _enum([
8539
8816
  "revert"
8540
8817
  ]);
8541
8818
  /**
8542
- * Where a work item is:
8543
- * - `candidate`: found, waiting for the PM to score it against the vision
8544
- * - `backlog`: accepted (a GitHub issue exists), waiting for a build slot
8545
- * - `building`, `verifying` (merge checks), `watching` (merged, main CI watched)
8546
- * - `merged` (done), `reverted`, `rejected` (by the PM), `failed` (merge checks),
8547
- * `escalated` (needs a human: protected area or a decision)
8819
+ * Where a work item is in its life (the pipeline step is derived from it, see `pipelineStep`):
8820
+ * - `candidate`: received, waiting to be classified (Identify type)
8821
+ * - `ignored`: an issue by an untrusted author; nothing runs until someone lets it in
8822
+ * - `backlog`: classified, waiting for a free agent
8823
+ * - `building` (reproduce or analyze, then implement), `verifying` (merge checks, the review,
8824
+ * then ready to merge), `watching` (merged automatically, main CI watched)
8825
+ * - `merged` (done), `reverted`, `rejected` (not reproduced, declined, closed), `failed`
8826
+ * (merge checks), `escalated` (touches a protected area: yours to merge)
8548
8827
  */
8549
8828
  const FactoryItemStage = _enum([
8550
8829
  "candidate",
8830
+ "ignored",
8551
8831
  "backlog",
8552
8832
  "building",
8553
8833
  "verifying",
@@ -8563,6 +8843,7 @@ const MergeCheck = object({
8563
8843
  name: _enum([
8564
8844
  "ci",
8565
8845
  "tests",
8846
+ "test_results",
8566
8847
  "review",
8567
8848
  "security",
8568
8849
  "ui_evidence",
@@ -8610,17 +8891,28 @@ const ReviewVerdict = object({
8610
8891
  const FactoryItem = object({
8611
8892
  id: Id,
8612
8893
  projectId: Id,
8613
- /** `factory:<slug>` while a candidate; `issue:<n>` once its issue exists. */
8894
+ /** `issue:<n>` once its issue exists (`factory:<slug>` before). */
8614
8895
  workKey: string().min(1),
8615
8896
  title: string().min(1),
8616
- /** Why it matters, as the finder or issue described it. */
8897
+ /** The issue body, or why it matters as the scout described it. */
8617
8898
  summary: string(),
8618
8899
  source: FactoryItemSource,
8619
8900
  area: DiscoveryArea.nullable(),
8620
8901
  acceptanceCriteria: array(string()),
8621
- /** The PM's score against the vision, 0..1. */
8902
+ /** Priority, 0..1 (higher first); null for issues, which queue in order of arrival. */
8622
8903
  score: number$1().min(0).max(1).nullable(),
8623
8904
  stage: FactoryItemStage,
8905
+ /** The pipeline (bug, feature, docs); null until classified. */
8906
+ type: WorkType.nullable().default(null),
8907
+ classification: Classification.nullable().default(null),
8908
+ /** Whether the factory may act on it by itself (see `WorkTrust`). */
8909
+ trust: WorkTrust.default("trusted"),
8910
+ /** GitHub login of the issue's author, when it came from an issue. */
8911
+ author: string().nullable().default(null),
8912
+ /** Who let an untrusted issue in. */
8913
+ admittedBy: _enum(["user", "pm"]).nullable().default(null),
8914
+ /** The bug's reproduction or the feature's analysis, once the builder reported it. */
8915
+ investigation: Investigation.nullable().default(null),
8624
8916
  issue: GitHubIssueRef.nullable(),
8625
8917
  pr: GitHubPrRef.nullable(),
8626
8918
  builderSessionId: Id.nullable(),
@@ -8672,14 +8964,17 @@ const FactoryTuning = object({
8672
8964
  requireCi: boolean().default(true),
8673
8965
  /** Security/dependency scan run in the builder's worktree (e.g. `pnpm audit --prod`). */
8674
8966
  auditCommand: string().min(1).nullable().default(null),
8675
- /** Fix rounds after failed merge checks before an item fails. */
8676
- maxFixAttempts: int().nonnegative().default(1),
8677
- /** Dark factory: start discovery when fewer items than this wait to be built. */
8967
+ /** Revise rounds (failed review or merge checks) before an item fails. */
8968
+ maxFixAttempts: int().nonnegative().default(2),
8969
+ /** Dark factory: the scout starts a round when fewer items than this wait for an agent. */
8678
8970
  minBacklog: int().nonnegative().default(2),
8679
- /** Dark factory: minutes between discovery rounds. */
8971
+ /** Dark factory: minutes between the scout's review rounds. */
8680
8972
  discoveryIntervalMin: int().positive().default(360),
8681
- /** Discovery sessions per round (round-robin over the areas). */
8682
- discoveryPerRound: int().positive().default(2),
8973
+ /** Dark factory: most lenses (long-lived reviewer sessions) the scout may use per round. */
8974
+ discoveryPerRound: int().nonnegative().default(2),
8975
+ /** Dark factory: most issues the scout may file per round. */
8976
+ maxIssuesPerRound: int().positive().default(3),
8977
+ /** Dark factory: the areas the scout's lenses may review. */
8683
8978
  areas: array(DiscoveryArea).default(DiscoveryArea.options),
8684
8979
  /** Provider for builders (`auto`: the project/role default). */
8685
8980
  builderProvider: union([literal("auto"), ProviderId]).default("auto"),
@@ -8694,7 +8989,7 @@ const FactoryTuningPatch = object(Object.fromEntries(Object.entries(FactoryTunin
8694
8989
  const kind = schema._zod.def.type;
8695
8990
  return [key, (kind === "default" || kind === "prefault" ? schema.unwrap() : schema).optional()];
8696
8991
  })));
8697
- /** A running improvement-finder session. */
8992
+ /** A discovery session of loops before 0.6 (kept so old loops still parse). */
8698
8993
  const DiscoveryRun = object({
8699
8994
  sessionId: Id,
8700
8995
  area: DiscoveryArea,
@@ -8709,10 +9004,14 @@ const FactoryLoop = object({
8709
9004
  /** Local day (`YYYY-MM-DD`) the counters below belong to. */
8710
9005
  day: string(),
8711
9006
  mergesToday: int().nonnegative(),
8712
- discovery: array(DiscoveryRun),
8713
- /** Next area index for round-robin discovery. */
8714
- nextArea: int().nonnegative(),
8715
- lastDiscoveryAt: Timestamp.nullable(),
9007
+ /** Unused since 0.6 (the scout replaced the discovery sessions). */
9008
+ discovery: array(DiscoveryRun).default([]),
9009
+ /** Unused since 0.6. */
9010
+ nextArea: int().nonnegative().default(0),
9011
+ /** Unused since 0.6 (see `scout.lastRoundAt`). */
9012
+ lastDiscoveryAt: Timestamp.nullable().default(null),
9013
+ /** The dark factory's scout. */
9014
+ scout: ScoutState.prefault({}),
8716
9015
  /** Day of the last daily digest. */
8717
9016
  lastDigestDay: string().nullable(),
8718
9017
  /** Issues opened before this are not picked up automatically. */
@@ -8807,8 +9106,9 @@ object({
8807
9106
  /** `PUT /api/projects/:id/vision`. */
8808
9107
  const PutVisionRequest = object({ contents: string().min(1).max(2e5) });
8809
9108
  /**
8810
- * `PUT /api/projects/:id/autonomy`. Switching to autopilot or dark factory requires a vision
8811
- * file and limits with a daily budget (sent here, or already saved while in a factory mode).
9109
+ * `PUT /api/projects/:id/autonomy`. Switching to the software or dark factory requires a GitHub
9110
+ * project, a vision file and limits with a daily budget (sent here, or already saved while in
9111
+ * a factory mode).
8812
9112
  */
8813
9113
  const SetAutonomyModeRequest = object({
8814
9114
  mode: AutonomyMode,
@@ -8819,7 +9119,7 @@ object({
8819
9119
  projectId: Id,
8820
9120
  mode: AutonomyMode,
8821
9121
  limits: FactoryLimits,
8822
- /** Autopilot and dark factory are experimental in v1. */
9122
+ /** The software and dark factory are experimental. */
8823
9123
  experimental: boolean()
8824
9124
  });
8825
9125
  /** `POST /api/projects/:id/kill-switch` and `POST /api/factory/kill-switch`. */
@@ -8829,7 +9129,7 @@ object({
8829
9129
  /** Sessions stopped by turning the switch on. */
8830
9130
  stoppedSessions: array(Id)
8831
9131
  });
8832
- /** A work item as the factory panel shows it. */
9132
+ /** A work item as the factory panel and its pipeline diagram show it. */
8833
9133
  const FactoryWorkItem = object({
8834
9134
  id: Id,
8835
9135
  title: string(),
@@ -8837,9 +9137,20 @@ const FactoryWorkItem = object({
8837
9137
  issue: GitHubIssueRef.nullable(),
8838
9138
  pr: GitHubPrRef.nullable(),
8839
9139
  score: number$1().nullable(),
9140
+ /** The builder session. */
8840
9141
  sessionId: Id.nullable(),
9142
+ /** The independent reviewer's session, once there is one. */
9143
+ reviewerSessionId: Id.nullable().default(null),
9144
+ /** The session working on it right now (the reviewer while reviewing), for the diagram. */
9145
+ activeSessionId: Id.nullable().default(null),
8841
9146
  stage: FactoryItemStage,
9147
+ step: PipelineStep.default("intake"),
9148
+ type: WorkType.nullable().default(null),
9149
+ trust: WorkTrust.default("trusted"),
9150
+ author: string().nullable().default(null),
8842
9151
  source: FactoryItemSource,
9152
+ /** Revise rounds so far. */
9153
+ attempts: int().nonnegative().default(0),
8843
9154
  reason: string().nullable(),
8844
9155
  note: string().nullable(),
8845
9156
  updatedAt: Timestamp
@@ -8872,40 +9183,23 @@ object({
8872
9183
  mergesToday: int().nonnegative(),
8873
9184
  consecutiveFailures: int().nonnegative(),
8874
9185
  activeSessions: int().nonnegative(),
9186
+ /** Waiting: being classified (`candidate`) or for a free agent (`backlog`). */
8875
9187
  backlog: array(FactoryWorkItem),
8876
9188
  inProgress: array(FactoryWorkItem),
8877
9189
  mergeChecks: array(FactoryMergeChecks),
8878
9190
  /** Merged, reverted, failed, rejected and escalated items, newest first. */
8879
9191
  recent: array(FactoryWorkItem),
9192
+ /** Issues by untrusted authors, newest first; nothing runs on them until let in. */
9193
+ ignored: array(FactoryWorkItem).default([]),
9194
+ /** The account CodeDen uses on GitHub (always trusted); null when unknown. */
9195
+ githubLogin: string().nullable().default(null),
9196
+ /** The dark factory's scout; null in the software factory. */
9197
+ scout: ScoutStatus.nullable().default(null),
8880
9198
  visionExists: boolean(),
8881
9199
  lastDigest: FactoryDigest.nullable(),
8882
9200
  lastTickAt: Timestamp.nullable()
8883
9201
  });
8884
9202
  object({ item: FactoryItem });
8885
- /** A candidate reported by an improvement finder (`factory_report_candidates`). */
8886
- const FactoryCandidate = object({
8887
- title: string().trim().min(3).max(200),
8888
- summary: string().trim().min(1).max(4e3),
8889
- acceptanceCriteria: array(string().trim().min(1).max(500)).min(1).max(12),
8890
- /** Paths the change would touch, when known. */
8891
- paths: array(string()).max(50).optional()
8892
- });
8893
- /** The PM's decision on a candidate (`factory_triage`). */
8894
- const FactoryTriageRequest = object({
8895
- itemId: Id,
8896
- decision: _enum(["accept", "reject"]),
8897
- /** Score against the vision, 0..1 (accepts). */
8898
- score: number$1().min(0).max(1).optional(),
8899
- /** Replaces the finder's acceptance criteria (accepts). */
8900
- acceptanceCriteria: array(string().trim().min(1).max(500)).min(1).max(12).optional(),
8901
- /** Why (required for rejects). */
8902
- reason: string().trim().min(1).max(1e3).optional(),
8903
- /**
8904
- * Accept work that can't be split under the size limit (an initial scaffold, a stack
8905
- * migration), with the reason. Recorded as a factory decision.
8906
- */
8907
- largeChange: string().trim().min(1).max(500).optional()
8908
- });
8909
9203
  /**
8910
9204
  * `factory_allow_large_change`: the PM lets an item that failed only the size check merge
8911
9205
  * after all, because the work can't be split. The item goes back to verifying.
@@ -9421,7 +9715,8 @@ const Notice = discriminatedUnion("type", [
9421
9715
  "escalated",
9422
9716
  "regression",
9423
9717
  "merged",
9424
- "failed"
9718
+ "failed",
9719
+ "ready"
9425
9720
  ]),
9426
9721
  /** Instructions (for the PM) or a summary (for the orchestrator). */
9427
9722
  text: string(),
@@ -9465,7 +9760,7 @@ object({
9465
9760
  kind: _enum(["github", "local"]),
9466
9761
  /**
9467
9762
  * The project's autonomy mode: tells the PM who merges pull requests (the user in manual and
9468
- * assisted, the factory loop in autopilot and dark factory).
9763
+ * assisted, the factory loop in the software and dark factory).
9469
9764
  */
9470
9765
  mode: AutonomyMode
9471
9766
  }),
@@ -12034,7 +12329,7 @@ const BillingMode = _enum([
12034
12329
  "subscription",
12035
12330
  "unknown"
12036
12331
  ]);
12037
- /** Who started the work a ledger row belongs to. `factory`: autopilot / dark-factory work. */
12332
+ /** Who started the work a ledger row belongs to. `factory`: software- and dark-factory work. */
12038
12333
  const UsageSource = _enum([
12039
12334
  "user",
12040
12335
  "orchestrator",
@@ -12265,7 +12560,7 @@ object({
12265
12560
  * rest of the bundle, so the package version is the single source of truth at runtime;
12266
12561
  * everywhere else (workspace, tests) it is `SOURCE_VERSION`.
12267
12562
  */
12268
- const CODEDEN_VERSION = packageVersion() ?? "0.5.0";
12563
+ const CODEDEN_VERSION = packageVersion() ?? "0.6.0";
12269
12564
  function packageVersion() {
12270
12565
  const value = globalThis.__CODEDEN_PACKAGE_VERSION__;
12271
12566
  return typeof value === "string" && value.length > 0 ? value : void 0;
@@ -30167,7 +30462,7 @@ async function handleMcpRequest(request, upstream) {
30167
30462
  return await upstream.forward(request);
30168
30463
  } catch (error) {
30169
30464
  if (request.signal.aborted) return new Response(null, { status: 499 });
30170
- return jsonRpcError(502, `CodeDen server unreachable: ${error.message}`);
30465
+ return jsonRpcError(502, `CodeDen server unreachable (it may be restarting; call the same tool again in a few seconds): ${error.message}`);
30171
30466
  }
30172
30467
  }
30173
30468
  // ../runner/src/process/supervisor.ts
@@ -32465,6 +32760,6 @@ async function startRunner(opts) {
32465
32760
  close
32466
32761
  };
32467
32762
  }
32468
- export { SetNetworkPasswordResponse as $, SessionOptions as $n, speechExcerpt as $t, findExecutable as A, PutVisionRequest as An, intersection as Ar, UpdateAutomationProjectSettingsRequest as At, RunnerToServerMessage as B, TriagePolicy as Bn, unknown as Br, SecretKey as Bt, importClaudeSdkFrom as C, FactoryAllowLargeChangeRequest as Cn, _enum as Cr, ListAutomationsQuery as Ct, resolveNpm as D, FactoryTuning as Dn, custom as Dr, TriageDecisionRequest as Dt, runNpm as E, FactoryTriageRequest as En, boolean as Er, StarterSetRequest as Et, CODEDEN_VERSION as F, Automation as Fn, optional as Fr, ListInboxQuery as Ft, ResolveConflictRequest as G, GitCommitRequest as Gn, SteerRequest as Gt, ArchiveSessionRequest as H, SessionStatus as Hn, toJSONSchema as Hr, SessionStartMeta as Ht, UsageQuery as I, AutomationAction as In, preprocess as Ir, ListSessionsQuery as It, NetworkStatus as J, SessionResult as Jn, UpdateProjectRequest as Jt, RoleMessageRequest as K, GitPushRequest as Kn, ThreadItemsQuery as Kt, UsageSettings as L, AutomationGuards as Ln, record as Lr, ReorderProjectsRequest as Lt, ownNodeEnv as M, SetAutonomyModeRequest as Mn, looseObject as Mr, CreateProjectRequest as Mt, import_websocket_server as N, isFactoryMode as Nn, number$1 as Nr, FileReadQuery as Nt, acquireInstallLock as O, KillSwitchRequest as On, discriminatedUnion as Or, TriageReport as Ot, wrapper_default as P, Artifact as Pn, object as Pr, FileWriteRequest as Pt, SetNetworkPasswordRequest as Q, RunnerCommandResults as Qn, Settings as Qt, SessionFileQuery as R, AutomationRun as Rn, string as Rr, ResolveInboxRequest as Rt, CLAUDE_SDK_VERSION as S, DiscoveryArea as Sn, datetime as Sr, ListAutomationRunsQuery as St, isClaudeSdkInstalled as T, FactoryDecisionRequest as Tn, array as Tr, SetAutomationEnabledRequest as Tt, ListConflictsQuery as U, DiffScope as Un, safeParse$1 as Ur, SetSecretRequest as Ut, ServerLock as V, Session as Vn, ZodError as Vr, SendMessageRequest as Vt, ListNoticesQuery as W, EditQueuedMessageRequest as Wn, prettifyError as Wr, StartSessionRequest as Wt, RemoteAccessFile as X, TerminalClientMessage as Xn, agentEventToNewEvent as Xt, PASSWORD_RULE_TEXT as Y, SpeechSummaryRequest as Yn, HealthResponse as Yt, SetNetworkAccessRequest as Z, TerminalQuery as Zn, READ_ALOUD_FULL_MAX_CHARS as Zt, ImageGenerationError as _, GithubPr as _n, McpServerTarget as _r, ImportAutomationsRequest as _t, Hono as a, UpdateInstallRequest as an, sortProjects as ar, BrowserClientMessage as at, mainRepoRoot as b, githubPrId as bn, ProviderId as br, AutomationProjectRequest as bt, createAdaptorServer as c, isNewerVersion as cn, InboxItem as cr, BrowserNavigateRequest as ct, defaultShell as d, NoticeBatchData as dn, AgentConfigDeleteQuery as dr, BrowserViewportRequest as dt, LOCAL_STT_SAMPLE_RATE as en, ProjectConfigFile as er, SignInRequest as et, shellCommandLine as f, CreateGithubIssueRequest as fn, AgentConfigDiffRequest as fr, BrowserWsQuery as ft, resolveImageOutput as g, GithubListQuery as gn, McpServerDiffRequest as gr, ExportAutomationsQuery as gt, IMAGE_ASPECT_RATIOS as h, GithubLabelRequest as hn, AgentConfigWriteRequest as hr, DuplicateAutomationRequest as ht, killTree as i, AppPointer as in, Project as ir, summarizeActivity as it, isElectronRuntime as j, ReviewVerdict as jn, literal as jr, UpdateAutomationRequest as jt, brokenInstallMessage as k, LEGACY_SIZE_LIMITS as kn, int as kr, UpcomingRunsQuery as kt, upgradeWebSocket as l, ConflictRecord as ln, InboxItemKind as lr, BrowserNewTabRequest as lt, createImageEngineRegistry as m, GithubIssue as mn, AgentConfigLocator as mr, AutomationImportSource as mt, readLock as n, SttQuery as nn, StartedBy as nr, ImageTestRequest as nt, tryDecodeURIComponent as o, UpdateStatus as on, DEFAULT_VISION_PATH as or, BrowserDevServerRequest as ot, ImageEngineRegistry as p, GithubCommentRequest as pn, AgentConfigListQuery as pr, AUTOMATION_IMPORT_LIMITS as pt, UpdateSessionRequest as q, RestoreFilesRequest as qn, UiClientMessage as qt, isAlive as r, TtsRequest as rn, WorkKey as rr, BrowserHostClientMessage as rt, bufferToFormData as s, compareVersions$1 as sn, FactoryLimits as sr, BrowserHistoryRequest as st, startRunner as t, LocalSttModelParams as tn, ConflictDecision as tr, passwordProblem as tt, refreshProcessPath as u, NOTICE_BATCH_CODE as un, messageFrom as ur, BrowserOpenRequest as ut, claudeMemoryDir as v, MergePrRequest as vn, McpServerUpsertRequest as vr, AutomationFileFrontmatter as vt, installClaudeSdk as w, FactoryCandidate as wn, _null as wr, RunAutomationRequest as wt, claudeSdkSource as x, parseGithubPrId as xn, ReasoningEffort as xr, CreateAutomationRequest as xt, findGitRoot as y, TriageIssueRequest as yn, AutonomyLevel as yr, AutomationGuardsPatch as yt, RunnerLock as z, AutomationTrigger as zn, union as zr, RespondRequest as zt };
32763
+ export { SetNetworkPasswordResponse as $, RestoreFilesRequest as $n, speechExcerpt as $t, findExecutable as A, isFactoryMode as An, _null as Ar, UpdateAutomationProjectSettingsRequest as At, RunnerToServerMessage as B, Artifact as Bn, object as Br, SecretKey as Bt, importClaudeSdkFrom as C, FactoryDecisionRequest as Cn, McpServerTarget as Cr, ListAutomationsQuery as Ct, resolveNpm as D, PutVisionRequest as Dn, ReasoningEffort as Dr, TriageDecisionRequest as Dt, runNpm as E, LEGACY_SIZE_LIMITS as En, ProviderId as Er, StarterSetRequest as Et, CODEDEN_VERSION as F, FactoryPlanRoundRequest as Fn, int as Fr, ListInboxQuery as Ft, ResolveConflictRequest as G, AutomationTrigger as Gn, union as Gr, SteerRequest as Gt, ArchiveSessionRequest as H, AutomationAction as Hn, preprocess as Hr, SessionStartMeta as Ht, UsageQuery as I, FactoryReproductionReport as In, intersection as Ir, ListSessionsQuery as It, NetworkStatus as J, SessionStatus as Jn, toJSONSchema as Jr, UpdateProjectRequest as Jt, RoleMessageRequest as K, TriagePolicy as Kn, unknown as Kr, ThreadItemsQuery as Kt, UsageSettings as L, FactorySetTypeRequest as Ln, literal as Lr, ReorderProjectsRequest as Lt, ownNodeEnv as M, FactoryAnalysisReport as Mn, boolean as Mr, CreateProjectRequest as Mt, import_websocket_server as N, FactoryFileIssueRequest as Nn, custom as Nr, FileReadQuery as Nt, acquireInstallLock as O, ReviewVerdict as On, datetime as Or, TriageReport as Ot, wrapper_default as P, FactoryFinding as Pn, discriminatedUnion as Pr, FileWriteRequest as Pt, SetNetworkPasswordRequest as Q, GitPushRequest as Qn, Settings as Qt, SessionFileQuery as R, ScoutState as Rn, looseObject as Rr, ResolveInboxRequest as Rt, CLAUDE_SDK_VERSION as S, FactoryAllowLargeChangeRequest as Sn, McpServerDiffRequest as Sr, ListAutomationRunsQuery as St, isClaudeSdkInstalled as T, KillSwitchRequest as Tn, AutonomyLevel as Tr, SetAutomationEnabledRequest as Tt, ListConflictsQuery as U, AutomationGuards as Un, record as Ur, SetSecretRequest as Ut, ServerLock as V, Automation as Vn, optional as Vr, SendMessageRequest as Vt, ListNoticesQuery as W, AutomationRun as Wn, string as Wr, StartSessionRequest as Wt, RemoteAccessFile as X, EditQueuedMessageRequest as Xn, prettifyError as Xr, agentEventToNewEvent as Xt, PASSWORD_RULE_TEXT as Y, DiffScope as Yn, safeParse$1 as Yr, HealthResponse as Yt, SetNetworkAccessRequest as Z, GitCommitRequest as Zn, READ_ALOUD_FULL_MAX_CHARS as Zt, ImageGenerationError as _, GithubPr as _n, AgentConfigDeleteQuery as _r, ImportAutomationsRequest as _t, Hono as a, UpdateInstallRequest as an, SessionOptions as ar, BrowserClientMessage as at, mainRepoRoot as b, githubPrId as bn, AgentConfigLocator as br, AutomationProjectRequest as bt, createAdaptorServer as c, isNewerVersion as cn, StartedBy as cr, BrowserNavigateRequest as ct, defaultShell as d, NoticeBatchData as dn, sortProjects as dr, BrowserViewportRequest as dt, LOCAL_STT_SAMPLE_RATE as en, SessionResult as er, SignInRequest as et, shellCommandLine as f, CreateGithubIssueRequest as fn, DEFAULT_VISION_PATH as fr, BrowserWsQuery as ft, resolveImageOutput as g, GithubListQuery as gn, messageFrom as gr, ExportAutomationsQuery as gt, IMAGE_ASPECT_RATIOS as h, GithubLabelRequest as hn, InboxItemKind as hr, DuplicateAutomationRequest as ht, killTree as i, AppPointer as in, RunnerCommandResults as ir, summarizeActivity as it, isElectronRuntime as j, FactoryAdmitRequest as jn, array as jr, UpdateAutomationRequest as jt, brokenInstallMessage as k, SetAutonomyModeRequest as kn, _enum as kr, UpcomingRunsQuery as kt, upgradeWebSocket as l, ConflictRecord as ln, WorkKey as lr, BrowserNewTabRequest as lt, createImageEngineRegistry as m, GithubIssue as mn, InboxItem as mr, AutomationImportSource as mt, readLock as n, SttQuery as nn, TerminalClientMessage as nr, ImageTestRequest as nt, tryDecodeURIComponent as o, UpdateStatus as on, ProjectConfigFile as or, BrowserDevServerRequest as ot, ImageEngineRegistry as p, GithubCommentRequest as pn, FactoryLimits as pr, AUTOMATION_IMPORT_LIMITS as pt, UpdateSessionRequest as q, Session as qn, ZodError as qr, UiClientMessage as qt, isAlive as r, TtsRequest as rn, TerminalQuery as rr, BrowserHostClientMessage as rt, bufferToFormData as s, compareVersions$1 as sn, ConflictDecision as sr, BrowserHistoryRequest as st, startRunner as t, LocalSttModelParams as tn, SpeechSummaryRequest as tr, passwordProblem as tt, refreshProcessPath as u, NOTICE_BATCH_CODE as un, Project as ur, BrowserOpenRequest as ut, claudeMemoryDir as v, MergePrRequest as vn, AgentConfigDiffRequest as vr, AutomationFileFrontmatter as vt, installClaudeSdk as w, FactoryTuning as wn, McpServerUpsertRequest as wr, RunAutomationRequest as wt, claudeSdkSource as x, parseGithubPrId as xn, AgentConfigWriteRequest as xr, CreateAutomationRequest as xt, findGitRoot as y, TriageIssueRequest as yn, AgentConfigListQuery as yr, AutomationGuardsPatch as yt, RunnerLock as z, pipelineStep as zn, number$1 as zr, RespondRequest as zt };
32469
32764
 
32470
- //# sourceMappingURL=runner-WAbCC8k2.js.map
32765
+ //# sourceMappingURL=runner-CYnMuxur.js.map