@levu/snap 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.
- package/.github/workflows/ci.yml +26 -0
- package/README.md +49 -0
- package/dist/cli/help-command.d.ts +1 -0
- package/dist/cli/help-command.js +1 -0
- package/dist/cli-entry.d.ts +1 -0
- package/dist/cli-entry.js +80 -0
- package/dist/core/contracts/action-contract.d.ts +25 -0
- package/dist/core/contracts/action-contract.js +1 -0
- package/dist/core/contracts/help-contract.d.ts +18 -0
- package/dist/core/contracts/help-contract.js +1 -0
- package/dist/core/contracts/module-contract.d.ts +6 -0
- package/dist/core/contracts/module-contract.js +1 -0
- package/dist/core/errors/framework-errors.d.ts +19 -0
- package/dist/core/errors/framework-errors.js +26 -0
- package/dist/core/registry/action-registry.d.ts +16 -0
- package/dist/core/registry/action-registry.js +52 -0
- package/dist/help/help-command.d.ts +8 -0
- package/dist/help/help-command.js +21 -0
- package/dist/help/help-model.d.ts +9 -0
- package/dist/help/help-model.js +1 -0
- package/dist/help/help-renderer.d.ts +2 -0
- package/dist/help/help-renderer.js +16 -0
- package/dist/help/hierarchy-resolver.d.ts +3 -0
- package/dist/help/hierarchy-resolver.js +43 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +8 -0
- package/dist/modules/sample-content/module.d.ts +3 -0
- package/dist/modules/sample-content/module.js +61 -0
- package/dist/modules/sample-system/module.d.ts +3 -0
- package/dist/modules/sample-system/module.js +71 -0
- package/dist/runtime/dispatch.d.ts +11 -0
- package/dist/runtime/dispatch.js +47 -0
- package/dist/runtime/engine.d.ts +13 -0
- package/dist/runtime/engine.js +44 -0
- package/dist/runtime/mode-resolver.d.ts +8 -0
- package/dist/runtime/mode-resolver.js +8 -0
- package/dist/runtime/resume-store.d.ts +13 -0
- package/dist/runtime/resume-store.js +45 -0
- package/dist/runtime/runtime-context.d.ts +9 -0
- package/dist/runtime/runtime-context.js +1 -0
- package/dist/runtime/state-machine.d.ts +32 -0
- package/dist/runtime/state-machine.js +50 -0
- package/dist/src/cli/help-command.d.ts +1 -0
- package/dist/src/cli/help-command.js +1 -0
- package/dist/src/cli-entry.d.ts +1 -0
- package/dist/src/cli-entry.js +80 -0
- package/dist/src/core/contracts/action-contract.d.ts +25 -0
- package/dist/src/core/contracts/action-contract.js +1 -0
- package/dist/src/core/contracts/help-contract.d.ts +18 -0
- package/dist/src/core/contracts/help-contract.js +1 -0
- package/dist/src/core/contracts/module-contract.d.ts +6 -0
- package/dist/src/core/contracts/module-contract.js +1 -0
- package/dist/src/core/errors/framework-errors.d.ts +19 -0
- package/dist/src/core/errors/framework-errors.js +26 -0
- package/dist/src/core/registry/action-registry.d.ts +16 -0
- package/dist/src/core/registry/action-registry.js +52 -0
- package/dist/src/help/help-command.d.ts +8 -0
- package/dist/src/help/help-command.js +21 -0
- package/dist/src/help/help-model.d.ts +9 -0
- package/dist/src/help/help-model.js +1 -0
- package/dist/src/help/help-renderer.d.ts +2 -0
- package/dist/src/help/help-renderer.js +16 -0
- package/dist/src/help/hierarchy-resolver.d.ts +3 -0
- package/dist/src/help/hierarchy-resolver.js +43 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.js +8 -0
- package/dist/src/modules/sample-content/module.d.ts +3 -0
- package/dist/src/modules/sample-content/module.js +61 -0
- package/dist/src/modules/sample-system/module.d.ts +3 -0
- package/dist/src/modules/sample-system/module.js +71 -0
- package/dist/src/runtime/dispatch.d.ts +11 -0
- package/dist/src/runtime/dispatch.js +47 -0
- package/dist/src/runtime/engine.d.ts +13 -0
- package/dist/src/runtime/engine.js +44 -0
- package/dist/src/runtime/mode-resolver.d.ts +8 -0
- package/dist/src/runtime/mode-resolver.js +8 -0
- package/dist/src/runtime/resume-store.d.ts +13 -0
- package/dist/src/runtime/resume-store.js +45 -0
- package/dist/src/runtime/runtime-context.d.ts +9 -0
- package/dist/src/runtime/runtime-context.js +1 -0
- package/dist/src/runtime/state-machine.d.ts +32 -0
- package/dist/src/runtime/state-machine.js +50 -0
- package/dist/src/tui/accessibility-footer.d.ts +7 -0
- package/dist/src/tui/accessibility-footer.js +4 -0
- package/dist/src/tui/component-adapters/confirm.d.ts +5 -0
- package/dist/src/tui/component-adapters/confirm.js +3 -0
- package/dist/src/tui/component-adapters/group.d.ts +5 -0
- package/dist/src/tui/component-adapters/group.js +7 -0
- package/dist/src/tui/component-adapters/multiselect.d.ts +10 -0
- package/dist/src/tui/component-adapters/multiselect.js +9 -0
- package/dist/src/tui/component-adapters/select.d.ts +10 -0
- package/dist/src/tui/component-adapters/select.js +7 -0
- package/dist/src/tui/component-adapters/text.d.ts +6 -0
- package/dist/src/tui/component-adapters/text.js +7 -0
- package/dist/src/tui/interrupt-handlers.d.ts +7 -0
- package/dist/src/tui/interrupt-handlers.js +7 -0
- package/dist/tests/e2e/cli-smoke.e2e.test.d.ts +1 -0
- package/dist/tests/e2e/cli-smoke.e2e.test.js +16 -0
- package/dist/tests/integration/runtime-dispatch.integration.test.d.ts +1 -0
- package/dist/tests/integration/runtime-dispatch.integration.test.js +20 -0
- package/dist/tests/transcript/help.transcript.test.d.ts +1 -0
- package/dist/tests/transcript/help.transcript.test.js +18 -0
- package/dist/tests/unit/state-machine.test.d.ts +1 -0
- package/dist/tests/unit/state-machine.test.js +20 -0
- package/dist/tui/accessibility-footer.d.ts +7 -0
- package/dist/tui/accessibility-footer.js +4 -0
- package/dist/tui/component-adapters/confirm.d.ts +5 -0
- package/dist/tui/component-adapters/confirm.js +3 -0
- package/dist/tui/component-adapters/group.d.ts +5 -0
- package/dist/tui/component-adapters/group.js +7 -0
- package/dist/tui/component-adapters/multiselect.d.ts +10 -0
- package/dist/tui/component-adapters/multiselect.js +9 -0
- package/dist/tui/component-adapters/select.d.ts +10 -0
- package/dist/tui/component-adapters/select.js +7 -0
- package/dist/tui/component-adapters/text.d.ts +6 -0
- package/dist/tui/component-adapters/text.js +7 -0
- package/dist/tui/interrupt-handlers.d.ts +7 -0
- package/dist/tui/interrupt-handlers.js +7 -0
- package/dist/vitest.config.d.ts +2 -0
- package/dist/vitest.config.js +7 -0
- package/docs/help-contract-spec.md +29 -0
- package/docs/module-authoring-guide.md +52 -0
- package/package.json +20 -0
- package/plans/260209-1547-hub-dual-runtime-framework/phase-01-foundation-and-contracts.md +71 -0
- package/plans/260209-1547-hub-dual-runtime-framework/phase-02-runtime-and-state-machine.md +76 -0
- package/plans/260209-1547-hub-dual-runtime-framework/phase-03-tui-components-and-policies.md +71 -0
- package/plans/260209-1547-hub-dual-runtime-framework/phase-04-help-system-and-ai-readability.md +69 -0
- package/plans/260209-1547-hub-dual-runtime-framework/phase-05-testing-and-quality-gates.md +79 -0
- package/plans/260209-1547-hub-dual-runtime-framework/phase-06-sample-modules-and-adoption.md +75 -0
- package/plans/260209-1547-hub-dual-runtime-framework/plan.md +105 -0
- package/plans/260209-1547-hub-dual-runtime-framework/reports/planner-report.md +27 -0
- package/plans/260209-1547-hub-dual-runtime-framework/research/researcher-01-report.md +166 -0
- package/plans/260209-1547-hub-dual-runtime-framework/research/researcher-02-report.md +87 -0
- package/plans/260209-1547-hub-dual-runtime-framework/scout/scout-01-report.md +24 -0
- package/src/cli/help-command.ts +1 -0
- package/src/cli-entry.ts +83 -0
- package/src/core/contracts/action-contract.ts +30 -0
- package/src/core/contracts/help-contract.ts +20 -0
- package/src/core/contracts/module-contract.ts +7 -0
- package/src/core/errors/framework-errors.ts +26 -0
- package/src/core/registry/action-registry.ts +94 -0
- package/src/help/help-command.ts +32 -0
- package/src/help/help-model.ts +10 -0
- package/src/help/help-renderer.ts +21 -0
- package/src/help/hierarchy-resolver.ts +54 -0
- package/src/index.ts +10 -0
- package/src/modules/sample-content/module.ts +66 -0
- package/src/modules/sample-system/module.ts +74 -0
- package/src/runtime/dispatch.ts +64 -0
- package/src/runtime/engine.ts +59 -0
- package/src/runtime/mode-resolver.ts +18 -0
- package/src/runtime/resume-store.ts +53 -0
- package/src/runtime/runtime-context.ts +10 -0
- package/src/runtime/state-machine.ts +77 -0
- package/src/tui/accessibility-footer.ts +11 -0
- package/src/tui/component-adapters/confirm.ts +8 -0
- package/src/tui/component-adapters/group.ts +12 -0
- package/src/tui/component-adapters/multiselect.ts +22 -0
- package/src/tui/component-adapters/select.ts +18 -0
- package/src/tui/component-adapters/text.ts +13 -0
- package/src/tui/interrupt-handlers.ts +15 -0
- package/tests/e2e/cli-smoke.e2e.test.ts +19 -0
- package/tests/integration/runtime-dispatch.integration.test.ts +23 -0
- package/tests/transcript/help.transcript.test.ts +20 -0
- package/tests/unit/state-machine.test.ts +22 -0
- package/tsconfig.build.json +9 -0
- package/tsconfig.json +17 -0
- package/vitest.config.ts +8 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { createRegistry } from '../../src/index.js';
|
|
3
|
+
import sampleContentModule from '../../src/modules/sample-content/module.js';
|
|
4
|
+
import sampleSystemModule from '../../src/modules/sample-system/module.js';
|
|
5
|
+
import { dispatchAction } from '../../src/runtime/dispatch.js';
|
|
6
|
+
describe('integration dispatch runtime', () => {
|
|
7
|
+
it('dispatches commandline action with required args', async () => {
|
|
8
|
+
const registry = createRegistry([sampleContentModule, sampleSystemModule]);
|
|
9
|
+
const result = await dispatchAction({
|
|
10
|
+
registry,
|
|
11
|
+
moduleId: 'content',
|
|
12
|
+
actionId: 'slugify',
|
|
13
|
+
args: { text: 'Hello Integration Test' },
|
|
14
|
+
isTTY: true
|
|
15
|
+
});
|
|
16
|
+
expect(result.ok).toBe(true);
|
|
17
|
+
expect(result.mode).toBe('commandline');
|
|
18
|
+
expect(result.data).toBe('hello-integration-test');
|
|
19
|
+
});
|
|
20
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { renderHelp } from '../../src/help/help-renderer.js';
|
|
3
|
+
import { resolveHelpHierarchy } from '../../src/help/hierarchy-resolver.js';
|
|
4
|
+
import sampleContentModule from '../../src/modules/sample-content/module.js';
|
|
5
|
+
describe('transcript help output', () => {
|
|
6
|
+
it('renders deterministic action help transcript', () => {
|
|
7
|
+
const views = resolveHelpHierarchy([sampleContentModule], 'content', 'slugify');
|
|
8
|
+
const output = renderHelp(views);
|
|
9
|
+
expect(output).toContain('# HELP');
|
|
10
|
+
expect(output).toContain('MODULE: content');
|
|
11
|
+
expect(output).toContain('ACTION: slugify');
|
|
12
|
+
expect(output).toContain('## SUMMARY');
|
|
13
|
+
expect(output).toContain('## ARGS');
|
|
14
|
+
expect(output).toContain('## EXAMPLES');
|
|
15
|
+
expect(output).toContain('## USE-CASES');
|
|
16
|
+
expect(output).toContain('## KEYBINDINGS');
|
|
17
|
+
});
|
|
18
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { StateMachine } from '../../src/runtime/state-machine.js';
|
|
3
|
+
describe('state-machine', () => {
|
|
4
|
+
it('supports next/back/jump/exit transitions', () => {
|
|
5
|
+
const machine = new StateMachine('wf', [
|
|
6
|
+
{ id: 'a', label: 'A' },
|
|
7
|
+
{ id: 'b', label: 'B' },
|
|
8
|
+
{ id: 'c', label: 'C' }
|
|
9
|
+
]);
|
|
10
|
+
expect(machine.currentNode().id).toBe('a');
|
|
11
|
+
machine.transition({ type: 'next' });
|
|
12
|
+
expect(machine.currentNode().id).toBe('b');
|
|
13
|
+
machine.transition({ type: 'jump', targetNodeId: 'c' });
|
|
14
|
+
expect(machine.currentNode().id).toBe('c');
|
|
15
|
+
machine.transition({ type: 'back' });
|
|
16
|
+
expect(machine.currentNode().id).toBe('b');
|
|
17
|
+
machine.transition({ type: 'exit' });
|
|
18
|
+
expect(machine.snapshot().exited).toBe(true);
|
|
19
|
+
});
|
|
20
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface MultiSelectOption {
|
|
2
|
+
value: string;
|
|
3
|
+
label: string;
|
|
4
|
+
}
|
|
5
|
+
export interface MultiSelectPromptInput {
|
|
6
|
+
message: string;
|
|
7
|
+
options: MultiSelectOption[];
|
|
8
|
+
initialValues?: string[];
|
|
9
|
+
}
|
|
10
|
+
export declare const runMultiSelectPrompt: (input: MultiSelectPromptInput) => Promise<string[]>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const runMultiSelectPrompt = async (input) => {
|
|
2
|
+
if (input.options.length === 0) {
|
|
3
|
+
throw new Error(`No options available for multiselect prompt: ${input.message}`);
|
|
4
|
+
}
|
|
5
|
+
if (input.initialValues && input.initialValues.length > 0) {
|
|
6
|
+
return input.initialValues.filter((value) => input.options.some((option) => option.value === value));
|
|
7
|
+
}
|
|
8
|
+
return [input.options[0].value];
|
|
9
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface SelectOption {
|
|
2
|
+
value: string;
|
|
3
|
+
label: string;
|
|
4
|
+
}
|
|
5
|
+
export interface SelectPromptInput {
|
|
6
|
+
message: string;
|
|
7
|
+
options: SelectOption[];
|
|
8
|
+
initialValue?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare const runSelectPrompt: (input: SelectPromptInput) => Promise<string>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ExitCode } from '../core/errors/framework-errors.js';
|
|
2
|
+
export type InterruptSignal = 'SIGINT' | 'ESC' | 'TIMEOUT';
|
|
3
|
+
export interface InterruptResult {
|
|
4
|
+
exitCode: ExitCode;
|
|
5
|
+
reason: string;
|
|
6
|
+
}
|
|
7
|
+
export declare const handleInterrupt: (signal: InterruptSignal) => InterruptResult;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ExitCode } from '../core/errors/framework-errors.js';
|
|
2
|
+
export const handleInterrupt = (signal) => {
|
|
3
|
+
if (signal === 'TIMEOUT') {
|
|
4
|
+
return { exitCode: ExitCode.VALIDATION_ERROR, reason: 'Workflow timed out' };
|
|
5
|
+
}
|
|
6
|
+
return { exitCode: ExitCode.INTERRUPTED, reason: `Interrupted by ${signal}` };
|
|
7
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Help Contract Spec
|
|
2
|
+
|
|
3
|
+
## Output Contract
|
|
4
|
+
|
|
5
|
+
Help renderer must produce deterministic text sections in this order:
|
|
6
|
+
|
|
7
|
+
1. `# HELP`
|
|
8
|
+
2. `MODULE: <module-id>`
|
|
9
|
+
3. `ACTION: <action-id|*>`
|
|
10
|
+
4. Section blocks:
|
|
11
|
+
- `## MODULE`
|
|
12
|
+
- `## ACTIONS`
|
|
13
|
+
- `## SUMMARY`
|
|
14
|
+
- `## ARGS`
|
|
15
|
+
- `## EXAMPLES`
|
|
16
|
+
- `## USE-CASES`
|
|
17
|
+
- `## KEYBINDINGS`
|
|
18
|
+
|
|
19
|
+
Each line item in section body uses `- <content>`.
|
|
20
|
+
|
|
21
|
+
## CLI Levels
|
|
22
|
+
|
|
23
|
+
- `hub -h` => module overview list.
|
|
24
|
+
- `hub -h <module>` => module scoped list.
|
|
25
|
+
- `hub -h <module> <action>` => action detail.
|
|
26
|
+
|
|
27
|
+
## Validation
|
|
28
|
+
|
|
29
|
+
Missing target returns non-zero exit code with deterministic error message.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Module Authoring Guide
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
|
|
5
|
+
Define actions once with full triad contract:
|
|
6
|
+
|
|
7
|
+
- `tui` flow steps
|
|
8
|
+
- `commandline` required/optional args
|
|
9
|
+
- `help` metadata
|
|
10
|
+
|
|
11
|
+
## Minimal Module Shape
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import type { ModuleContract } from '../core/contracts/module-contract.js';
|
|
15
|
+
import { ExitCode } from '../core/errors/framework-errors.js';
|
|
16
|
+
|
|
17
|
+
const moduleContract: ModuleContract = {
|
|
18
|
+
moduleId: 'example',
|
|
19
|
+
description: 'Example module',
|
|
20
|
+
actions: [
|
|
21
|
+
{
|
|
22
|
+
actionId: 'run',
|
|
23
|
+
description: 'Run example action',
|
|
24
|
+
tui: { steps: ['collect-input', 'confirm'] },
|
|
25
|
+
commandline: { requiredArgs: ['name'] },
|
|
26
|
+
help: {
|
|
27
|
+
summary: 'Run example with one name argument.',
|
|
28
|
+
args: [{ name: 'name', required: true, description: 'Target name' }],
|
|
29
|
+
examples: ['hub example run --name=alice'],
|
|
30
|
+
useCases: [{ name: 'default', description: 'Basic usage', command: 'hub example run --name=alice' }],
|
|
31
|
+
keybindings: ['Enter confirm', 'Esc cancel']
|
|
32
|
+
},
|
|
33
|
+
run: async (context) => ({
|
|
34
|
+
ok: true,
|
|
35
|
+
mode: context.mode,
|
|
36
|
+
exitCode: ExitCode.SUCCESS,
|
|
37
|
+
data: `hello ${String(context.args.name ?? '')}`
|
|
38
|
+
})
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export default moduleContract;
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Register Module
|
|
47
|
+
|
|
48
|
+
Add module to registry bootstrapping in `/Users/khang/Documents/repo/snap/src/cli-entry.ts`.
|
|
49
|
+
|
|
50
|
+
## Validation Rules
|
|
51
|
+
|
|
52
|
+
Registration fails if any action misses triad data (`tui`, `commandline`, `help`).
|
package/package.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@levu/snap",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"bin": {
|
|
6
|
+
"snap": "./dist/cli-entry.js"
|
|
7
|
+
},
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "tsc -p tsconfig.build.json",
|
|
10
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
11
|
+
"test": "vitest run",
|
|
12
|
+
"dev": "tsx src/cli-entry.ts"
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@types/node": "^22.10.2",
|
|
16
|
+
"tsx": "^4.20.3",
|
|
17
|
+
"typescript": "^5.7.2",
|
|
18
|
+
"vitest": "^2.1.8"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Phase 01 — Foundation and contracts
|
|
2
|
+
|
|
3
|
+
## Context links
|
|
4
|
+
- Parent plan: `./plan.md`
|
|
5
|
+
- Inputs: `./scout/scout-01-report.md`, `./research/researcher-01-report.md`, `./research/researcher-02-report.md`
|
|
6
|
+
- Planner summary: `./reports/planner-report.md`
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
- Date: 2026-02-09
|
|
10
|
+
- Description: define core framework contracts and registry model enforcing TUI + CLI + help triad.
|
|
11
|
+
- Priority: P0
|
|
12
|
+
- Implementation status: complete
|
|
13
|
+
- Review status: complete
|
|
14
|
+
|
|
15
|
+
## Key Insights
|
|
16
|
+
- Contract-first is required to prevent CLI/TUI/help drift.
|
|
17
|
+
- Greenfield repo allows clean architecture without migration baggage.
|
|
18
|
+
|
|
19
|
+
## Requirements
|
|
20
|
+
- Functional:
|
|
21
|
+
- Define module/action contract types.
|
|
22
|
+
- Enforce triad presence at registration time.
|
|
23
|
+
- Define error taxonomy and exit-code map.
|
|
24
|
+
- Define runtime context and lifecycle hooks.
|
|
25
|
+
- Non-functional:
|
|
26
|
+
- Type-safe API surface.
|
|
27
|
+
- Minimal public API for v1 (KISS).
|
|
28
|
+
|
|
29
|
+
## Architecture
|
|
30
|
+
<!-- Updated: Validation Session 1 - lock single-package layout for MVP -->
|
|
31
|
+
- Locked MVP packaging: single package layout (`src/*`) with modular folders; no monorepo split in v1.
|
|
32
|
+
- `core/contracts/*` for typed schemas and compile-time helpers.
|
|
33
|
+
- `core/registry/*` for module/action registration and validation.
|
|
34
|
+
- `core/errors/*` for standardized framework errors.
|
|
35
|
+
|
|
36
|
+
## Related code files
|
|
37
|
+
- Modify: none (greenfield)
|
|
38
|
+
- Create:
|
|
39
|
+
- `src/core/contracts/module-contract.ts`
|
|
40
|
+
- `src/core/contracts/action-contract.ts`
|
|
41
|
+
- `src/core/contracts/help-contract.ts`
|
|
42
|
+
- `src/core/registry/action-registry.ts`
|
|
43
|
+
- `src/core/errors/framework-errors.ts`
|
|
44
|
+
- Delete: none
|
|
45
|
+
|
|
46
|
+
## Implementation Steps
|
|
47
|
+
1. Define TypeScript contract interfaces and helper builders.
|
|
48
|
+
2. Implement registry with startup validation.
|
|
49
|
+
3. Add triad completeness checks and diagnostic messages.
|
|
50
|
+
4. Add error codes and exit-code policy map.
|
|
51
|
+
|
|
52
|
+
## Todo list
|
|
53
|
+
- [x] Core contract interfaces defined
|
|
54
|
+
- [x] Registry implemented
|
|
55
|
+
- [x] Triad enforcement implemented
|
|
56
|
+
- [x] Error taxonomy added
|
|
57
|
+
|
|
58
|
+
## Success Criteria
|
|
59
|
+
- Registering incomplete action fails deterministically with clear diagnostics.
|
|
60
|
+
- Complete action contract can be registered and discovered.
|
|
61
|
+
|
|
62
|
+
## Risk Assessment
|
|
63
|
+
- Risk: over-modeling too early.
|
|
64
|
+
- Mitigation: keep v1 contracts minimal and extensible.
|
|
65
|
+
|
|
66
|
+
## Security Considerations
|
|
67
|
+
- Validate user-defined metadata before rendering/executing.
|
|
68
|
+
- Avoid arbitrary code execution in registration path.
|
|
69
|
+
|
|
70
|
+
## Next steps
|
|
71
|
+
- Build runtime resolver + state machine in Phase 02.
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Phase 02 — Runtime and state machine
|
|
2
|
+
|
|
3
|
+
## Context links
|
|
4
|
+
- Parent plan: `./plan.md`
|
|
5
|
+
- Depends on: `./phase-01-foundation-and-contracts.md`
|
|
6
|
+
- Research: `./research/researcher-01-report.md`, `./research/researcher-02-report.md`
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
- Date: 2026-02-09
|
|
10
|
+
- Description: implement shared runtime engine and workflow state machine for TUI-default + auto non-interactive behavior.
|
|
11
|
+
- Priority: P0
|
|
12
|
+
- Implementation status: complete
|
|
13
|
+
- Review status: complete
|
|
14
|
+
|
|
15
|
+
## Key Insights
|
|
16
|
+
- One execution engine must serve both TUI and command paths.
|
|
17
|
+
- Mode resolution must be deterministic and safe in non-TTY contexts.
|
|
18
|
+
|
|
19
|
+
## Requirements
|
|
20
|
+
- Functional:
|
|
21
|
+
- Implement runtime resolver: default TUI, auto headless when required args provided.
|
|
22
|
+
- Implement state-machine transitions for flow nodes including `next/back/jump/exit`.
|
|
23
|
+
- Implement persisted resume checkpoints for interrupted multi-step workflows.
|
|
24
|
+
- Implement in-process module loading and action dispatch.
|
|
25
|
+
- Implement unified result envelope and exit semantics.
|
|
26
|
+
- Non-functional:
|
|
27
|
+
- Deterministic behavior for CI/automation.
|
|
28
|
+
- No duplicated business logic across adapters.
|
|
29
|
+
|
|
30
|
+
## Architecture
|
|
31
|
+
<!-- Updated: Validation Session 1 - include jump + resume in MVP -->
|
|
32
|
+
- `runtime/mode-resolver.ts` decides interactive vs non-interactive.
|
|
33
|
+
- `runtime/engine.ts` executes action handlers with shared context.
|
|
34
|
+
- `runtime/state-machine.ts` handles transitions: next/back/jump/exit.
|
|
35
|
+
- `runtime/resume-store.ts` persists and restores workflow checkpoints.
|
|
36
|
+
- `runtime/dispatch.ts` maps parser result to action contract.
|
|
37
|
+
|
|
38
|
+
## Related code files
|
|
39
|
+
- Modify: none (greenfield)
|
|
40
|
+
- Create:
|
|
41
|
+
- `src/runtime/mode-resolver.ts`
|
|
42
|
+
- `src/runtime/engine.ts`
|
|
43
|
+
- `src/runtime/state-machine.ts`
|
|
44
|
+
- `src/runtime/resume-store.ts`
|
|
45
|
+
- `src/runtime/dispatch.ts`
|
|
46
|
+
- `src/runtime/runtime-context.ts`
|
|
47
|
+
- Delete: none
|
|
48
|
+
|
|
49
|
+
## Implementation Steps
|
|
50
|
+
1. Implement mode resolver with strict decision tree.
|
|
51
|
+
2. Implement shared runtime executor and result envelope.
|
|
52
|
+
3. Implement workflow state-machine and transition guards including jump.
|
|
53
|
+
4. Implement resume checkpoint store and restore path.
|
|
54
|
+
5. Wire dispatch path from parser to runtime.
|
|
55
|
+
|
|
56
|
+
## Todo list
|
|
57
|
+
- [x] Mode resolver implemented
|
|
58
|
+
- [x] Runtime engine implemented
|
|
59
|
+
- [x] State machine with jump implemented
|
|
60
|
+
- [x] Resume checkpoint store implemented
|
|
61
|
+
- [x] Dispatch integration complete
|
|
62
|
+
|
|
63
|
+
## Success Criteria
|
|
64
|
+
- Same action handler runs correctly from both TUI and command invocation.
|
|
65
|
+
- Missing args in non-TTY returns strict help/error output without prompt hang.
|
|
66
|
+
|
|
67
|
+
## Risk Assessment
|
|
68
|
+
- Risk: mode ambiguity in mixed argument scenarios.
|
|
69
|
+
- Mitigation: explicit precedence rules and diagnostics.
|
|
70
|
+
|
|
71
|
+
## Security Considerations
|
|
72
|
+
- Validate parsed input before dispatch.
|
|
73
|
+
- Enforce safe defaults for cancellation/timeouts.
|
|
74
|
+
|
|
75
|
+
## Next steps
|
|
76
|
+
- Build TUI component adapters and edge policies in Phase 03.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Phase 03 — TUI components and policies
|
|
2
|
+
|
|
3
|
+
## Context links
|
|
4
|
+
- Parent plan: `./plan.md`
|
|
5
|
+
- Depends on: `./phase-02-runtime-and-state-machine.md`
|
|
6
|
+
- Research: `./research/researcher-01-report.md`
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
- Date: 2026-02-09
|
|
10
|
+
- Description: implement clack-based component adapters, accessibility footer, and policy-driven edge handling.
|
|
11
|
+
- Priority: P1
|
|
12
|
+
- Implementation status: complete
|
|
13
|
+
- Review status: complete
|
|
14
|
+
|
|
15
|
+
## Key Insights
|
|
16
|
+
- Use clack primitives fully, wrap them in framework contracts.
|
|
17
|
+
- Accessibility line helps both humans and AI snapshots understand current state.
|
|
18
|
+
|
|
19
|
+
## Requirements
|
|
20
|
+
- Functional:
|
|
21
|
+
- Support clack prompts/core patterns (select, multiselect, confirm, text, groups, task logs/spinners).
|
|
22
|
+
- Implement framework wrapper components with validation hooks.
|
|
23
|
+
- Add accessibility footer with current node, selection, keybind hints.
|
|
24
|
+
- Enforce ESC/Ctrl+C/error/invalid-input policies with configurable actions.
|
|
25
|
+
- Non-functional:
|
|
26
|
+
- Async-safe prompt flows.
|
|
27
|
+
- Non-TTY fallback to runtime resolver path.
|
|
28
|
+
|
|
29
|
+
## Architecture
|
|
30
|
+
- `tui/component-adapters/*` wraps clack APIs.
|
|
31
|
+
- `tui/accessibility-footer.ts` renders stable context text.
|
|
32
|
+
- `tui/interrupt-handlers.ts` maps cancel signals to policy engine.
|
|
33
|
+
|
|
34
|
+
## Related code files
|
|
35
|
+
- Modify: none (greenfield)
|
|
36
|
+
- Create:
|
|
37
|
+
- `src/tui/component-adapters/select.ts`
|
|
38
|
+
- `src/tui/component-adapters/multiselect.ts`
|
|
39
|
+
- `src/tui/component-adapters/confirm.ts`
|
|
40
|
+
- `src/tui/component-adapters/text.ts`
|
|
41
|
+
- `src/tui/component-adapters/group.ts`
|
|
42
|
+
- `src/tui/accessibility-footer.ts`
|
|
43
|
+
- `src/tui/interrupt-handlers.ts`
|
|
44
|
+
- Delete: none
|
|
45
|
+
|
|
46
|
+
## Implementation Steps
|
|
47
|
+
1. Implement component wrappers and shared adapter interfaces.
|
|
48
|
+
2. Implement input validation and cancellation normalization.
|
|
49
|
+
3. Add accessibility footer renderer.
|
|
50
|
+
4. Integrate policy engine hooks for edge-case handling.
|
|
51
|
+
|
|
52
|
+
## Todo list
|
|
53
|
+
- [x] Core component wrappers implemented
|
|
54
|
+
- [x] Validation/cancel normalization implemented
|
|
55
|
+
- [x] Accessibility footer implemented
|
|
56
|
+
- [x] Policy hooks integrated
|
|
57
|
+
|
|
58
|
+
## Success Criteria
|
|
59
|
+
- TUI flows execute with consistent keybinding/interrupt behavior.
|
|
60
|
+
- Accessibility footer appears on each interactive step.
|
|
61
|
+
|
|
62
|
+
## Risk Assessment
|
|
63
|
+
- Risk: terminal compatibility differences.
|
|
64
|
+
- Mitigation: isolate adapter layer and test across OS.
|
|
65
|
+
|
|
66
|
+
## Security Considerations
|
|
67
|
+
- Sanitize untrusted text displayed in terminal.
|
|
68
|
+
- Avoid leaking sensitive values in prompts and logs.
|
|
69
|
+
|
|
70
|
+
## Next steps
|
|
71
|
+
- Implement strict help contract and hierarchy in Phase 04.
|
package/plans/260209-1547-hub-dual-runtime-framework/phase-04-help-system-and-ai-readability.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Phase 04 — Help system and AI readability
|
|
2
|
+
|
|
3
|
+
## Context links
|
|
4
|
+
- Parent plan: `./plan.md`
|
|
5
|
+
- Depends on: `./phase-01-foundation-and-contracts.md`, `./phase-02-runtime-and-state-machine.md`
|
|
6
|
+
- Research: `./research/researcher-01-report.md`
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
- Date: 2026-02-09
|
|
10
|
+
- Description: implement strict hierarchical help outputs for module/action/use-case discovery.
|
|
11
|
+
- Priority: P1
|
|
12
|
+
- Implementation status: complete
|
|
13
|
+
- Review status: complete
|
|
14
|
+
|
|
15
|
+
## Key Insights
|
|
16
|
+
- Text-only can be AI-safe if sections are fixed and deterministic.
|
|
17
|
+
- Help hierarchy must mirror command hierarchy exactly.
|
|
18
|
+
|
|
19
|
+
## Requirements
|
|
20
|
+
<!-- Updated: Validation Session 1 - lock text-only strict help contract for MVP -->
|
|
21
|
+
- Functional:
|
|
22
|
+
- Implement `hub -h`, `hub -h <module>`, `hub -h <module> <use-case>`.
|
|
23
|
+
- Render strict text-only sections with stable ordering and markers.
|
|
24
|
+
- Include keybindings/navigation notes for TUI-relevant actions.
|
|
25
|
+
- Enforce every action defines complete help metadata.
|
|
26
|
+
- Non-functional:
|
|
27
|
+
- No prose drift across runs.
|
|
28
|
+
- Human-readable and parser-friendly formatting.
|
|
29
|
+
|
|
30
|
+
## Architecture
|
|
31
|
+
- `help-registry-view` queries contracts and returns normalized help model.
|
|
32
|
+
- `help-renderer` outputs strict sections and delimiters.
|
|
33
|
+
- `diagnostic-renderer` prints missing args/error guidance in same format family.
|
|
34
|
+
|
|
35
|
+
## Related code files
|
|
36
|
+
- Modify: none (greenfield)
|
|
37
|
+
- Create:
|
|
38
|
+
- `src/help/help-model.ts`
|
|
39
|
+
- `src/help/help-renderer.ts`
|
|
40
|
+
- `src/help/hierarchy-resolver.ts`
|
|
41
|
+
- `src/cli/help-command.ts`
|
|
42
|
+
- Delete: none
|
|
43
|
+
|
|
44
|
+
## Implementation Steps
|
|
45
|
+
1. Define strict help section schema and formatting rules.
|
|
46
|
+
2. Implement hierarchy resolver for module/action/use-case.
|
|
47
|
+
3. Implement renderers for normal help and error-help.
|
|
48
|
+
4. Wire help command to parser/runtime paths.
|
|
49
|
+
|
|
50
|
+
## Todo list
|
|
51
|
+
- [x] Help schema defined
|
|
52
|
+
- [x] Hierarchy resolver implemented
|
|
53
|
+
- [x] Renderer implemented
|
|
54
|
+
- [x] CLI integration complete
|
|
55
|
+
|
|
56
|
+
## Success Criteria
|
|
57
|
+
- All help levels print deterministic sections.
|
|
58
|
+
- Agent can discover command usage without interacting with TUI.
|
|
59
|
+
|
|
60
|
+
## Risk Assessment
|
|
61
|
+
- Risk: over-verbose help harms scanability.
|
|
62
|
+
- Mitigation: concise defaults + expanded use-case mode.
|
|
63
|
+
|
|
64
|
+
## Security Considerations
|
|
65
|
+
- Ensure help/examples never include secrets.
|
|
66
|
+
- Validate untrusted metadata before rendering.
|
|
67
|
+
|
|
68
|
+
## Next steps
|
|
69
|
+
- Add test matrix and quality gates in Phase 05.
|