@try-works/dsh-recursive-mode 0.1.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 (88) hide show
  1. package/cordis.patch.yml +12 -0
  2. package/lib/bootstrap.d.ts +35 -0
  3. package/lib/client/board.d.ts +10 -0
  4. package/lib/client/contract.d.ts +51 -0
  5. package/lib/client/derive.d.ts +92 -0
  6. package/lib/client/index.d.ts +21 -0
  7. package/lib/client/inspector.d.ts +10 -0
  8. package/lib/client/node.d.ts +71 -0
  9. package/lib/client/settings.d.ts +6 -0
  10. package/lib/client/slots.d.ts +7 -0
  11. package/lib/client/strip.d.ts +7 -0
  12. package/lib/client.d.ts +10 -0
  13. package/lib/client.js +490 -0
  14. package/lib/closeout.d.ts +23 -0
  15. package/lib/commands.d.ts +51 -0
  16. package/lib/delegation.d.ts +92 -0
  17. package/lib/enforcement.d.ts +53 -0
  18. package/lib/events.d.ts +173 -0
  19. package/lib/handoff.d.ts +51 -0
  20. package/lib/index.d.ts +40 -0
  21. package/lib/lifecycle.d.ts +107 -0
  22. package/lib/lock.d.ts +92 -0
  23. package/lib/policy.d.ts +12 -0
  24. package/lib/projection.d.ts +29 -0
  25. package/lib/recursive_closeout.tool.d.ts +8 -0
  26. package/lib/recursive_init.tool.d.ts +2 -0
  27. package/lib/recursive_lint.tool.d.ts +2 -0
  28. package/lib/recursive_lock.tool.d.ts +2 -0
  29. package/lib/recursive_scratch.tool.d.ts +7 -0
  30. package/lib/recursive_status.tool.d.ts +2 -0
  31. package/lib/review.d.ts +39 -0
  32. package/lib/router.d.ts +77 -0
  33. package/lib/run.d.ts +29 -0
  34. package/lib/runtime.d.ts +241 -0
  35. package/lib/scratch.d.ts +18 -0
  36. package/lib/status.d.ts +19 -0
  37. package/lib/types.d.ts +104 -0
  38. package/lib/workspace.d.ts +50 -0
  39. package/package.json +119 -0
  40. package/preset/recursive/agent.cordis.yml +282 -0
  41. package/preset/recursive/preset.yml +3 -0
  42. package/scripts/install-recursive-mode.ps1 +956 -0
  43. package/scripts/install-recursive-mode.py +750 -0
  44. package/scripts/lint-recursive-run.py +2868 -0
  45. package/scripts/recursive-closeout.py +541 -0
  46. package/scripts/recursive-init.py +356 -0
  47. package/scripts/recursive-lock.py +302 -0
  48. package/scripts/recursive-status.py +2124 -0
  49. package/scripts/recursive_phase_rules.py +367 -0
  50. package/scripts/recursive_router_lib.py +2282 -0
  51. package/scripts/test-recursive-mode-smoke.ts +204 -0
  52. package/scripts/verify-locks.py +353 -0
  53. package/src/bootstrap.ts +118 -0
  54. package/src/client/board.tsx +61 -0
  55. package/src/client/contract.ts +58 -0
  56. package/src/client/derive.ts +241 -0
  57. package/src/client/index.ts +28 -0
  58. package/src/client/inspector.tsx +49 -0
  59. package/src/client/node.ts +156 -0
  60. package/src/client/settings.tsx +18 -0
  61. package/src/client/slots.ts +67 -0
  62. package/src/client/strip.tsx +28 -0
  63. package/src/client.ts +11 -0
  64. package/src/closeout.ts +183 -0
  65. package/src/commands.ts +142 -0
  66. package/src/delegation.ts +306 -0
  67. package/src/enforcement.ts +180 -0
  68. package/src/events.ts +173 -0
  69. package/src/handoff.ts +165 -0
  70. package/src/index.ts +283 -0
  71. package/src/lifecycle.ts +235 -0
  72. package/src/lock.ts +369 -0
  73. package/src/policy.ts +56 -0
  74. package/src/projection.ts +237 -0
  75. package/src/recursive_closeout.tool.ts +35 -0
  76. package/src/recursive_init.tool.ts +28 -0
  77. package/src/recursive_lint.tool.ts +29 -0
  78. package/src/recursive_lock.tool.ts +33 -0
  79. package/src/recursive_scratch.tool.ts +42 -0
  80. package/src/recursive_status.tool.ts +24 -0
  81. package/src/review.ts +178 -0
  82. package/src/router.ts +197 -0
  83. package/src/run.ts +85 -0
  84. package/src/runtime.ts +564 -0
  85. package/src/scratch.ts +85 -0
  86. package/src/status.ts +194 -0
  87. package/src/types.ts +112 -0
  88. package/src/workspace.ts +67 -0
