@mingchuno/agent-workflows 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -6
- package/dist/src/adapters/agents.js +6 -3
- package/dist/src/adapters/hosting.js +16 -10
- package/dist/src/adapters/sdk-protocol.d.ts +3 -3
- package/dist/src/adapters/sdk-protocol.js +9 -7
- package/dist/src/cli.d.ts +1 -1
- package/dist/src/cli.js +40 -19
- package/dist/src/config.d.ts +22 -22
- package/dist/src/config.js +31 -26
- package/dist/src/defaults.d.ts +2 -0
- package/dist/src/defaults.js +2 -0
- package/dist/src/domain.d.ts +24 -4
- package/dist/src/domain.js +10 -3
- package/dist/src/evidence.d.ts +54 -0
- package/dist/src/evidence.js +214 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +1 -0
- package/dist/src/invocation.d.ts +24 -0
- package/dist/src/invocation.js +163 -0
- package/dist/src/operations.d.ts +7 -2
- package/dist/src/operations.js +76 -134
- package/dist/src/prompts.d.ts +28 -0
- package/dist/src/prompts.js +63 -0
- package/dist/src/recovery.d.ts +19 -0
- package/dist/src/recovery.js +99 -0
- package/dist/src/runner.d.ts +5 -0
- package/dist/src/runner.js +145 -18
- package/dist/src/runtime/process.d.ts +2 -0
- package/dist/src/runtime/process.js +41 -12
- package/dist/src/store.d.ts +21 -2
- package/dist/src/store.js +122 -1
- package/dist/src/tui/actions.d.ts +16 -0
- package/dist/src/tui/actions.js +23 -0
- package/dist/src/tui/constants.d.ts +6 -0
- package/dist/src/tui/constants.js +3 -0
- package/dist/src/{tui-data.d.ts → tui/data.d.ts} +8 -6
- package/dist/src/tui/data.js +141 -0
- package/dist/src/tui/dialogs.d.ts +17 -0
- package/dist/src/tui/dialogs.js +149 -0
- package/dist/src/tui/format.d.ts +7 -0
- package/dist/src/tui/format.js +62 -0
- package/dist/src/tui/index.d.ts +2 -0
- package/dist/src/tui/index.js +1 -0
- package/dist/src/tui/layout.d.ts +25 -0
- package/dist/src/tui/layout.js +36 -0
- package/dist/src/tui/log-file.d.ts +26 -0
- package/dist/src/tui/log-file.js +156 -0
- package/dist/src/tui/log.d.ts +11 -0
- package/dist/src/tui/log.js +90 -0
- package/dist/src/tui/monitor.d.ts +8 -0
- package/dist/src/tui/monitor.js +222 -0
- package/dist/src/tui/text.d.ts +3 -0
- package/dist/src/tui/text.js +10 -0
- package/dist/src/tui/use-log-controller.d.ts +27 -0
- package/dist/src/tui/use-log-controller.js +192 -0
- package/dist/src/tui/views.d.ts +17 -0
- package/dist/src/tui/views.js +97 -0
- package/docs/api.md +119 -6
- package/docs/architecture.md +21 -4
- package/docs/configuration.md +137 -5
- package/docs/database.md +7 -0
- package/docs/operations.md +117 -2
- package/docs/providers.md +58 -2
- package/docs/releases.md +34 -79
- package/examples/config.ts +2 -2
- package/package.json +4 -2
- package/dist/src/tui-data.js +0 -89
- package/dist/src/tui.d.ts +0 -5
- package/dist/src/tui.js +0 -69
- package/docs/acceptance.md +0 -35
package/docs/providers.md
CHANGED
|
@@ -6,7 +6,7 @@ Authenticate the selected local agent runtime before starting. Codex SDK uses th
|
|
|
6
6
|
|
|
7
7
|
| Capability | Codex | Copilot |
|
|
8
8
|
| ------------------------------------------- | -------------------------------------------------------------------- | ----------------------------------------------------------------- |
|
|
9
|
-
| Implementation,
|
|
9
|
+
| Implementation, publication, independent review | SDK fresh thread | SDK fresh session |
|
|
10
10
|
| Explicit model/effort validation | Runtime model cache or injected catalog | SDK model catalog or injected catalog |
|
|
11
11
|
| Runtime context controls | Rejected | Compaction/exhaustion utilization fractions |
|
|
12
12
|
| Structured publication/review | Application JSON schema validation | Application JSON schema validation |
|
|
@@ -19,9 +19,48 @@ Codex implementation uses its workspace-write sandbox. Copilot implementation ap
|
|
|
19
19
|
|
|
20
20
|
The runner deliberately does not automatically resume interrupted agent work. Runtime session existence does not establish whether old processes are still writing. Use runtime-specific tools/SDKs to inspect sessions after stopping the runner and establishing ownership; there is no universal session-opening command.
|
|
21
21
|
|
|
22
|
+
## Environment inheritance
|
|
23
|
+
|
|
24
|
+
CLI `--env-file` values reach validation commands, Git subprocesses and agent
|
|
25
|
+
workers through the runner's process environment. SDK callers get the same
|
|
26
|
+
inheritance from their own process environment. The installed Codex SDK forwards
|
|
27
|
+
that environment to its executable; Copilot uses it for its local runtime, with
|
|
28
|
+
SDK-specific adjustments such as removing `NODE_DEBUG`.
|
|
29
|
+
|
|
30
|
+
Commands launched inside a provider remain subject to its runtime configuration.
|
|
31
|
+
For example, Codex's [shell environment policy](https://developers.openai.com/codex/config-advanced/#shell-environment-policy)
|
|
32
|
+
can filter or replace inherited values. The CLI does not override these policies
|
|
33
|
+
or inject environment values into an already-running remote Copilot runtime.
|
|
34
|
+
Controlled executable tests cover the SDK worker boundary; live model-driven
|
|
35
|
+
shell-tool inheritance requires the explicit smoke verification below.
|
|
36
|
+
|
|
22
37
|
## GitHub
|
|
23
38
|
|
|
24
|
-
Set `hosting.origin` to `https://github.com` or the GitHub Enterprise web origin. Repository is `owner/name`; the adapter derives the REST endpoint. `tokenEnv` names the environment variable holding
|
|
39
|
+
Set `hosting.origin` to `https://github.com` or the GitHub Enterprise web origin. Repository is `owner/name`; the adapter derives the REST endpoint. `hosting.tokenEnv` names the environment variable holding the API token, for example `GITHUB_TOKEN`.
|
|
40
|
+
|
|
41
|
+
### Create a fine-grained personal access token
|
|
42
|
+
|
|
43
|
+
In GitHub **Settings → Developer settings → Personal access tokens → Fine-grained tokens → Generate new token**:
|
|
44
|
+
|
|
45
|
+
1. Set an expiration and choose the repository's user or organization as **Resource owner**.
|
|
46
|
+
2. Under **Repository access**, choose **Only select repositories** and select the configured `owner/name`, including for a public repository.
|
|
47
|
+
3. Under **Repository permissions**, grant:
|
|
48
|
+
|
|
49
|
+
| Permission | Access | Used for |
|
|
50
|
+
| ---------- | ------ | -------- |
|
|
51
|
+
| Issues | Read-only | List and recheck issues for intake |
|
|
52
|
+
| Pull requests | Read and write | Find/create draft PRs, check their head, and publish reviews with inline comments |
|
|
53
|
+
| Metadata | Read-only (automatically included) | Required baseline repository access |
|
|
54
|
+
|
|
55
|
+
4. Generate the token and store it through your secret manager in the variable named by `hosting.tokenEnv`. If organization approval is required, wait for approval before starting the runner; pending tokens can only read public resources.
|
|
56
|
+
|
|
57
|
+
**Pull requests must be Read and write.** Reading issues or pushing a branch successfully does not establish permission to create a PR. Missing PR write access can fail the `change-request` step with `Resource not accessible by personal access token` after implementation has completed.
|
|
58
|
+
|
|
59
|
+
Git push uses the checkout's configured remote and Git credentials independently of this API token. The API adapter does not require **Contents** permission. If you also use this PAT for HTTPS Git pushes, grant **Contents: Read and write**; pushing changes to `.github/workflows/` additionally requires **Workflows: Read and write**. Do not embed credentials in remote URLs.
|
|
60
|
+
|
|
61
|
+
If access is denied, check the selected owner/repository, PR write permission, token expiration, organization approval, and the token owner's repository access. If you replace the token value, restart the runner with the updated environment; existing environment variables override `--env-file` values. An already failed run requires explicit [recovery](operations.md#ownership-and-recovery); updating permissions does not restart it.
|
|
62
|
+
|
|
63
|
+
References: GitHub's [PAT creation guide](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens), [issue permissions](https://docs.github.com/en/rest/issues/issues#list-repository-issues), [PR creation permissions](https://docs.github.com/en/rest/pulls/pulls#create-a-pull-request), and [review permissions](https://docs.github.com/en/rest/pulls/reviews#create-a-review-for-a-pull-request).
|
|
25
64
|
|
|
26
65
|
Issue intake paginates and excludes PRs. Publications default to draft. Reviews use the exact commit ID and right-side added lines where valid; other findings appear in the summary.
|
|
27
66
|
|
|
@@ -47,3 +86,20 @@ Draft MRs use the supported `Draft:` title prefix. Revision-bound inline discuss
|
|
|
47
86
|
## Explicit smoke verification
|
|
48
87
|
|
|
49
88
|
Real-provider smoke tests are opt-in manual runs: configure a disposable repository/issue, authenticated agent, hosting token, Git push access and validation; run one project; inspect the draft request, exact-head review and session records. This performs paid agent usage and real remote writes. The automated acceptance evidence is fixture-based, not a claim of live-provider compatibility or account access.
|
|
89
|
+
|
|
90
|
+
## Structured output and evidence access
|
|
91
|
+
|
|
92
|
+
Codex receives the application output schema through `runStreamed` options.
|
|
93
|
+
Copilot receives generated JSON instructions; common strict validation gates both
|
|
94
|
+
providers. Stage task text cannot remove those checks. Both retain their existing
|
|
95
|
+
inspection permissions: Codex's read-only sandbox and Copilot's read-only
|
|
96
|
+
permission handler (`approve-once` for reads, `reject` for non-read requests).
|
|
97
|
+
Managed human-approval requirements remain denied. No shell permission is added
|
|
98
|
+
for Copilot.
|
|
99
|
+
|
|
100
|
+
Evidence indexes use absolute paths outside the checkout. Controlled tests check
|
|
101
|
+
schema mapping, outside-directory reads and denied write/shell requests. The
|
|
102
|
+
optional `AGENT_WORKFLOWS_LIVE_AGENTS=codex,copilot` test checks actual runtime
|
|
103
|
+
file-reader access using the authenticated local providers; it is separate from
|
|
104
|
+
local fixture acceptance. Missing runtime authentication is a live-test failure,
|
|
105
|
+
not evidence of successful provider access.
|
package/docs/releases.md
CHANGED
|
@@ -2,88 +2,43 @@
|
|
|
2
2
|
|
|
3
3
|
One public npm package, `@mingchuno/agent-workflows`, contains the SDK and
|
|
4
4
|
`agent-workflows` CLI/TUI. Release Please opens a version/changelog PR from
|
|
5
|
-
Conventional Commits on `main`.
|
|
6
|
-
|
|
7
|
-
bump
|
|
8
|
-
|
|
9
|
-
##
|
|
10
|
-
|
|
11
|
-
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
The maintainer must control the `@mingchuno` npm scope and have account 2FA.
|
|
27
|
-
The package must exist before configuring its trusted publisher.
|
|
28
|
-
|
|
29
|
-
1. Merge the implementation, let Release Please open its first release PR, then
|
|
30
|
-
review and merge the proposed `0.1.0` release. Keep automated publishing disabled.
|
|
31
|
-
2. In a clean checkout of tag `v0.1.0`, install the pinned tools and dependencies,
|
|
32
|
-
then verify and test the package:
|
|
33
|
-
|
|
34
|
-
```sh
|
|
35
|
-
mise trust
|
|
36
|
-
mise install
|
|
37
|
-
mise exec -- pnpm install --frozen-lockfile
|
|
38
|
-
mise exec -- pnpm verify
|
|
39
|
-
mise exec -- pnpm pack:smoke
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
The smoke test leaves `.artifacts/mingchuno-agent-workflows-0.1.0.tgz`.
|
|
43
|
-
Authenticate interactively and publish that tested tarball:
|
|
44
|
-
|
|
45
|
-
```sh
|
|
46
|
-
mise exec -- pnpm exec npm login --registry=https://registry.npmjs.org/
|
|
47
|
-
mise exec -- pnpm exec npm publish .artifacts/mingchuno-agent-workflows-0.1.0.tgz --access public --ignore-scripts --registry=https://registry.npmjs.org/
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
3. In the npm package settings, add a GitHub Actions trusted publisher:
|
|
51
|
-
|
|
52
|
-
| Field | Value |
|
|
53
|
-
| --- | --- |
|
|
54
|
-
| Owner | `mingchuno` |
|
|
55
|
-
| Repository | `agent-workflows` |
|
|
56
|
-
| Workflow filename | `release.yml` |
|
|
57
|
-
| Environment | `npm` |
|
|
58
|
-
| Publication permission | Allow direct `npm publish` |
|
|
59
|
-
|
|
60
|
-
4. Set GitHub repository variable `NPM_PUBLISH_ENABLED=true`. The next releasable
|
|
61
|
-
change exercises OIDC; the manual first publication does not verify it.
|
|
62
|
-
|
|
63
|
-
The GitHub App manages releases; npm OIDC authenticates publication independently.
|
|
64
|
-
No `NPM_TOKEN` is required. The publishing job uses a GitHub-hosted runner,
|
|
65
|
-
`id-token: write`, and pinned npm 12. Public repository/package visibility enables
|
|
66
|
-
automatic provenance. See [npm trusted publishing](https://docs.npmjs.com/trusted-publishers/).
|
|
5
|
+
Conventional Commits on `main`. Merging that PR creates a GitHub release and,
|
|
6
|
+
when `NPM_PUBLISH_ENABLED=true`, publishes to npm. Fixes bump patch, features
|
|
7
|
+
bump minor, and breaking changes bump minor before 1.0.
|
|
8
|
+
|
|
9
|
+
## Configuration
|
|
10
|
+
|
|
11
|
+
- The release GitHub App needs Contents, Pull requests and Issues read/write.
|
|
12
|
+
Actions secrets `RELEASE_APP_ID` and `RELEASE_APP_PRIVATE_KEY` provide its
|
|
13
|
+
credentials. App-created release PRs trigger CI.
|
|
14
|
+
- Squash commits use the PR title and description. Protect `main` with `check`
|
|
15
|
+
and `commitlint`; preserve `!` or `BREAKING CHANGE:` for breaking changes.
|
|
16
|
+
- The `npm` environment restricts deployment to `main`. Environment reviewers
|
|
17
|
+
are optional; merging the release PR is the normal release decision.
|
|
18
|
+
- npm trusted publishing uses GitHub Actions owner `mingchuno`, repository
|
|
19
|
+
`agent-workflows`, workflow `release.yml`, environment `npm`, and permission
|
|
20
|
+
to publish directly. It authenticates independently of the GitHub App via
|
|
21
|
+
OIDC; no `NPM_TOKEN` is required. See [npm trusted publishing](https://docs.npmjs.com/trusted-publishers/).
|
|
22
|
+
- The repository variable `NPM_PUBLISH_ENABLED=true` enables publication.
|
|
23
|
+
Unset it or set it to `false` to pause future publishing. Inspect active runs
|
|
24
|
+
separately: they may already have evaluated the switch.
|
|
67
25
|
|
|
68
26
|
## Verification and recovery
|
|
69
27
|
|
|
70
|
-
`pnpm verify`
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
be able to create test databases. Neither invokes paid agents or real hosting writes.
|
|
28
|
+
The publishing job runs `pnpm verify` and `pnpm pack:smoke` at the release commit.
|
|
29
|
+
The smoke test installs the tarball in a temporary consumer, checks SDK imports
|
|
30
|
+
and TypeScript resolution, runs the CLI, and applies migrations to an isolated
|
|
31
|
+
database. It needs registry access and the [development test prerequisites](../README.md#development-and-review).
|
|
32
|
+
Neither command invokes paid agents or writes to real hosting providers.
|
|
76
33
|
|
|
77
|
-
Publishing checks the tag, release SHA, package version and tested tarball
|
|
78
|
-
|
|
79
|
-
|
|
34
|
+
Publishing checks the tag, release SHA, package version and tested tarball
|
|
35
|
+
integrity, then publishes that same tarball. Release runs are serialized and
|
|
36
|
+
never cancelled by newer pushes.
|
|
80
37
|
|
|
81
38
|
After a publishing failure, choose **Re-run failed jobs** on that Actions run to
|
|
82
|
-
retain the release outputs and commit. An existing npm version is skipped only
|
|
83
|
-
its integrity matches; differing contents require a new version. Re-running
|
|
84
|
-
whole workflow or dispatching a new run may find no new release and skip
|
|
85
|
-
If Release Please failed after creating a tag, inspect the existing
|
|
86
|
-
recovering; never overwrite a published version or delete a
|
|
87
|
-
|
|
88
|
-
To pause future publishing, unset `NPM_PUBLISH_ENABLED` or set it to `false`.
|
|
89
|
-
Inspect active runs separately: they may already have evaluated the switch.
|
|
39
|
+
retain the release outputs and commit. An existing npm version is skipped only
|
|
40
|
+
when its integrity matches; differing contents require a new version. Re-running
|
|
41
|
+
the whole workflow or dispatching a new run may find no new release and skip
|
|
42
|
+
publishing. If Release Please failed after creating a tag, inspect the existing
|
|
43
|
+
release before recovering; never overwrite a published version or delete a
|
|
44
|
+
release tag to retry.
|
package/examples/config.ts
CHANGED
|
@@ -23,7 +23,7 @@ export const configuration = configSchema.parse({
|
|
|
23
23
|
implementation: {
|
|
24
24
|
prompt: "Implement the issue and follow repository guidance.",
|
|
25
25
|
},
|
|
26
|
-
|
|
26
|
+
publication: {
|
|
27
27
|
profile: { provider: "copilot" },
|
|
28
28
|
prompt:
|
|
29
29
|
"Write concise publication text from the diff and validation evidence.",
|
|
@@ -45,7 +45,7 @@ export const modelOverrides = {
|
|
|
45
45
|
model: "YOUR_CODEX_MODEL",
|
|
46
46
|
reasoningEffort: "high",
|
|
47
47
|
},
|
|
48
|
-
|
|
48
|
+
publication: {
|
|
49
49
|
provider: "copilot" as const,
|
|
50
50
|
model: "YOUR_COPILOT_MODEL",
|
|
51
51
|
reasoningEffort: "low",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mingchuno/agent-workflows",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Local durable coding workflows on DBOS",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"pack:smoke": "pnpm build && node scripts/test.mjs --pack-smoke",
|
|
41
41
|
"release:publish": "node scripts/publish.mjs",
|
|
42
42
|
"lint:pr": "node scripts/lint-pr-title.mjs",
|
|
43
|
-
"start": "tsx src/cli.ts",
|
|
43
|
+
"start": "node --import tsx -- src/cli.ts",
|
|
44
44
|
"format": "biome format --write .",
|
|
45
45
|
"format:check": "biome format .",
|
|
46
46
|
"lint": "biome check .",
|
|
@@ -60,6 +60,8 @@
|
|
|
60
60
|
"pg": "^8.23.0",
|
|
61
61
|
"pino": "^10.3.1",
|
|
62
62
|
"react": "^19.3.0",
|
|
63
|
+
"string-width": "^8.2.2",
|
|
64
|
+
"wrap-ansi": "^9.0.2",
|
|
63
65
|
"zod": "^4.6.5"
|
|
64
66
|
},
|
|
65
67
|
"devDependencies": {
|
package/dist/src/tui-data.js
DELETED
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import { useEffect, useState } from "react";
|
|
2
|
-
export function useMonitorData(source, selection) {
|
|
3
|
-
const { projectIndex, runIndex } = selection;
|
|
4
|
-
const [projects, setProjects] = useState([]);
|
|
5
|
-
const [runs, setRuns] = useState([]);
|
|
6
|
-
const [sessions, setSessions] = useState([]), [events, setEvents] = useState([]);
|
|
7
|
-
const [message, setMessage] = useState("Connecting…"), [pending, setPending] = useState();
|
|
8
|
-
const project = projects[projectIndex];
|
|
9
|
-
const projectRuns = runs.filter((run) => run.projectId === project?.id);
|
|
10
|
-
const run = projectRuns[runIndex];
|
|
11
|
-
const selectedRunId = run?.id;
|
|
12
|
-
useEffect(() => {
|
|
13
|
-
let closed = false, busy = false;
|
|
14
|
-
const update = async () => {
|
|
15
|
-
if (busy)
|
|
16
|
-
return;
|
|
17
|
-
busy = true;
|
|
18
|
-
try {
|
|
19
|
-
const [nextProjects, nextRuns] = await Promise.all([
|
|
20
|
-
source.projects(),
|
|
21
|
-
source.runs(),
|
|
22
|
-
]);
|
|
23
|
-
if (closed)
|
|
24
|
-
return;
|
|
25
|
-
setProjects(nextProjects);
|
|
26
|
-
setRuns(nextRuns);
|
|
27
|
-
if (selectedRunId) {
|
|
28
|
-
const [nextSessions, nextEvents] = await Promise.all([
|
|
29
|
-
source.invocations(selectedRunId),
|
|
30
|
-
source.events(0, selectedRunId),
|
|
31
|
-
]);
|
|
32
|
-
if (closed)
|
|
33
|
-
return;
|
|
34
|
-
setSessions(nextSessions);
|
|
35
|
-
setEvents(nextEvents.filter((event) => event.runId === selectedRunId));
|
|
36
|
-
}
|
|
37
|
-
else {
|
|
38
|
-
setSessions([]);
|
|
39
|
-
setEvents([]);
|
|
40
|
-
}
|
|
41
|
-
if (pending) {
|
|
42
|
-
const command = (await source.commands()).find((command) => command.id === pending);
|
|
43
|
-
if (command && command.status !== "pending") {
|
|
44
|
-
setMessage(`${command.kind}: ${command.status}${command.error ? ` — ${command.error}` : ""}`);
|
|
45
|
-
setPending(undefined);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
else
|
|
49
|
-
setMessage((current) => current === "Connecting…" ? "Connected" : current);
|
|
50
|
-
}
|
|
51
|
-
catch (error) {
|
|
52
|
-
if (!closed)
|
|
53
|
-
setMessage(`Connection error: ${String(error)}`);
|
|
54
|
-
}
|
|
55
|
-
finally {
|
|
56
|
-
busy = false;
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
|
-
void update();
|
|
60
|
-
const timer = setInterval(() => void update(), 400);
|
|
61
|
-
return () => {
|
|
62
|
-
closed = true;
|
|
63
|
-
clearInterval(timer);
|
|
64
|
-
};
|
|
65
|
-
}, [source, selectedRunId, pending]);
|
|
66
|
-
const action = async (kind, target) => {
|
|
67
|
-
setMessage(`${kind}: pending`);
|
|
68
|
-
setPending("submitting");
|
|
69
|
-
try {
|
|
70
|
-
setPending(await source.request(kind, target));
|
|
71
|
-
}
|
|
72
|
-
catch (error) {
|
|
73
|
-
setPending(undefined);
|
|
74
|
-
setMessage(`${kind}: failed — ${String(error)}`);
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
return {
|
|
78
|
-
projects,
|
|
79
|
-
project,
|
|
80
|
-
projectRuns,
|
|
81
|
-
run,
|
|
82
|
-
sessions,
|
|
83
|
-
events,
|
|
84
|
-
message,
|
|
85
|
-
setMessage,
|
|
86
|
-
pending,
|
|
87
|
-
action,
|
|
88
|
-
};
|
|
89
|
-
}
|
package/dist/src/tui.d.ts
DELETED
package/dist/src/tui.js
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { readFile } from "node:fs/promises";
|
|
3
|
-
import { Box, Text, useApp, useInput } from "ink";
|
|
4
|
-
import { useState } from "react";
|
|
5
|
-
import { useMonitorData } from "./tui-data.js";
|
|
6
|
-
export function Monitor({ source }) {
|
|
7
|
-
const { exit } = useApp();
|
|
8
|
-
const [projectIndex, setProjectIndex] = useState(0), [runIndex, setRunIndex] = useState(0), [sessionIndex, setSessionIndex] = useState(0), [stepIndex, setStepIndex] = useState(0), [validationIndex, setValidationIndex] = useState(0);
|
|
9
|
-
const { projects, project, projectRuns, run, sessions, events, message, setMessage, pending, action, } = useMonitorData(source, { projectIndex, runIndex });
|
|
10
|
-
const [log, setLog] = useState("");
|
|
11
|
-
const session = sessions[sessionIndex];
|
|
12
|
-
const steps = events.filter((event) => event.kind === "step");
|
|
13
|
-
const selectedStep = steps[stepIndex];
|
|
14
|
-
const showLog = (path) => {
|
|
15
|
-
void readFile(path, "utf8").then((text) => setLog(text.split("\n").slice(-8).join("\n")), (error) => setMessage(`Log unavailable: ${String(error)}`));
|
|
16
|
-
};
|
|
17
|
-
useInput((input, key) => {
|
|
18
|
-
if (input === "q") {
|
|
19
|
-
exit();
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
if (key.leftArrow || key.rightArrow) {
|
|
23
|
-
setProjectIndex((index) => Math.max(0, Math.min(projects.length - 1, index + (key.rightArrow ? 1 : -1))));
|
|
24
|
-
setRunIndex(0);
|
|
25
|
-
setSessionIndex(0);
|
|
26
|
-
setStepIndex(0);
|
|
27
|
-
setValidationIndex(0);
|
|
28
|
-
setLog("");
|
|
29
|
-
}
|
|
30
|
-
if (key.upArrow || key.downArrow) {
|
|
31
|
-
setRunIndex((index) => Math.max(0, Math.min(projectRuns.length - 1, index + (key.downArrow ? 1 : -1))));
|
|
32
|
-
setSessionIndex(0);
|
|
33
|
-
setStepIndex(0);
|
|
34
|
-
setValidationIndex(0);
|
|
35
|
-
setLog("");
|
|
36
|
-
}
|
|
37
|
-
if (key.tab) {
|
|
38
|
-
setSessionIndex((index) => (index + 1) % Math.max(sessions.length, 1));
|
|
39
|
-
setLog("");
|
|
40
|
-
}
|
|
41
|
-
if (input === "l" && session)
|
|
42
|
-
showLog(session.log);
|
|
43
|
-
if (input === "[" || input === "]")
|
|
44
|
-
setStepIndex((index) => Math.max(0, Math.min(steps.length - 1, index + (input === "]" ? 1 : -1))));
|
|
45
|
-
if (input === "v" && run?.validation?.length) {
|
|
46
|
-
const check = run.validation[validationIndex % run.validation.length];
|
|
47
|
-
setMessage(`Validation: ${check.command} · exit ${check.exitCode}`);
|
|
48
|
-
showLog(check.log);
|
|
49
|
-
setValidationIndex((index) => index + 1);
|
|
50
|
-
}
|
|
51
|
-
if (pending)
|
|
52
|
-
return;
|
|
53
|
-
if (input === "p" && project)
|
|
54
|
-
void action(project.paused ? "resume" : "pause", project.id);
|
|
55
|
-
if (input === "s" && run)
|
|
56
|
-
void action("stop", run.id);
|
|
57
|
-
if (input === "r" && run)
|
|
58
|
-
void action("retry", run.id);
|
|
59
|
-
});
|
|
60
|
-
return (_jsxs(Box, { flexDirection: "column", paddingX: 1, children: [_jsx(Text, { bold: true, children: "Agent Workflows \u00B7 Monitor" }), _jsx(Text, { children: "\u2190 \u2192 project \u00B7 \u2191 \u2193 run \u00B7 [ ] step/attempt \u00B7 Tab session \u00B7 l agent log \u00B7 v validation log \u00B7 p pause/resume \u00B7 s stop \u00B7 r retry \u00B7 q close" }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { bold: true, children: project
|
|
61
|
-
? `${project.id} · ${project.paused ? "intake paused" : "intake enabled"} · ${projectRuns.filter((run) => run.outcome === "queued").length} queued`
|
|
62
|
-
: "No projects registered. Start the runner to populate this view." }), project?.blocked && (_jsxs(Text, { color: "yellow", children: ["Blocked: ", project.blocked] })), projectRuns
|
|
63
|
-
.slice(Math.max(0, runIndex - 1), runIndex + 2)
|
|
64
|
-
.map((item) => (_jsxs(Text, { inverse: item.id === run?.id, children: [item.id === run?.id ? ">" : " ", " #", item.issue.number, " \u00B7 attempt", " ", item.attempt, " \u00B7 ", item.outcome, " \u00B7 ", item.phase] }, item.id))), project && projectRuns.length === 0 && (_jsx(Text, { children: "No runs yet. Eligible issues appear after polling." }))] }), run && (_jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsxs(Text, { bold: true, children: ["Run ", run.id] }), _jsx(Text, { children: run.issue.title }), run.error && _jsx(Text, { color: "red", children: run.error }), _jsxs(Text, { children: ["Validation:", " ", run.validation
|
|
65
|
-
?.map((check) => `${check.command}: exit ${check.exitCode}`)
|
|
66
|
-
.join(" · ") || "No checks recorded"] }), _jsxs(Text, { children: ["Step/attempt event ", steps.length ? stepIndex + 1 : 0, "/", steps.length, ":", " ", selectedStep
|
|
67
|
-
? JSON.stringify(selectedStep.payload)
|
|
68
|
-
: "No steps recorded"] }), _jsxs(Text, { bold: true, children: ["Agent sessions \u00B7 ", sessions.length] }), session ? (_jsxs(_Fragment, { children: [_jsxs(Text, { children: [session.step, " \u00B7 invocation ", session.attempt, " \u00B7", " ", session.outcome] }), _jsxs(Text, { children: ["Session: ", session.sessionId ?? session.sessionState] }), _jsxs(Text, { children: ["Requested: ", JSON.stringify(session.requested)] }), _jsxs(Text, { children: ["Effective: ", JSON.stringify(session.effective)] }), _jsxs(Text, { children: ["Log: ", session.log] })] })) : (_jsx(Text, { children: "No agent sessions recorded" })), log && _jsx(Text, { children: log })] })), _jsx(Box, { marginTop: 1, children: _jsx(Text, { children: message }) }), _jsx(Text, { dimColor: true, children: "Closing this monitor leaves the runner and its tasks running." })] }));
|
|
69
|
-
}
|
package/docs/acceptance.md
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
# Phase 1 review guide
|
|
2
|
-
|
|
3
|
-
Implementation scope is the unchanged [specification in issue #1](https://github.com/mingchuno/agent-workflows/issues/1). Review the public contracts first, then the workspace/recovery boundaries. No task-specific worktrees, clones, merges or automatic review/fix loops are implemented.
|
|
4
|
-
|
|
5
|
-
| Acceptance area | Implementation / behavioral evidence |
|
|
6
|
-
| ------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
7
|
-
| Existing checkout, clean startup, branch policy and base transition | `ExistingCheckout`; real Git tests cover dirty files, collisions, unresolved Git operations, mutation detection and next-task base |
|
|
8
|
-
| Durable default workflow and extension | `Operations`, `defaultWorkflow`; PostgreSQL runner tests and the executable reporting-workflow example |
|
|
9
|
-
| Deduplication, one task/project, independent progress | Instance-qualified task keys, DBOS concurrency-one queues; all four agent/host combinations and multi-project tests |
|
|
10
|
-
| GitHub/GitLab intake and publication | Octokit/Gitbeaker contracts; pagination, PR exclusion, label queries, custom GitLab root/credentials, draft MR and inline review fixtures |
|
|
11
|
-
| Agent profiles, SDKs, prompts and sessions | Isolated SDK workers; profile/default isolation, supported-setting rejection, SDK argument/event contracts and invocation records |
|
|
12
|
-
| Validation and generated publication | Actual Git diff/fingerprints, schema-checked text; failed validation, malformed text, no-change and timeout tests |
|
|
13
|
-
| Recovery and external effects | Process-level interruptions after edits, commit, push, request creation and review publication; blocked ambiguous agent recovery and no duplicate publication effects |
|
|
14
|
-
| Cancellation and ownership | Real stubborn child process, journals, local leases, advisory locks; cancellation/reuse and duplicate-owner tests |
|
|
15
|
-
| Independent exact-revision review | Fresh sessions, published diff/head context, added-line mapping and stale-head rejection |
|
|
16
|
-
| Public observability and controls | Store query/subscription, retained sessions, timestamps, artifacts, credential redaction, CLI JSON and explicit retries |
|
|
17
|
-
| CLI/TUI | Init/error/help tests; keyboard step/session navigation, live state and action feedback; controls share application commands |
|
|
18
|
-
| SDK documentation | Quickstart, configuration, API, providers, operations/recovery and type-checked examples; reporting example runs with controlled adapters |
|
|
19
|
-
|
|
20
|
-
## Local verification
|
|
21
|
-
|
|
22
|
-
Run `pnpm check`, `pnpm test`, `pnpm build`, and `pnpm lint`. Tests create a disposable PostgreSQL database unless `TEST_DATABASE_URL` is set, use real temporary Git repositories, and use controlled agents/hosting endpoints. `pnpm audit --prod` checks runtime dependency advisories. The GitHub Actions job supplies the same fixture boundary on Linux.
|
|
23
|
-
|
|
24
|
-
The implementation was verified locally on macOS with Node 24 and PostgreSQL 17. Remote CI has not run for this uncommitted working tree. No authenticated live Codex/Copilot model invocation, real GitHub publication or real GitLab instance smoke test was performed. Those require a deliberately chosen test repository and provider access and are separate from deterministic acceptance.
|
|
25
|
-
|
|
26
|
-
## Deliberate operational boundaries
|
|
27
|
-
|
|
28
|
-
- Interrupted agent work blocks if ownership/state is ambiguous; it never starts another writer merely because DBOS recovered.
|
|
29
|
-
- Explicit retry creates a new attempt from the base after the developer restores a clean checkout. It preserves the previous run and branch and does not silently amend an existing PR/MR.
|
|
30
|
-
- Runtime context controls are supported only where exposed by the provider; unknown defaults remain unknown. Codex explicit-model validation depends on its local model catalog or an injected catalog.
|
|
31
|
-
- Git hooks are disabled for the application-authored task commit; configure required checks as validation commands. Changed symlinks and submodules require manual handling.
|
|
32
|
-
- The runner assumes exclusive checkout use. It detects boundary changes but does not sandbox arbitrary custom adapters or prevent every unrelated local tool write.
|
|
33
|
-
- macOS/Linux process groups are required. Windows startup fails explicitly.
|
|
34
|
-
|
|
35
|
-
Human review should concentrate on cancellation/ownership, recovery reconciliation and adapter permissions before enabling unattended work on a real repository. Completion means the automation has published its draft and review, not that the code is approved.
|