Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
e73a481
feat(cli): TUI prototype with Peccy branding
May 1, 2026
334486c
feat(cli): demo watch gif upload
May 1, 2026
945b149
docs(cedar-hitl): restore and revise HITL gates design, fold adversar…
May 7, 2026
ca76049
feat(cedar-hitl): pin Cedar engines and seed cross-engine parity cont…
May 7, 2026
e32c365
feat(cedar-hitl): three-outcome PolicyEngine core
May 7, 2026
7399f6e
feat(cedar-hitl): approval milestone writers + engine counters
May 7, 2026
4cdeb9f
feat(cedar-hitl): TaskApprovals + AWAITING_APPROVAL transition primit…
May 7, 2026
40c2cd5
feat(cedar-hitl): PreToolUse three-outcome REQUIRE_APPROVAL path
May 7, 2026
78783a9
feat(cedar-hitl): TaskApprovalsTable + SlackUserMapping + status enum
May 7, 2026
ec3b1cc
feat(cedar-hitl): Cedar-wasm layer + wire approval tables into agent …
May 7, 2026
ff74484
feat(cedar-hitl): approve + deny handlers + shared types (Β§7.1, Β§7.2)
May 7, 2026
d7fb4fb
feat(cedar-hitl): get-pending + get-policies + link-slack-user handlers
May 7, 2026
697dea9
feat(cedar-hitl): wire Chunk 5 routes + orchestrator + reconciler + a…
May 7, 2026
f05e6cc
feat(cedar-hitl): Chunk 6 CLI β€” approve / deny / pending / policies
May 7, 2026
faa8722
feat(cedar-hitl): Chunk 7a β€” persist gate counter + IMPL-23 cache obs…
May 7, 2026
c0dd119
feat(cedar-hitl): Chunk 7b β€” persist approval_gate_cap from blueprint
May 7, 2026
d4225d6
feat(cedar-hitl): Chunk 7c β€” observability wrap-up for resolved cap +…
May 8, 2026
91b0483
feat(cedar-hitl): Chunk 8a β€” extend approval outcome event schema
May 8, 2026
fbcc152
feat(cedar-hitl): Chunk 8b β€” ApprovalMetricsPublisher + native CloudW…
May 8, 2026
cf90a7e
docs(cedar-hitl): Chunk 9 β€” sync design doc to Chunks 7b / 8a / 8b
May 8, 2026
349a4d9
feat(cedar-hitl): Chunk 10 review fixes β€” close 2 blockers + tighten …
May 8, 2026
cea0a16
fix(cedar-hitl): suppress AwsSolutions-IAM5 on Runtime ExecutionRole …
May 8, 2026
fb69894
fix(cedar-hitl): E2E deploy-readiness β€” policies bundle + onboarding …
May 11, 2026
785037c
fix(cedar-hitl): E2E approval-flow regressions + CLI parity for --app…
May 12, 2026
36f2f78
Merge branch 'feature/cedar-hitl-engine' into feature/tui-prototype
May 12, 2026
ed255cf
feat(cedar-hitl): close seven follow-ups from the 2026-05-11/12 E2E pass
May 12, 2026
7019663
chore(cedar-hitl): merge upstream/main β€” Slack + Linear integrations
May 13, 2026
b06a785
docs(cedar-hitl): add user-facing HITL approval documentation
May 13, 2026
d3791d6
chore(cedar-hitl): merge upstream/main β€” fanout/SlackNotify refactor …
May 14, 2026
6d5e9db
feat(tui): interactive Ink TUI with Cedar HITL integration
May 14, 2026
9c7077c
Merge branch 'feature/cedar-hitl-engine' into feature/tui-prototype
May 14, 2026
fbb3855
feat(tui): add SOURCE column to TaskList
May 14, 2026
d7f4e92
Merge remote-tracking branch 'upstream/main' into feature/tui-prototype
May 19, 2026
466bbc3
chore(yarn.lock): re-pin TUI deps after upstream merge
May 19, 2026
30be0ca
feat(tui): clipboard image paste + TaskStatusType narrowing
May 19, 2026
57cfa30
fix(tui): zero-install clipboard image paste via osascript / xclip / …
May 19, 2026
aa2bca7
Merge remote-tracking branch 'upstream/main' into feature/tui-prototype
May 19, 2026
f613238
chore(tui): apply prek autofix β€” MIT license headers + import order
May 19, 2026
199c139
fix(tui): surface Cedar HITL Β§11.1 timeout/cap milestones (IMPL-26)
May 19, 2026
4546f10
refactor(cli): share Cedar HITL milestone formatter between TUI and C…
May 19, 2026
554281b
fix(tui): await approve/deny round-trip and surface API failures
May 19, 2026
e9c7197
chore: drop stale package-lock.json (yarn.lock is canonical)
May 20, 2026
0b7392c
fix(tui): split cadence + 2s pending poll, raise server limit to 60/min
May 20, 2026
12ee53f
fix(cli): unblock prek eslint hook + clean baseline lint debt
May 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion cdk/src/constructs/task-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,23 @@ export interface TaskApiProps {
*/
readonly nudgeRateLimitPerMinute?: number;

/**
* Per-user per-minute `GET /v1/pending` rate limit.
*
* The default of 10 was sized for the original CLI-only `bgagent pending`
* workflow where users polled by hand. The TUI's adaptive ladder polls
* `/v1/pending` on a 2-30s cadence and a fast first poll naturally lands
* 20-30 calls in the first minute β€” comfortably above 10. The handler's
* default (`get-pending.ts::PENDING_RATE_LIMIT_PER_MINUTE`) is also 10,
* so omitting this prop preserves the historical behaviour.
*
* Sized for: a single TUI session at 2s sustained cadence (30/min) plus
* room for concurrent CLI `bgagent pending` checks during testing.
*
* @default 60
*/
readonly pendingRateLimitPerMinute?: number;

/**
* The DynamoDB repo config table. When provided, task creation checks
* that the target repository is onboarded before accepting the task.
Expand Down Expand Up @@ -652,12 +669,21 @@ export class TaskApi extends Construct {
props.taskEventsTable.grantReadWriteData(denyTaskFn);

// GetPendingFn β€” GET /pending
// Adds `PENDING_RATE_LIMIT_PER_MINUTE` on top of the shared
// approval env so the per-user rate limit is configurable from
// the construct prop (default 60/min β€” sized to support a
// single TUI session at 2s sustained cadence with headroom for
// concurrent CLI `bgagent pending` calls). Approve/deny don't
// need this var so it stays out of `approvalEnv`.
const getPendingFn = new lambda.NodejsFunction(this, 'GetPendingFn', {
entry: path.join(handlersDir, 'get-pending.ts'),
handler: 'handler',
runtime: Runtime.NODEJS_24_X,
architecture: Architecture.ARM_64,
environment: approvalEnv,
environment: {
...approvalEnv,
PENDING_RATE_LIMIT_PER_MINUTE: String(props.pendingRateLimitPerMinute ?? 60),
},
bundling: commonBundling,
timeout: Duration.seconds(10),
memorySize: 256,
Expand Down
9 changes: 9 additions & 0 deletions cli/.eslintrc.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

47 changes: 47 additions & 0 deletions cli/docs/recordings/demo-approvals.tape
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Approval flow β€” list β†’ detail β†’ approve/deny
# Run: vhs demo-approvals.tape

Output demo-approvals.gif
Set FontSize 14
Set Width 1200
Set Height 700
Set Padding 20

Type "npm run tui"
Enter
Sleep 3s
Type " "
Sleep 1s

# Go to Approvals
Type "3"
Sleep 1.5s

# Browse approvals
Down
Sleep 0.5s
Up
Sleep 1s

# Drill into detail
Enter
Sleep 3s

# Deny with confirmation
Type "d"
Sleep 1s
# See the confirm dialog
Sleep 1.5s
# Cancel
Type "n"
Sleep 1s

# Approve instead
Type "a"
Sleep 1.5s

# Back to list
Escape
Sleep 1s

Type "q"
Binary file added cli/docs/recordings/demo-full.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
115 changes: 115 additions & 0 deletions cli/docs/recordings/demo-full.tape
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# Full TUI Demo β€” splash β†’ all panels
# Run: vhs demo-full.tape

Output demo-full.gif
Set FontSize 14
Set Width 1200
Set Height 700
Set Padding 20

# Start the TUI
Type "npm run tui"
Enter
Sleep 3s

# Splash screen visible β€” press key to dismiss
Type " "
Sleep 1.5s

# Tasks panel β€” navigate list
Sleep 1s
Down
Sleep 0.5s
Down
Sleep 0.5s
Up
Sleep 1s

# Select first task β†’ Watch
Enter
Sleep 3s

# Watch events streaming in...
Sleep 3s

# Scroll up through events
Up
Up
Up
Sleep 1s
# Scroll back down
Down
Down
Down
Sleep 1s

# Nudge the agent
Type "n"
Sleep 0.5s
Type "focus on the unit tests first"
Sleep 0.5s
Enter
Sleep 1.5s

# Switch to Approvals
Type "3"
Sleep 1.5s

# Drill into detail
Enter
Sleep 2s

# Approve
Type "a"
Sleep 1s

# Back to list
Escape
Sleep 1s

# Switch to Policies
Type "4"
Sleep 1s

# View a policy detail
Down
Down
Enter
Sleep 2s

# Navigate while detail stays open
Down
Sleep 1s
Down
Sleep 1s

# Close detail
Escape
Sleep 1s

# Switch to Submit (New Task)
Type "5"
Sleep 1s

# Select repo
Down
Sleep 0.5s
Enter
Sleep 0.5s

# Type instructions
Enter
Type "Add integration tests for the payment service"
Enter
Sleep 1s

# Submit
Down
Down
Down
Enter
Sleep 2s

# Quit
Type "q"
Sleep 0.5s
20 changes: 20 additions & 0 deletions cli/docs/recordings/demo-splash.tape
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Splash screen β€” just the Peccy animation
# Run: vhs demo-splash.tape

Output demo-splash.gif
Set FontSize 16
Set Width 800
Set Height 500
Set Padding 20

Type "npm run tui"
Enter

# Let the splash play for the full Peccy animation cycle
Sleep 5s

# Dismiss
Type " "
Sleep 2s

Type "q"
Binary file added cli/docs/recordings/demo-watch.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
52 changes: 52 additions & 0 deletions cli/docs/recordings/demo-watch.tape
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Watch panel β€” event streaming + inline approval + nudge
# Run: vhs demo-watch.tape

Output demo-watch.gif
Set FontSize 14
Set Width 1200
Set Height 700
Set Padding 20

Type "npm run tui"
Enter
Sleep 3s
Type " "
Sleep 1s

# Select a task
Enter
Sleep 5s

# Events streaming in...
Sleep 5s

# Scroll up through history
Up
Up
Up
Up
Sleep 2s

# Back to live
Down
Down
Down
Down
Sleep 2s

# Approve inline
Type "a"
Sleep 1.5s

# Nudge
Type "n"
Sleep 0.5s
Type "please add error handling"
Enter
Sleep 2s

# Back to tasks
Escape
Sleep 1s

Type "q"
49 changes: 49 additions & 0 deletions cli/jest.tui.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/* eslint-disable @typescript-eslint/no-require-imports */
/**
* Separate Jest config for the TUI panel tests. These need the real
* Ink runtime (which is pure ESM), so we opt them into Jest's
* experimental VM-modules ESM path. Run with:
*
* NODE_OPTIONS=--experimental-vm-modules npx jest --config jest.tui.config.cjs
*
* The main Jest config keeps CommonJS + `moduleNameMapper` for the
* bulk of the test suite; only panel tests that actually mount Ink
* components go through this config.
*/
module.exports = {
rootDir: '.',
testMatch: ['<rootDir>/test/tui-panels/**/*.test.@(ts|tsx)'],
testPathIgnorePatterns: ['/node_modules/'],
// Strip the `.js` suffix TUI sources use (Node16 ESM style) so
// Jest's resolver finds the `.ts` / `.tsx` sources.
moduleNameMapper: {
'^(\\.{1,2}/.*)\\.js$': '$1',
},
extensionsToTreatAsEsm: ['.ts', '.tsx'],
transform: {
'^.+\\.[jt]sx?$': [
'ts-jest',
{
tsconfig: 'tsconfig.dev.json',
useESM: true,
},
],
},
// Ink + ink-testing-library are ESM; Jest's default transformIgnorePatterns
// skips node_modules, so we whitelist the ones we need compiled.
transformIgnorePatterns: [
'node_modules/(?!(ink|ink-testing-library|chalk|cli-truncate|slice-ansi|string-width|strip-ansi|ansi-regex|ansi-styles|figures|is-fullwidth-code-point|emoji-regex|code-excerpt|indent-string|cli-cursor|cli-boxes|restore-cursor|widest-line|wrap-ansi|type-fest|auto-bind|yoga-layout|@alcalzone/ansi-tokenize|is-unicode-supported|is-in-ci|signal-exit|terminal-size|tagged-tag|xml-naming|uuid)/)',
],
testEnvironment: 'node',
clearMocks: true,
// Coverage off for panel smokes β€” the coverage gate in the main config
// already covers the pure logic; panels are about interaction, not
// line-coverage gain.
collectCoverage: false,
// Ink keeps terminal-size polling + raw-mode listeners alive after
// unmount in ways that leak into Jest's worker. We `forceExit` so the
// suite doesn't hang for the 5 s default. Tests themselves assert all
// behaviour before that point; `forceExit` only affects post-pass
// teardown.
forceExit: true,
};
Loading
Loading