@@ -0,0 +1,12 @@
1
+ # dsh-recursive-mode bundle patch: inserts the RecursiveRuntime service realm and the
2
+ # recursive_status tool over the profile root. The cordis:group realm keeps the service
3
+ # out of the root realm (R2: registered exactly once, no collision on double-mount).
4
+
5
+ - insert:
6
+ - id: recursive-realm
7
+ name: cordis:group
8
+ isolate:
9
+ recursive: true
10
+ config:
11
+ - id: recursive
12
+ name: @try-works/dsh-recursive-mode/src/index.ts
@@ -0,0 +1,35 @@
1
+ export interface BootstrapResult {
2
+ root: string;
3
+ bootstrapped: boolean;
4
+ created: string[];
5
+ existing: string[];
6
+ }
7
+ export interface StageBResult {
8
+ root: string;
9
+ source: 'new' | 'resume';
10
+ bootstrapped: boolean;
11
+ runs: string[];
12
+ activeRunId?: string;
13
+ }
14
+ /**
15
+ * Idempotent scaffold install: creates the /.recursive/ control plane when
16
+ * missing. Never overwrites existing files; preserves unrelated content.
17
+ */
18
+ export declare function bootstrapScaffold(root: string): BootstrapResult;
19
+ /**
20
+ * Enumerate runs as directory names only (bounded O(#dirs)). Never reads
21
+ * run docs; never returns file paths.
22
+ */
23
+ export declare function enumerateRuns(root: string): string[];
24
+ export interface StageBInput {
25
+ root: string;
26
+ source: 'new' | 'resume';
27
+ activeRunId?: string;
28
+ }
29
+ /**
30
+ * Stage B workflow init at agent/session-start. New: bootstrap if missing +
31
+ * enumerate runs. Resume: never re-bootstrap; enumerate + note the active run
32
+ * (the caller re-reads only that run's current phase doc). Always scoped to
33
+ * the given control-plane root.
34
+ */
35
+ export declare function stageBWorkflowInit(input: StageBInput): StageBResult;
@@ -0,0 +1,10 @@
1
+ import type { RecursiveProjection, RecursiveRunCard } from '../types.ts';
2
+ import type { RecursiveProjectionReader } from './contract.ts';
3
+ /** Flatten the worktree-grouped projection into a stable run list. */
4
+ export declare function listRuns(projection: RecursiveProjection | undefined): RecursiveRunCard[];
5
+ export interface BoardProps {
6
+ useProjection: RecursiveProjectionReader;
7
+ }
8
+ export declare function Board({ useProjection }: BoardProps): import("react").DetailedReactHTMLElement<{
9
+ className: string;
10
+ }, HTMLElement>;
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Structural client seams (self-contained). The real @deepseek-ai/dsh-client-*
3
+ * packages are HOST-INJECTED at bundle time via dsh.client.inject (never
4
+ * installed in this package's dependency tree — they depend on workspace:^
5
+ * peers that resolve only inside the DSH workspace). We declare the minimal
6
+ * shapes we consume so the pure client modules type-check and bundle in
7
+ * isolation; the DSH loader links them to the real runtime identities at
8
+ * compose time.
9
+ *
10
+ * One deliberate narrowing: the client only READS (R9 read-only). It never
11
+ * calls back into the host; every host fact arrives through the projection.
12
+ */
13
+ /** SessionEvent-like carrier (the projection/node fold reads events by shape). */
14
+ export interface ClientSessionEvent {
15
+ type: string;
16
+ seq?: number;
17
+ time?: number;
18
+ data?: Record<string, unknown>;
19
+ }
20
+ /** A session header (cwd is the control-plane root). */
21
+ export interface ClientSessionHeader {
22
+ cwd?: string;
23
+ }
24
+ /** Minimal appendable session (log-only write seam). */
25
+ export interface ClientSession {
26
+ header: ClientSessionHeader;
27
+ append(type: string, data: unknown): unknown;
28
+ }
29
+ /** The client root context the bundle receives from the module loader. */
30
+ export interface ClientContext {
31
+ slots: ClientSlots;
32
+ get(name: string): unknown;
33
+ }
34
+ /** A registered slot's options (list/keyed entries carry id/order/label). */
35
+ export interface SlotOptions {
36
+ name: string;
37
+ id?: string;
38
+ order?: number;
39
+ label?: string;
40
+ children?: unknown;
41
+ store?: unknown;
42
+ locale?: unknown;
43
+ registrant?: unknown;
44
+ }
45
+ /** The slot registry surface the client injects into. */
46
+ export interface ClientSlots {
47
+ inject(seat: string, factory: (ctx: unknown) => () => void): () => void;
48
+ register(options: SlotOptions, component: unknown): () => void;
49
+ }
50
+ /** useProjection('recursive') reader — undefined = capability absent. */
51
+ export type RecursiveProjectionReader = (key: 'recursive') => unknown;
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Pure derivation over the projected RecursiveRunCard (Phase D R5/R6/R7):
3
+ * kanban lane mapping, card facts, conversation-node keying, and inspector
4
+ * phase-row expansion. EVERYTHING here is a pure function over the wire card
5
+ * — no React, no fs, no session window, no /.recursive/run/ scraping (the
6
+ * read-only-client + projection-over-files invariant, 00-requirements R9).
7
+ *
8
+ * The card arrives from the 'recursive' session projection (whole value,
9
+ * host-computed); this module only derives presentation from it.
10
+ */
11
+ import type { RecursiveRunCard, RecursiveRunState } from '../types.ts';
12
+ /** The ordered kanban lanes (§11.4): one lane per phase group. */
13
+ export interface RecursiveLane {
14
+ /** Stable lane id. */
15
+ id: string;
16
+ /** Human label. */
17
+ label: string;
18
+ /** Phase-group keys folded into this lane. */
19
+ groups: readonly string[];
20
+ }
21
+ export declare const KANBAN_LANES: readonly RecursiveLane[];
22
+ /** Group id for a phase filename (e.g. '03.5-code-review.md' -> '03.5'); null for non-phase names. */
23
+ export declare function phaseGroupOf(phase: string): string | null;
24
+ /** Kanban lane id for a phase filename. */
25
+ export declare function laneOf(phase: string): string | null;
26
+ /**
27
+ * The run's current-phase lane: the highest-ordered phase group present in the
28
+ * card wins (a run is "at" its furthest phase). No phases -> lane 0.
29
+ */
30
+ export declare function columnForRun(card: RecursiveRunCard): string;
31
+ /** Subagent chip (one per childId, latest status). */
32
+ export interface RecursiveSubagentChip {
33
+ childId: string;
34
+ role: string;
35
+ provider: string;
36
+ status: 'running' | 'done' | 'failed';
37
+ }
38
+ /** Presentation facts derived from one card (§11.4). */
39
+ export interface RecursiveCardFacts {
40
+ runId: string;
41
+ worktreeRoot: string;
42
+ repo?: string;
43
+ template?: string;
44
+ state: RecursiveRunState;
45
+ stateReason?: string;
46
+ /** Phases locked so far. */
47
+ lockedCount: number;
48
+ /** Distinct phase groups present (progress denominator). */
49
+ totalPhases: number;
50
+ /** lockedCount / totalPhases (0 when totalPhases is 0). */
51
+ progress: number;
52
+ /** Any tamper fact present. */
53
+ tampered: boolean;
54
+ /** Latest gate block present. */
55
+ gateBlocked: boolean;
56
+ gateKind?: string;
57
+ /** Run was merged to a repo root. */
58
+ merged: boolean;
59
+ mergedToRepoRoot?: string;
60
+ /** Lock validity: tampered | locked | in-progress. */
61
+ lockValidity: 'tampered' | 'locked' | 'in-progress';
62
+ /** Latest current-phase label (or null). */
63
+ currentPhase: string | null;
64
+ /** Subagent chips, latest status per child. */
65
+ subagents: RecursiveSubagentChip[];
66
+ }
67
+ /** Derive §11.4 presentation facts from one card (no fs, no session). */
68
+ export declare function cardFacts(card: RecursiveRunCard): RecursiveCardFacts;
69
+ /**
70
+ * Stable conversation-node business id: runId + worktreeRoot (§11.6). The
71
+ * worktree root is part of the id so two runs with the same runId in
72
+ * different worktrees never collide — never "latest unfinished".
73
+ */
74
+ export declare function nodeKeyOf(runId: string, worktreeRoot: string): string;
75
+ /** One expanded inspector phase row (§11.5). */
76
+ export interface RecursivePhaseInspectorRow {
77
+ /** Normalized phase key (group only, e.g. '03.5'). */
78
+ phase: string;
79
+ /** Full filename if present, else null (a mandatory-empty row). */
80
+ fileName: string | null;
81
+ status: string;
82
+ lockedAt?: string;
83
+ lockHash?: string;
84
+ /** Whether the row is present in the card (vs a mandatory-empty slot). */
85
+ present: boolean;
86
+ }
87
+ /**
88
+ * Expand a card's phase chain into full inspector rows: the always-shown
89
+ * '03.5' slot (§11.10 mandatory deviation) plus 01.5 when present, and
90
+ * 06/07/08 as three distinct rows (never one merged lane).
91
+ */
92
+ export declare function expandPhaseRows(card: RecursiveRunCard): RecursivePhaseInspectorRow[];
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Client entry (Phase D R4): the browser half of dsh-recursive-mode. Receives
3
+ * the client root context from the DSH loader and registers the board,
4
+ * inspector, conversation node, status strip, and settings page (§11.8).
5
+ * READ-ONLY (R9): every host fact arrives through the recursive projection;
6
+ * this module never touches the filesystem.
7
+ *
8
+ * The apply(ctx) surface mirrors the shipped dsh-client-ui-* packages; the
9
+ * dsh.client.inject list in package.json names the host packages the loader
10
+ * must provide (they are injected at compose time, never installed here).
11
+ */
12
+ import type { ClientContext } from './contract.ts';
13
+ export { recursiveNodeDefinition, RECURSIVE_NODE_KIND, matchRecursiveNode, foldRecursiveNode } from './node.ts';
14
+ export type { RecursiveNodeData, RecursiveNodeState } from './node.ts';
15
+ export { Board, listRuns } from './board.tsx';
16
+ export { Inspector } from './inspector.tsx';
17
+ export { StatusStrip } from './strip.tsx';
18
+ export { RecursiveSettings } from './settings.tsx';
19
+ export type { RecursiveProjectionReader } from './contract.ts';
20
+ /** Browser-half plugin entry (R4). */
21
+ export declare function apply(ctx: ClientContext): void;
@@ -0,0 +1,10 @@
1
+ import type { RecursiveProjectionReader } from './contract.ts';
2
+ export interface InspectorProps {
3
+ runId: string;
4
+ worktreeRoot: string;
5
+ useProjection: RecursiveProjectionReader;
6
+ onBackToToolDetails: () => void;
7
+ }
8
+ export declare function Inspector({ runId, worktreeRoot, useProjection, onBackToToolDetails }: InspectorProps): import("react").DetailedReactHTMLElement<{
9
+ className: string;
10
+ }, HTMLElement>;
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Conversation run node (Phase D R7, §11.6): a structural ConversationNodeDefinition
3
+ * over the recursive/* event family, keyed by runId + worktreeRoot. One compact,
4
+ * live node per run in the Chat view. PURE fold (no React) — the renderer lives
5
+ * in slots.ts.
6
+ *
7
+ * The real ConversationNodeDefinition contract arrives from
8
+ * @deepseek-ai/dsh-client-runtime/client at compose time; the structural shape
9
+ * here is type-compatible with the cookbook surface (match/start/update/
10
+ * buildViewNode + target/kind). The host links the bundle's exports to the real
11
+ * runtime identities.
12
+ */
13
+ import type { ClientSessionEvent } from './contract.ts';
14
+ export declare const RECURSIVE_NODE_KIND = "recursive/run";
15
+ /** The chat-node payload the renderer receives (pure derived state). */
16
+ export interface RecursiveNodeData {
17
+ readonly runId: string;
18
+ readonly worktreeRoot: string;
19
+ readonly state: string;
20
+ readonly currentPhase: string | null;
21
+ readonly lockedCount: number;
22
+ readonly totalPhases: number;
23
+ readonly tampered: boolean;
24
+ readonly gateBlocked: boolean;
25
+ readonly mergedToRepoRoot?: string;
26
+ }
27
+ /** Pure fold state for one run node. */
28
+ export interface RecursiveNodeState {
29
+ runId: string;
30
+ worktreeRoot: string;
31
+ state: string;
32
+ phases: Record<string, {
33
+ phase: string;
34
+ status: string;
35
+ }>;
36
+ tampered: boolean;
37
+ gateBlocked: boolean;
38
+ mergedToRepoRoot?: string;
39
+ }
40
+ /** Extract a stable (runId, worktreeRoot) business id + lifecycle role from one event. */
41
+ export declare function matchRecursiveNode(event: ClientSessionEvent): {
42
+ id: string;
43
+ role: 'start' | 'update';
44
+ } | null;
45
+ /** Fold one recursive/* event into the node state. */
46
+ export declare function foldRecursiveNode(s: RecursiveNodeState | undefined, event: ClientSessionEvent): RecursiveNodeState;
47
+ /** The structural ConversationNodeDefinition (host links to the real contract). */
48
+ export declare const recursiveNodeDefinition: {
49
+ kind: string;
50
+ target: string;
51
+ match: typeof matchRecursiveNode;
52
+ start: (_ctx: unknown, match: {
53
+ event: ClientSessionEvent;
54
+ }) => RecursiveNodeState;
55
+ update: (ctx: {
56
+ state: RecursiveNodeState;
57
+ }, match: {
58
+ event: ClientSessionEvent;
59
+ }) => RecursiveNodeState;
60
+ buildViewNode: (ctx: {
61
+ key: string;
62
+ id: string;
63
+ state?: RecursiveNodeState;
64
+ }) => {
65
+ key: string;
66
+ kind: string;
67
+ id: string;
68
+ target: string;
69
+ data: RecursiveNodeData;
70
+ } | null;
71
+ };
@@ -0,0 +1,6 @@
1
+ export interface RecursiveSettingsProps {
2
+ close: () => void;
3
+ }
4
+ export declare function RecursiveSettings({ close }: RecursiveSettingsProps): import("react").DetailedReactHTMLElement<{
5
+ className: string;
6
+ }, HTMLElement>;
@@ -0,0 +1,7 @@
1
+ import type { ClientContext, RecursiveProjectionReader } from './contract.ts';
2
+ import type { RecursiveProjection } from '../types.ts';
3
+ /** Narrow the projection whole value to the worktree-grouped run map. */
4
+ declare function projectionOf(reader: RecursiveProjectionReader): RecursiveProjection | undefined;
5
+ export declare function registerSlots(ctx: ClientContext): () => void;
6
+ /** Export the projection reader narrow for the board/inspector/strip. */
7
+ export { projectionOf };
@@ -0,0 +1,7 @@
1
+ import type { RecursiveProjectionReader } from './contract.ts';
2
+ export interface StripProps {
3
+ useProjection: RecursiveProjectionReader;
4
+ }
5
+ export declare function StatusStrip({ useProjection }: StripProps): import("react").DetailedReactHTMLElement<{
6
+ className: string;
7
+ }, HTMLElement> | null;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Client-namespace projection of the recursive domain (Phase D R3): a pure
3
+ * re-export of the package's types outlet. Client code imports ONLY the
4
+ * client namespace (repo discipline), so ./client projects the same
5
+ * single-source content ./types serves to host consumers — zero duplication
6
+ * (the goal client.ts pattern).
7
+ *
8
+ * @module dsh-recursive-mode/client
9
+ */
10
+ export type * from './types.ts';