@cluesmith/codev 3.3.4 → 3.3.6
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/dashboard-dist/assets/index-BjcqV9Vv.css +32 -0
- package/dashboard-dist/assets/index-b7GnZV2i.js +220 -0
- package/dashboard-dist/assets/index-b7GnZV2i.js.map +1 -0
- package/dashboard-dist/index.html +2 -2
- package/dist/agent-farm/cli.d.ts.map +1 -1
- package/dist/agent-farm/cli.js +50 -17
- package/dist/agent-farm/cli.js.map +1 -1
- package/dist/agent-farm/commands/architect.d.ts.map +1 -1
- package/dist/agent-farm/commands/architect.js +5 -1
- package/dist/agent-farm/commands/architect.js.map +1 -1
- package/dist/agent-farm/commands/attach.d.ts +1 -1
- package/dist/agent-farm/commands/attach.d.ts.map +1 -1
- package/dist/agent-farm/commands/cleanup.d.ts +1 -1
- package/dist/agent-farm/commands/cleanup.d.ts.map +1 -1
- package/dist/agent-farm/commands/cleanup.js +2 -1
- package/dist/agent-farm/commands/cleanup.js.map +1 -1
- package/dist/agent-farm/commands/decisions.d.ts +25 -0
- package/dist/agent-farm/commands/decisions.d.ts.map +1 -0
- package/dist/agent-farm/commands/decisions.js +54 -0
- package/dist/agent-farm/commands/decisions.js.map +1 -0
- package/dist/agent-farm/commands/ide.d.ts +32 -3
- package/dist/agent-farm/commands/ide.d.ts.map +1 -1
- package/dist/agent-farm/commands/ide.js +180 -19
- package/dist/agent-farm/commands/ide.js.map +1 -1
- package/dist/agent-farm/commands/reset/context.d.ts +4 -2
- package/dist/agent-farm/commands/reset/context.d.ts.map +1 -1
- package/dist/agent-farm/commands/reset/context.js +12 -4
- package/dist/agent-farm/commands/reset/context.js.map +1 -1
- package/dist/agent-farm/commands/send.d.ts +3 -2
- package/dist/agent-farm/commands/send.d.ts.map +1 -1
- package/dist/agent-farm/commands/send.js +35 -21
- package/dist/agent-farm/commands/send.js.map +1 -1
- package/dist/agent-farm/commands/spawn-worktree.d.ts +7 -0
- package/dist/agent-farm/commands/spawn-worktree.d.ts.map +1 -1
- package/dist/agent-farm/commands/spawn-worktree.js +63 -20
- package/dist/agent-farm/commands/spawn-worktree.js.map +1 -1
- package/dist/agent-farm/commands/spawn.d.ts +17 -0
- package/dist/agent-farm/commands/spawn.d.ts.map +1 -1
- package/dist/agent-farm/commands/spawn.js +41 -19
- package/dist/agent-farm/commands/spawn.js.map +1 -1
- package/dist/agent-farm/lib/builder-lookup.d.ts +3 -2
- package/dist/agent-farm/lib/builder-lookup.d.ts.map +1 -1
- package/dist/agent-farm/lib/builder-lookup.js +24 -9
- package/dist/agent-farm/lib/builder-lookup.js.map +1 -1
- package/dist/agent-farm/lib/ide-extensions.d.ts +82 -0
- package/dist/agent-farm/lib/ide-extensions.d.ts.map +1 -0
- package/dist/agent-farm/lib/ide-extensions.js +179 -0
- package/dist/agent-farm/lib/ide-extensions.js.map +1 -0
- package/dist/agent-farm/lib/ide-record.d.ts +6 -1
- package/dist/agent-farm/lib/ide-record.d.ts.map +1 -1
- package/dist/agent-farm/lib/ide-record.js +8 -1
- package/dist/agent-farm/lib/ide-record.js.map +1 -1
- package/dist/agent-farm/lib/ide-version.d.ts +97 -0
- package/dist/agent-farm/lib/ide-version.d.ts.map +1 -0
- package/dist/agent-farm/lib/ide-version.js +224 -0
- package/dist/agent-farm/lib/ide-version.js.map +1 -0
- package/dist/agent-farm/lib/tunnel-client.d.ts.map +1 -1
- package/dist/agent-farm/lib/tunnel-client.js +7 -3
- package/dist/agent-farm/lib/tunnel-client.js.map +1 -1
- package/dist/agent-farm/servers/agent-state/broadcast.d.ts +19 -0
- package/dist/agent-farm/servers/agent-state/broadcast.d.ts.map +1 -0
- package/dist/agent-farm/servers/agent-state/broadcast.js +30 -0
- package/dist/agent-farm/servers/agent-state/broadcast.js.map +1 -0
- package/dist/agent-farm/servers/agent-state/identity.d.ts +50 -0
- package/dist/agent-farm/servers/agent-state/identity.d.ts.map +1 -0
- package/dist/agent-farm/servers/agent-state/identity.js +120 -0
- package/dist/agent-farm/servers/agent-state/identity.js.map +1 -0
- package/dist/agent-farm/servers/agent-state/liveness.d.ts +107 -0
- package/dist/agent-farm/servers/agent-state/liveness.d.ts.map +1 -0
- package/dist/agent-farm/servers/agent-state/liveness.js +224 -0
- package/dist/agent-farm/servers/agent-state/liveness.js.map +1 -0
- package/dist/agent-farm/servers/agent-state/route.d.ts +38 -0
- package/dist/agent-farm/servers/agent-state/route.d.ts.map +1 -0
- package/dist/agent-farm/servers/agent-state/route.js +170 -0
- package/dist/agent-farm/servers/agent-state/route.js.map +1 -0
- package/dist/agent-farm/servers/agent-state/serve.d.ts +31 -0
- package/dist/agent-farm/servers/agent-state/serve.d.ts.map +1 -0
- package/dist/agent-farm/servers/agent-state/serve.js +49 -0
- package/dist/agent-farm/servers/agent-state/serve.js.map +1 -0
- package/dist/agent-farm/servers/agent-state/store.d.ts +76 -0
- package/dist/agent-farm/servers/agent-state/store.d.ts.map +1 -0
- package/dist/agent-farm/servers/agent-state/store.js +157 -0
- package/dist/agent-farm/servers/agent-state/store.js.map +1 -0
- package/dist/agent-farm/servers/decisions/file.d.ts +50 -0
- package/dist/agent-farm/servers/decisions/file.d.ts.map +1 -0
- package/dist/agent-farm/servers/decisions/file.js +146 -0
- package/dist/agent-farm/servers/decisions/file.js.map +1 -0
- package/dist/agent-farm/servers/decisions/grammar.d.ts +36 -0
- package/dist/agent-farm/servers/decisions/grammar.d.ts.map +1 -0
- package/dist/agent-farm/servers/decisions/grammar.js +109 -0
- package/dist/agent-farm/servers/decisions/grammar.js.map +1 -0
- package/dist/agent-farm/servers/decisions/notice.d.ts +11 -0
- package/dist/agent-farm/servers/decisions/notice.d.ts.map +1 -0
- package/dist/agent-farm/servers/decisions/notice.js +18 -0
- package/dist/agent-farm/servers/decisions/notice.js.map +1 -0
- package/dist/agent-farm/servers/decisions/parse.d.ts +36 -0
- package/dist/agent-farm/servers/decisions/parse.d.ts.map +1 -0
- package/dist/agent-farm/servers/decisions/parse.js +338 -0
- package/dist/agent-farm/servers/decisions/parse.js.map +1 -0
- package/dist/agent-farm/servers/decisions/routes.d.ts +17 -0
- package/dist/agent-farm/servers/decisions/routes.d.ts.map +1 -0
- package/dist/agent-farm/servers/decisions/routes.js +160 -0
- package/dist/agent-farm/servers/decisions/routes.js.map +1 -0
- package/dist/agent-farm/servers/decisions/splice.d.ts +26 -0
- package/dist/agent-farm/servers/decisions/splice.d.ts.map +1 -0
- package/dist/agent-farm/servers/decisions/splice.js +120 -0
- package/dist/agent-farm/servers/decisions/splice.js.map +1 -0
- package/dist/agent-farm/servers/decisions/stamp.d.ts +8 -0
- package/dist/agent-farm/servers/decisions/stamp.d.ts.map +1 -0
- package/dist/agent-farm/servers/decisions/stamp.js +195 -0
- package/dist/agent-farm/servers/decisions/stamp.js.map +1 -0
- package/dist/agent-farm/servers/decisions/template.d.ts +2 -0
- package/dist/agent-farm/servers/decisions/template.d.ts.map +1 -0
- package/dist/agent-farm/servers/decisions/template.js +15 -0
- package/dist/agent-farm/servers/decisions/template.js.map +1 -0
- package/dist/agent-farm/servers/ide-server.d.ts +28 -8
- package/dist/agent-farm/servers/ide-server.d.ts.map +1 -1
- package/dist/agent-farm/servers/ide-server.js +147 -50
- package/dist/agent-farm/servers/ide-server.js.map +1 -1
- package/dist/agent-farm/servers/overview.d.ts +31 -4
- package/dist/agent-farm/servers/overview.d.ts.map +1 -1
- package/dist/agent-farm/servers/overview.js +235 -55
- package/dist/agent-farm/servers/overview.js.map +1 -1
- package/dist/agent-farm/servers/tower-instances.d.ts +14 -1
- package/dist/agent-farm/servers/tower-instances.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-instances.js +51 -9
- package/dist/agent-farm/servers/tower-instances.js.map +1 -1
- package/dist/agent-farm/servers/tower-routes.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-routes.js +113 -14
- package/dist/agent-farm/servers/tower-routes.js.map +1 -1
- package/dist/agent-farm/servers/tower-server.js +35 -1
- package/dist/agent-farm/servers/tower-server.js.map +1 -1
- package/dist/agent-farm/servers/tower-terminals.d.ts +25 -0
- package/dist/agent-farm/servers/tower-terminals.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-terminals.js +128 -4
- package/dist/agent-farm/servers/tower-terminals.js.map +1 -1
- package/dist/agent-farm/servers/tower-utils.d.ts.map +1 -1
- package/dist/agent-farm/servers/tower-utils.js +18 -5
- package/dist/agent-farm/servers/tower-utils.js.map +1 -1
- package/dist/agent-farm/utils/builder-worktree-identity.d.ts +39 -0
- package/dist/agent-farm/utils/builder-worktree-identity.d.ts.map +1 -0
- package/dist/agent-farm/utils/builder-worktree-identity.js +42 -0
- package/dist/agent-farm/utils/builder-worktree-identity.js.map +1 -0
- package/dist/agent-farm/utils/harness.d.ts +71 -0
- package/dist/agent-farm/utils/harness.d.ts.map +1 -1
- package/dist/agent-farm/utils/harness.js +153 -0
- package/dist/agent-farm/utils/harness.js.map +1 -1
- package/dist/agent-farm/utils/lifecycle-reporter.d.ts +79 -0
- package/dist/agent-farm/utils/lifecycle-reporter.d.ts.map +1 -0
- package/dist/agent-farm/utils/lifecycle-reporter.js +347 -0
- package/dist/agent-farm/utils/lifecycle-reporter.js.map +1 -0
- package/dist/agent-farm/utils/message-format.d.ts +8 -0
- package/dist/agent-farm/utils/message-format.d.ts.map +1 -1
- package/dist/agent-farm/utils/message-format.js +16 -0
- package/dist/agent-farm/utils/message-format.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +17 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/adopt.d.ts +16 -2
- package/dist/commands/adopt.d.ts.map +1 -1
- package/dist/commands/adopt.js +67 -23
- package/dist/commands/adopt.js.map +1 -1
- package/dist/commands/bootstrap-docs.d.ts +132 -0
- package/dist/commands/bootstrap-docs.d.ts.map +1 -0
- package/dist/commands/bootstrap-docs.js +725 -0
- package/dist/commands/bootstrap-docs.js.map +1 -0
- package/dist/commands/consult/index.d.ts +20 -1
- package/dist/commands/consult/index.d.ts.map +1 -1
- package/dist/commands/consult/index.js +70 -3
- package/dist/commands/consult/index.js.map +1 -1
- package/dist/commands/consult/tree-tripwire.d.ts +2 -75
- package/dist/commands/consult/tree-tripwire.d.ts.map +1 -1
- package/dist/commands/consult/tree-tripwire.js +7 -184
- package/dist/commands/consult/tree-tripwire.js.map +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +36 -4
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/porch/checks.d.ts +7 -1
- package/dist/commands/porch/checks.d.ts.map +1 -1
- package/dist/commands/porch/checks.js +77 -14
- package/dist/commands/porch/checks.js.map +1 -1
- package/dist/commands/porch/index.d.ts +38 -1
- package/dist/commands/porch/index.d.ts.map +1 -1
- package/dist/commands/porch/index.js +79 -43
- package/dist/commands/porch/index.js.map +1 -1
- package/dist/commands/porch/protocol.d.ts +4 -3
- package/dist/commands/porch/protocol.d.ts.map +1 -1
- package/dist/commands/porch/protocol.js +32 -5
- package/dist/commands/porch/protocol.js.map +1 -1
- package/dist/commands/porch/state.d.ts +0 -4
- package/dist/commands/porch/state.d.ts.map +1 -1
- package/dist/commands/porch/state.js +23 -10
- package/dist/commands/porch/state.js.map +1 -1
- package/dist/commands/porch/types.d.ts +2 -0
- package/dist/commands/porch/types.d.ts.map +1 -1
- package/dist/commands/update.d.ts +5 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +73 -18
- package/dist/commands/update.js.map +1 -1
- package/dist/lib/agent-env.d.ts +31 -1
- package/dist/lib/agent-env.d.ts.map +1 -1
- package/dist/lib/agent-env.js +38 -1
- package/dist/lib/agent-env.js.map +1 -1
- package/dist/lib/agent-process.d.ts +23 -0
- package/dist/lib/agent-process.d.ts.map +1 -0
- package/dist/lib/agent-process.js +24 -0
- package/dist/lib/agent-process.js.map +1 -0
- package/dist/lib/config.d.ts +8 -0
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/forge-contracts.d.ts +9 -3
- package/dist/lib/forge-contracts.d.ts.map +1 -1
- package/dist/lib/forge-contracts.js.map +1 -1
- package/dist/lib/forge.d.ts +8 -5
- package/dist/lib/forge.d.ts.map +1 -1
- package/dist/lib/forge.js +57 -1
- package/dist/lib/forge.js.map +1 -1
- package/dist/lib/github.d.ts.map +1 -1
- package/dist/lib/github.js +38 -0
- package/dist/lib/github.js.map +1 -1
- package/dist/lib/governance-bootstrap.d.ts +155 -0
- package/dist/lib/governance-bootstrap.d.ts.map +1 -0
- package/dist/lib/governance-bootstrap.js +469 -0
- package/dist/lib/governance-bootstrap.js.map +1 -0
- package/dist/lib/issue-id.d.ts +34 -0
- package/dist/lib/issue-id.d.ts.map +1 -0
- package/dist/lib/issue-id.js +61 -0
- package/dist/lib/issue-id.js.map +1 -0
- package/dist/lib/scaffold.d.ts +4 -0
- package/dist/lib/scaffold.d.ts.map +1 -1
- package/dist/lib/scaffold.js +29 -5
- package/dist/lib/scaffold.js.map +1 -1
- package/dist/lib/shipped-skill-hashes.d.ts +10 -0
- package/dist/lib/shipped-skill-hashes.d.ts.map +1 -0
- package/dist/lib/shipped-skill-hashes.js +197 -0
- package/dist/lib/shipped-skill-hashes.js.map +1 -0
- package/dist/lib/skill-refresh.d.ts +90 -0
- package/dist/lib/skill-refresh.d.ts.map +1 -0
- package/dist/lib/skill-refresh.js +267 -0
- package/dist/lib/skill-refresh.js.map +1 -0
- package/dist/lib/tree-snapshot.d.ts +172 -0
- package/dist/lib/tree-snapshot.d.ts.map +1 -0
- package/dist/lib/tree-snapshot.js +393 -0
- package/dist/lib/tree-snapshot.js.map +1 -0
- package/dist/terminal/pty-session.d.ts +5 -0
- package/dist/terminal/pty-session.d.ts.map +1 -1
- package/dist/terminal/pty-session.js +7 -0
- package/dist/terminal/pty-session.js.map +1 -1
- package/ide-extension/codev-vscode.vsix +0 -0
- package/ide-extension/manifest.json +7 -0
- package/package.json +8 -6
- package/scripts/forge/jira/_lib.sh +113 -0
- package/scripts/forge/jira/auth-status.sh +29 -0
- package/scripts/forge/jira/issue-comment.sh +23 -0
- package/scripts/forge/jira/issue-list.sh +32 -0
- package/scripts/forge/jira/issue-search.sh +40 -0
- package/scripts/forge/jira/issue-view.sh +41 -0
- package/scripts/forge/jira/recently-closed.sh +81 -0
- package/scripts/forge/jira/user-identity.sh +18 -0
- package/skeleton/.claude/skills/afx/SKILL.md +51 -0
- package/skeleton/.claude/skills/arch-init/SKILL.md +56 -9
- package/skeleton/.claude/skills/arch-save/SKILL.md +100 -9
- package/skeleton/.claude/skills/codev/SKILL.md +18 -2
- package/skeleton/.claude/skills/consult/SKILL.md +9 -0
- package/skeleton/.claude/skills/porch/SKILL.md +18 -0
- package/skeleton/.claude/skills/update-arch-docs/SKILL.md +28 -2
- package/skeleton/.codex/skills/afx/SKILL.md +51 -0
- package/skeleton/.codex/skills/arch-init/SKILL.md +56 -9
- package/skeleton/.codex/skills/arch-save/SKILL.md +100 -9
- package/skeleton/.codex/skills/codev/SKILL.md +18 -2
- package/skeleton/.codex/skills/consult/SKILL.md +9 -0
- package/skeleton/.codex/skills/porch/SKILL.md +18 -0
- package/skeleton/.codex/skills/update-arch-docs/SKILL.md +28 -2
- package/skeleton/protocol-schema.json +6 -0
- package/skeleton/protocols/maintain/protocol.md +5 -0
- package/skeleton/protocols/pir/prompts/review.md +0 -1
- package/skeleton/protocols/protocol-schema.json +6 -0
- package/skeleton/resources/commands/agent-farm.md +156 -0
- package/skeleton/resources/commands/codev.md +47 -0
- package/skeleton/resources/commands/consult.md +9 -2
- package/skeleton/resources/commands/overview.md +1 -0
- package/skeleton/resources/decision-protocol.md +215 -0
- package/skeleton/resources/workflow-reference.md +12 -0
- package/skeleton/roles/architect.md +6 -0
- package/skeleton/templates/bootstrap-docs-prompt.md +16 -0
- package/skeleton/templates/bootstrap-docs-review-prompt.md +19 -0
- package/skeleton/templates/cheatsheet.md +2 -1
- package/dashboard-dist/assets/index-DZf6pNPE.js +0 -199
- package/dashboard-dist/assets/index-DZf6pNPE.js.map +0 -1
- package/dashboard-dist/assets/index-DnYLy5C_.css +0 -32
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# Shared helpers for the Jira forge preset scripts (Jira Cloud via Atlassian's `acli`).
|
|
2
|
+
#
|
|
3
|
+
# This file is SOURCED, not executed (`. "$(dirname "$0")/_lib.sh"`), so it has
|
|
4
|
+
# no shebang and defines only functions/vars. POSIX sh only — no bashisms — the
|
|
5
|
+
# scripts are #!/bin/sh and forge runs them via `sh -c`. It is not a forge
|
|
6
|
+
# concept: forge.ts builds presets from an explicit KNOWN_CONCEPTS allowlist, so
|
|
7
|
+
# a leading-underscore file in this directory is never registered as a concept.
|
|
8
|
+
#
|
|
9
|
+
# Sibling-file dependency: the concept scripts that source this file need it to
|
|
10
|
+
# sit next to them. A hand-copied override in `.codev/scripts/forge/jira/` must
|
|
11
|
+
# copy `_lib.sh` alongside the script, or the `.` line fails.
|
|
12
|
+
#
|
|
13
|
+
# acli facts these helpers encode (verified against acli 1.3.39-stable):
|
|
14
|
+
# - `acli jira auth status` round-trips to the site and prints text (no
|
|
15
|
+
# --json): `Site: <host>`, `Email: <addr>`, `Authentication Type: …`.
|
|
16
|
+
# - A work item's REST `self` link names an Atlassian infrastructure host, not
|
|
17
|
+
# the site, so browser URLs are built from the site, never from `self`.
|
|
18
|
+
# - Jira rejects unbounded JQL, so every query carries a status-category
|
|
19
|
+
# clause; project scoping is optional on top of it.
|
|
20
|
+
|
|
21
|
+
# Print the site's browser base URL (`https://<site>.atlassian.net`), no
|
|
22
|
+
# trailing slash. Honors CODEV_JIRA_SITE (`forge.jira-site`), with or without a
|
|
23
|
+
# scheme; otherwise asks acli which site it is logged into. Callers must use:
|
|
24
|
+
# SITE="$(jira_site)" || exit 1
|
|
25
|
+
jira_site() {
|
|
26
|
+
if [ -n "$CODEV_JIRA_SITE" ]; then
|
|
27
|
+
_site="$CODEV_JIRA_SITE"
|
|
28
|
+
else
|
|
29
|
+
_site="$(acli jira auth status 2>/dev/null | sed -n 's/^[[:space:]]*Site:[[:space:]]*//p' | head -n 1)"
|
|
30
|
+
fi
|
|
31
|
+
_site="$(printf '%s' "$_site" | sed -e 's#^[a-zA-Z]*://##' -e 's#/*$##')"
|
|
32
|
+
if [ -z "$_site" ]; then
|
|
33
|
+
echo "jira: cannot determine the Jira site; set forge.jira-site in .codev/config.json or run: acli jira auth login" >&2
|
|
34
|
+
return 1
|
|
35
|
+
fi
|
|
36
|
+
printf 'https://%s' "$_site"
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
# Print the JQL project-scope prefix (`project = "KEY" AND `), or nothing when
|
|
40
|
+
# CODEV_JIRA_PROJECT (`forge.jira-project`) is unset. The key is validated
|
|
41
|
+
# rather than escaped: Jira project keys are `[A-Z][A-Z0-9_]+`, and anything
|
|
42
|
+
# else is a misconfiguration that must not reach the query. Callers must use:
|
|
43
|
+
# SCOPE="$(jira_scope)" || exit 1
|
|
44
|
+
jira_scope() {
|
|
45
|
+
[ -z "$CODEV_JIRA_PROJECT" ] && return 0
|
|
46
|
+
_key="$(printf '%s' "$CODEV_JIRA_PROJECT" | tr '[:lower:]' '[:upper:]')"
|
|
47
|
+
case "$_key" in
|
|
48
|
+
[A-Z]*) ;;
|
|
49
|
+
*) _key="" ;;
|
|
50
|
+
esac
|
|
51
|
+
if [ -z "$_key" ] || printf '%s' "$_key" | grep -q '[^A-Z0-9_]'; then
|
|
52
|
+
echo "jira: invalid forge.jira-project '$CODEV_JIRA_PROJECT' (expected a project key like ENG)" >&2
|
|
53
|
+
return 1
|
|
54
|
+
fi
|
|
55
|
+
printf 'project = "%s" AND ' "$_key"
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
# Fail unless CODEV_ISSUE_ID is a work item key (`KEY-123`). It is passed to
|
|
59
|
+
# acli as an argument, so the check also keeps a leading `-` from being read as
|
|
60
|
+
# a flag. Callers must use: jira_require_issue_id || exit 1
|
|
61
|
+
jira_require_issue_id() {
|
|
62
|
+
if [ -z "$CODEV_ISSUE_ID" ]; then
|
|
63
|
+
echo "CODEV_ISSUE_ID is not set" >&2
|
|
64
|
+
return 1
|
|
65
|
+
fi
|
|
66
|
+
if ! printf '%s' "$CODEV_ISSUE_ID" | grep -Eq '^[A-Za-z][A-Za-z0-9_]*-[0-9]+$'; then
|
|
67
|
+
echo "jira: '$CODEV_ISSUE_ID' is not a Jira work item key (expected KEY-123)" >&2
|
|
68
|
+
return 1
|
|
69
|
+
fi
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
# jq definitions shared by the JSON-emitting scripts. Prepend to a filter:
|
|
73
|
+
# jq "$JIRA_JQ_DEFS"' …filter… '
|
|
74
|
+
#
|
|
75
|
+
# adf_text flattens Atlassian Document Format (descriptions and comment bodies)
|
|
76
|
+
# to plain text: inline text joined per block, blocks separated by blank lines,
|
|
77
|
+
# list items prefixed with "- " or "N. ". Media and unknown leaf nodes drop out.
|
|
78
|
+
# No markdown fidelity is attempted.
|
|
79
|
+
#
|
|
80
|
+
# person maps a Jira user to the contract's `{login}`. The email is preferred
|
|
81
|
+
# because `user-identity` can only report the current user's email (acli
|
|
82
|
+
# exposes nothing else), and the "assigned to me" filter compares the two.
|
|
83
|
+
# Users who hide their email degrade to their display name.
|
|
84
|
+
JIRA_JQ_DEFS='
|
|
85
|
+
def adf_inline:
|
|
86
|
+
if .type == "text" then (.text // "")
|
|
87
|
+
elif .type == "hardBreak" then "\n"
|
|
88
|
+
elif .type == "mention" then (.attrs.text // "")
|
|
89
|
+
elif .type == "emoji" then (.attrs.text // .attrs.shortName // "")
|
|
90
|
+
elif .type == "inlineCard" or .type == "blockCard" then (.attrs.url // "")
|
|
91
|
+
elif (.content | type) == "array" then ([.content[] | adf_inline] | join(""))
|
|
92
|
+
else "" end;
|
|
93
|
+
def adf_block:
|
|
94
|
+
if .type == "paragraph" or .type == "heading" or .type == "codeBlock" then
|
|
95
|
+
([(.content // [])[] | adf_inline] | join(""))
|
|
96
|
+
elif .type == "bulletList" then
|
|
97
|
+
([(.content // [])[] | "- " + ([(.content // [])[] | adf_block] | join("\n"))] | join("\n"))
|
|
98
|
+
elif .type == "orderedList" then
|
|
99
|
+
([(.content // []) | to_entries[] | "\(.key + 1). " + ([(.value.content // [])[] | adf_block] | join("\n"))] | join("\n"))
|
|
100
|
+
elif .type == "mediaSingle" or .type == "mediaGroup" or .type == "media" or .type == "rule" then ""
|
|
101
|
+
elif (.content | type) == "array" then
|
|
102
|
+
([.content[] | adf_block | select(. != "")] | join("\n\n"))
|
|
103
|
+
else adf_inline end;
|
|
104
|
+
def adf_text:
|
|
105
|
+
if . == null then ""
|
|
106
|
+
elif type == "string" then .
|
|
107
|
+
elif type == "object" then ([(.content // [])[] | adf_block | select(. != "")] | join("\n\n"))
|
|
108
|
+
else "" end;
|
|
109
|
+
def person:
|
|
110
|
+
if . == null then null else { login: (.emailAddress // .displayName // "") } end;
|
|
111
|
+
def labels_of: [(.fields.labels // [])[] | { name: . }];
|
|
112
|
+
def assignees_of: (if .fields.assignee then [.fields.assignee | person] else [] end);
|
|
113
|
+
'
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# Forge concept: auth-status (Jira Cloud via acli)
|
|
3
|
+
# forge-executable: acli
|
|
4
|
+
# Input (optional): CODEV_JIRA_SITE — the site this workspace expects
|
|
5
|
+
# Output: exit code (0 = authenticated); acli's status text on stdout
|
|
6
|
+
#
|
|
7
|
+
# `acli jira auth status` round-trips to the site (it fails when the site is
|
|
8
|
+
# unreachable), so it is an authenticated call, not a local config read. acli
|
|
9
|
+
# owns the credential (`acli jira auth login`, browser OAuth or API token);
|
|
10
|
+
# codev never reads or passes a Jira token. When CODEV_JIRA_SITE is set, a login
|
|
11
|
+
# to a different site is reported as unauthenticated, so `codev doctor` never
|
|
12
|
+
# reports success against the wrong site.
|
|
13
|
+
set -e
|
|
14
|
+
|
|
15
|
+
STATUS="$(acli jira auth status 2>&1)" || {
|
|
16
|
+
printf '%s\n' "$STATUS" >&2
|
|
17
|
+
exit 1
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if [ -n "$CODEV_JIRA_SITE" ]; then
|
|
21
|
+
WANT="$(printf '%s' "$CODEV_JIRA_SITE" | sed -e 's#^[a-zA-Z]*://##' -e 's#/*$##' | tr '[:upper:]' '[:lower:]')"
|
|
22
|
+
HAVE="$(printf '%s\n' "$STATUS" | sed -n 's/^[[:space:]]*Site:[[:space:]]*//p' | head -n 1 | tr '[:upper:]' '[:lower:]')"
|
|
23
|
+
if [ "$WANT" != "$HAVE" ]; then
|
|
24
|
+
echo "jira: acli is logged into '${HAVE:-no site}', but forge.jira-site is '$WANT'; run: acli jira auth switch" >&2
|
|
25
|
+
exit 1
|
|
26
|
+
fi
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
printf '%s\n' "$STATUS"
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# Forge concept: issue-comment (Jira Cloud via acli)
|
|
3
|
+
# forge-executable: acli
|
|
4
|
+
# Input: CODEV_ISSUE_ID, CODEV_COMMENT_BODY
|
|
5
|
+
# Output: exit code only
|
|
6
|
+
#
|
|
7
|
+
# The body goes to acli as plain text through a temp file (no quoting or argv
|
|
8
|
+
# length limits). acli accepts plain text or Atlassian Document Format there;
|
|
9
|
+
# codev's markdown is not converted, so it renders as plain text.
|
|
10
|
+
set -e
|
|
11
|
+
. "$(dirname "$0")/_lib.sh"
|
|
12
|
+
|
|
13
|
+
jira_require_issue_id || exit 1
|
|
14
|
+
if [ -z "${CODEV_COMMENT_BODY+set}" ]; then
|
|
15
|
+
echo "CODEV_COMMENT_BODY is not set" >&2
|
|
16
|
+
exit 1
|
|
17
|
+
fi
|
|
18
|
+
|
|
19
|
+
BODY_FILE="$(mktemp)"
|
|
20
|
+
trap 'rm -f "${BODY_FILE:?}"' EXIT
|
|
21
|
+
printf '%s\n' "$CODEV_COMMENT_BODY" > "$BODY_FILE"
|
|
22
|
+
|
|
23
|
+
acli jira workitem comment create --key "$CODEV_ISSUE_ID" --body-file "$BODY_FILE" >/dev/null
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# Forge concept: issue-list (Jira Cloud via acli)
|
|
3
|
+
# forge-executable: acli
|
|
4
|
+
# Input (optional): CODEV_JIRA_PROJECT (project key), CODEV_JIRA_SITE
|
|
5
|
+
# Output: JSON [{number, title, url, labels, author, assignees}]
|
|
6
|
+
#
|
|
7
|
+
# Open = status category not Done (never status names, which are per-site).
|
|
8
|
+
# `acli jira workitem search` only returns an allow-listed set of fields, none
|
|
9
|
+
# of them dates, so `createdAt` is omitted: consumers treat it as unknown, and
|
|
10
|
+
# the JQL orders items newest first. The limit stays at 100 because a search
|
|
11
|
+
# takes ~5s per 100 items and forge commands time out at 30s.
|
|
12
|
+
set -e
|
|
13
|
+
. "$(dirname "$0")/_lib.sh"
|
|
14
|
+
|
|
15
|
+
SCOPE="$(jira_scope)" || exit 1
|
|
16
|
+
SITE="$(jira_site)" || exit 1
|
|
17
|
+
|
|
18
|
+
RAW="$(acli jira workitem search \
|
|
19
|
+
--jql "${SCOPE}statusCategory != Done ORDER BY created DESC" \
|
|
20
|
+
--fields summary,status,labels,creator,assignee \
|
|
21
|
+
--limit 100 \
|
|
22
|
+
--json)"
|
|
23
|
+
|
|
24
|
+
printf '%s' "$RAW" | jq --arg site "$SITE" "$JIRA_JQ_DEFS"'
|
|
25
|
+
[.[] | select(. != null and (.key | type) == "string") | {
|
|
26
|
+
number: .key,
|
|
27
|
+
title: (.fields.summary // ""),
|
|
28
|
+
url: "\($site)/browse/\(.key)",
|
|
29
|
+
labels: labels_of,
|
|
30
|
+
author: (.fields.creator | person),
|
|
31
|
+
assignees: assignees_of
|
|
32
|
+
}]'
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# Forge concept: issue-search (Jira Cloud via acli)
|
|
3
|
+
# forge-executable: acli
|
|
4
|
+
#
|
|
5
|
+
# Like issue-list, but for the backlog-search webview: includes `body` (the
|
|
6
|
+
# description, flattened from ADF) and honors a requested state, mapped to the
|
|
7
|
+
# status category: open = not Done, closed = Done, all = any category (still a
|
|
8
|
+
# bounded query, which Jira requires).
|
|
9
|
+
#
|
|
10
|
+
# Input (optional): CODEV_ISSUE_STATE — open|closed|all (default: open)
|
|
11
|
+
# CODEV_JIRA_PROJECT, CODEV_JIRA_SITE
|
|
12
|
+
# Output: JSON [{number, title, url, labels, author, assignees, body}]
|
|
13
|
+
set -e
|
|
14
|
+
. "$(dirname "$0")/_lib.sh"
|
|
15
|
+
|
|
16
|
+
case "${CODEV_ISSUE_STATE:-open}" in
|
|
17
|
+
closed) STATE_CLAUSE='statusCategory = Done' ;;
|
|
18
|
+
all) STATE_CLAUSE='statusCategory is not EMPTY' ;;
|
|
19
|
+
*) STATE_CLAUSE='statusCategory != Done' ;;
|
|
20
|
+
esac
|
|
21
|
+
|
|
22
|
+
SCOPE="$(jira_scope)" || exit 1
|
|
23
|
+
SITE="$(jira_site)" || exit 1
|
|
24
|
+
|
|
25
|
+
RAW="$(acli jira workitem search \
|
|
26
|
+
--jql "${SCOPE}${STATE_CLAUSE} ORDER BY created DESC" \
|
|
27
|
+
--fields summary,status,labels,creator,assignee,description \
|
|
28
|
+
--limit 100 \
|
|
29
|
+
--json)"
|
|
30
|
+
|
|
31
|
+
printf '%s' "$RAW" | jq --arg site "$SITE" "$JIRA_JQ_DEFS"'
|
|
32
|
+
[.[] | select(. != null and (.key | type) == "string") | {
|
|
33
|
+
number: .key,
|
|
34
|
+
title: (.fields.summary // ""),
|
|
35
|
+
url: "\($site)/browse/\(.key)",
|
|
36
|
+
labels: labels_of,
|
|
37
|
+
author: (.fields.creator | person),
|
|
38
|
+
assignees: assignees_of,
|
|
39
|
+
body: (.fields.description | adf_text)
|
|
40
|
+
}]'
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# Forge concept: issue-view (Jira Cloud via acli)
|
|
3
|
+
# forge-executable: acli
|
|
4
|
+
# Input: CODEV_ISSUE_ID (e.g. "ENG-123"); CODEV_JIRA_SITE (optional)
|
|
5
|
+
# Output: JSON {title, body, state, url, author, createdAt, assignees, labels, milestone, comments[]} (IssueViewResult)
|
|
6
|
+
#
|
|
7
|
+
# One `workitem view` call carries everything, comments included. Description
|
|
8
|
+
# and comment bodies are Atlassian Document Format, flattened to plain text.
|
|
9
|
+
# `state` is the status *name* (display only); open/closed decisions elsewhere
|
|
10
|
+
# use the status category. Jira has no milestones; the first fix version stands
|
|
11
|
+
# in (optional by contract). `url` is the browser page on the site, never the
|
|
12
|
+
# REST `self` link (which names an infrastructure host).
|
|
13
|
+
set -e
|
|
14
|
+
. "$(dirname "$0")/_lib.sh"
|
|
15
|
+
|
|
16
|
+
jira_require_issue_id || exit 1
|
|
17
|
+
SITE="$(jira_site)" || exit 1
|
|
18
|
+
|
|
19
|
+
RAW="$(acli jira workitem view "$CODEV_ISSUE_ID" \
|
|
20
|
+
--fields summary,description,status,creator,reporter,assignee,labels,created,comment,fixVersions \
|
|
21
|
+
--json)"
|
|
22
|
+
|
|
23
|
+
printf '%s' "$RAW" | jq --arg site "$SITE" "$JIRA_JQ_DEFS"'
|
|
24
|
+
if (.key | type) != "string" then
|
|
25
|
+
error("issue not found: \(env.CODEV_ISSUE_ID)")
|
|
26
|
+
else {
|
|
27
|
+
title: (.fields.summary // ""),
|
|
28
|
+
body: (.fields.description | adf_text),
|
|
29
|
+
state: (.fields.status.name // ""),
|
|
30
|
+
url: "\($site)/browse/\(.key)",
|
|
31
|
+
author: ((.fields.creator // .fields.reporter) | person),
|
|
32
|
+
createdAt: .fields.created,
|
|
33
|
+
assignees: assignees_of,
|
|
34
|
+
labels: labels_of,
|
|
35
|
+
milestone: (if ((.fields.fixVersions // []) | length) > 0 then { title: .fields.fixVersions[0].name } else null end),
|
|
36
|
+
comments: [(.fields.comment.comments // [])[] | {
|
|
37
|
+
body: (.body | adf_text),
|
|
38
|
+
createdAt: .created,
|
|
39
|
+
author: ((.author | person) // { login: "" })
|
|
40
|
+
}]
|
|
41
|
+
} end'
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# Forge concept: recently-closed (Jira Cloud via acli)
|
|
3
|
+
# forge-executable: acli
|
|
4
|
+
# Input (optional): CODEV_SINCE_DATE (ISO 8601), CODEV_JIRA_PROJECT, CODEV_JIRA_SITE
|
|
5
|
+
# Output: JSON [{number, title, url, labels, createdAt, closedAt}]
|
|
6
|
+
#
|
|
7
|
+
# Closed = status category Done, never status names (names are per-site).
|
|
8
|
+
#
|
|
9
|
+
# `workitem search` cannot return dates, but consumers drop items without
|
|
10
|
+
# `closedAt`, so each hit is fetched with `workitem view` (one key per call)
|
|
11
|
+
# for `statuscategorychangedate`, with bounded parallelism. The window is small
|
|
12
|
+
# (the overview asks for the last 24h) and capped at 25 hits.
|
|
13
|
+
#
|
|
14
|
+
# JQL date literals are day-or-minute precision in the user's Jira time zone,
|
|
15
|
+
# so the query bound is the since date minus one day: a superset. The consumer
|
|
16
|
+
# applies the exact cutoff against `closedAt`.
|
|
17
|
+
set -e
|
|
18
|
+
. "$(dirname "$0")/_lib.sh"
|
|
19
|
+
|
|
20
|
+
SCOPE="$(jira_scope)" || exit 1
|
|
21
|
+
SITE="$(jira_site)" || exit 1
|
|
22
|
+
|
|
23
|
+
DATE_CLAUSE=""
|
|
24
|
+
if [ -n "$CODEV_SINCE_DATE" ]; then
|
|
25
|
+
SINCE_DAY="$(jq -rn --arg s "$CODEV_SINCE_DATE" '
|
|
26
|
+
try (
|
|
27
|
+
$s | (if test("T") then . else . + "T00:00:00Z" end)
|
|
28
|
+
| sub("\\.[0-9]+"; "") | fromdateiso8601 - 86400 | strftime("%Y-%m-%d")
|
|
29
|
+
) catch ($s[0:10])')"
|
|
30
|
+
# The fallback takes the input's first ten characters, so validate before it
|
|
31
|
+
# reaches the JQL, as _lib.sh validates keys.
|
|
32
|
+
if ! printf '%s' "$SINCE_DAY" | grep -Eq '^[0-9]{4}-[0-9]{2}-[0-9]{2}$'; then
|
|
33
|
+
echo "jira: invalid CODEV_SINCE_DATE '$CODEV_SINCE_DATE' (expected an ISO 8601 date)" >&2
|
|
34
|
+
exit 1
|
|
35
|
+
fi
|
|
36
|
+
DATE_CLAUSE=" AND statusCategoryChangedDate >= \"$SINCE_DAY\""
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
HITS="$(acli jira workitem search \
|
|
40
|
+
--jql "${SCOPE}statusCategory = Done${DATE_CLAUSE} ORDER BY statusCategoryChangedDate DESC" \
|
|
41
|
+
--fields summary,status,labels \
|
|
42
|
+
--limit 25 \
|
|
43
|
+
--json)"
|
|
44
|
+
|
|
45
|
+
KEYS="$(printf '%s' "$HITS" | jq -r '.[] | select(. != null) | .key | select(type == "string" and test("^[A-Za-z][A-Za-z0-9_]*-[0-9]+$"))')"
|
|
46
|
+
if [ -z "$KEYS" ]; then
|
|
47
|
+
echo '[]'
|
|
48
|
+
exit 0
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
WORK="$(mktemp -d)"
|
|
52
|
+
trap 'rm -rf "${WORK:?}"' EXIT
|
|
53
|
+
|
|
54
|
+
# One file per key, so concurrent views never interleave on a shared stdout.
|
|
55
|
+
# Each view writes a .part file that is renamed only on success: a failed view
|
|
56
|
+
# leaves no .json, its item is emitted without dates (the consumer drops it),
|
|
57
|
+
# and the warning makes that visible.
|
|
58
|
+
printf '%s\n' "$KEYS" | xargs -P 6 -I {} sh -c '
|
|
59
|
+
if acli jira workitem view "$1" --fields created,statuscategorychangedate,resolutiondate --json > "$2/$1.part" 2>/dev/null; then
|
|
60
|
+
mv "$2/$1.part" "$2/$1.json"
|
|
61
|
+
else
|
|
62
|
+
echo "jira: could not fetch dates for $1" >&2
|
|
63
|
+
fi
|
|
64
|
+
' _ {} "$WORK"
|
|
65
|
+
|
|
66
|
+
DATES="$WORK/dates.map"
|
|
67
|
+
if ls "$WORK"/*.json >/dev/null 2>&1; then
|
|
68
|
+
cat "$WORK"/*.json | jq -s 'map(select(.key != null) | { key: .key, value: .fields }) | from_entries' > "$DATES"
|
|
69
|
+
else
|
|
70
|
+
echo '{}' > "$DATES"
|
|
71
|
+
fi
|
|
72
|
+
|
|
73
|
+
printf '%s' "$HITS" | jq --arg site "$SITE" --slurpfile dates "$DATES" "$JIRA_JQ_DEFS"'
|
|
74
|
+
[.[] | select(. != null and (.key | type) == "string") | ($dates[0][.key] // {}) as $d | {
|
|
75
|
+
number: .key,
|
|
76
|
+
title: (.fields.summary // ""),
|
|
77
|
+
url: "\($site)/browse/\(.key)",
|
|
78
|
+
labels: labels_of,
|
|
79
|
+
createdAt: $d.created,
|
|
80
|
+
closedAt: ($d.statuscategorychangedate // $d.resolutiondate)
|
|
81
|
+
}]'
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# Forge concept: user-identity (Jira Cloud via acli)
|
|
3
|
+
# forge-executable: acli
|
|
4
|
+
# Output: plain text — the logged-in account's email
|
|
5
|
+
#
|
|
6
|
+
# acli reports the current account only as `Email:` in `auth status` (no
|
|
7
|
+
# display name or account id), so the email is the identity. The issue scripts
|
|
8
|
+
# map assignees to their email for the same reason, which keeps the "assigned
|
|
9
|
+
# to me" filter matching.
|
|
10
|
+
set -e
|
|
11
|
+
|
|
12
|
+
STATUS="$(acli jira auth status)"
|
|
13
|
+
EMAIL="$(printf '%s\n' "$STATUS" | sed -n 's/^[[:space:]]*Email:[[:space:]]*//p' | head -n 1)"
|
|
14
|
+
if [ -z "$EMAIL" ]; then
|
|
15
|
+
echo "jira: acli auth status reported no account email" >&2
|
|
16
|
+
exit 1
|
|
17
|
+
fi
|
|
18
|
+
printf '%s\n' "$EMAIL"
|
|
@@ -179,13 +179,63 @@ afx tower disconnect # Disconnect from Codev Cloud
|
|
|
179
179
|
|
|
180
180
|
There is NO `afx tower restart` — use `afx tower stop && afx tower start`.
|
|
181
181
|
|
|
182
|
+
## afx ide
|
|
183
|
+
|
|
184
|
+
Manages the Codev IDE server (VS Code server-web) that Tower forwards at `/ide/`. Tower spawns
|
|
185
|
+
and owns the process; these commands drive it. Open a workspace at
|
|
186
|
+
`http://localhost:4100/ide/?folder=<abs path>`.
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
afx ide install # npm i -g @cluesmith/codev-ide, then report the installed version
|
|
190
|
+
afx ide start # Find codev-ide-server, ask Tower to spawn it (port 8200)
|
|
191
|
+
afx ide start --server-path <bin> # Use this binary instead of discovery
|
|
192
|
+
afx ide start -p <port> # Run the server on another port
|
|
193
|
+
afx ide stop # Stop the server
|
|
194
|
+
afx ide status # Port, PID, server path/version, extensions dir, sidebar version
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
**Discovery** (when `--server-path` is absent): `codev-ide-server` on `PATH`, then
|
|
198
|
+
`@cluesmith/codev-ide` next to the running codev install, then under `npm root -g`. Nothing
|
|
199
|
+
found exits 1 before Tower is contacted, naming `afx ide install` and `--server-path`.
|
|
200
|
+
|
|
201
|
+
**On every start** Tower checks `codev-ide-server --version` against a minimum (an older server
|
|
202
|
+
is refused with the installed version, the floor, and the upgrade command), installs the
|
|
203
|
+
sidebar vsix that ships inside `@cluesmith/codev` into `~/.agent-farm/ide-extensions` (skipped
|
|
204
|
+
when that version is already installed; other extensions in the directory are left alone), and
|
|
205
|
+
spawns the server with `--extensions-dir` pointing there. The first start can take a minute or more.
|
|
206
|
+
|
|
207
|
+
The server loads extensions only from `~/.agent-farm/ide-extensions`, so anything installed into
|
|
208
|
+
its default extensions directory is no longer loaded. Install additional extensions there:
|
|
209
|
+
`codev-ide-server --install-extension <id-or-vsix> --extensions-dir ~/.agent-farm/ide-extensions`.
|
|
210
|
+
|
|
211
|
+
A server that is already running is never killed by `start`. If it predates the current server
|
|
212
|
+
or sidebar, `start` warns: restart it with `afx ide stop && afx ide start`.
|
|
213
|
+
|
|
214
|
+
There is NO `afx ide restart` and NO `afx ide upgrade`. To upgrade, run `afx ide install`, then
|
|
215
|
+
`afx ide stop && afx ide start`.
|
|
216
|
+
|
|
182
217
|
## afx workspace
|
|
183
218
|
|
|
184
219
|
```bash
|
|
185
220
|
afx workspace start # Start workspace for current project
|
|
186
221
|
afx workspace stop # Stop workspace processes
|
|
222
|
+
afx workspace add-architect --name <name> # Add a named sibling architect terminal
|
|
223
|
+
afx workspace remove-architect <name> # Remove a sibling architect (cannot remove main)
|
|
224
|
+
afx workspace recover # Revive builders whose shellper died (e.g. after reboot)
|
|
187
225
|
```
|
|
188
226
|
|
|
227
|
+
**Recreating a dead architect** (its process died while Tower kept the registration):
|
|
228
|
+
re-add it under the SAME name, then re-init its identity:
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
afx workspace add-architect --name <name>
|
|
232
|
+
afx send architect:<name> "/arch-init <name>"
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Builder-to-architect affinity survives the death (builders keep their Owner), so a
|
|
236
|
+
same-name re-add restores routing with no worktree impact and no builder disruption.
|
|
237
|
+
`afx workspace recover` revives builders only, not architects.
|
|
238
|
+
|
|
189
239
|
`afx dash` is a deprecated alias — use `afx workspace` instead.
|
|
190
240
|
|
|
191
241
|
## afx cron
|
|
@@ -220,5 +270,6 @@ afx open <file> # Open file in annotation viewer (NOT system ope
|
|
|
220
270
|
afx shell # Spawn utility shell
|
|
221
271
|
afx attach # Attach to running builder terminal
|
|
222
272
|
afx rename <name> # Rename current shell session
|
|
273
|
+
afx decisions init # Create the decisions file; turns on the Decisions tab
|
|
223
274
|
afx architect # Start architect session in current terminal
|
|
224
275
|
```
|
|
@@ -46,12 +46,56 @@ name in a multi-architect workspace).
|
|
|
46
46
|
(`codev/state/*.md`); never commit them. Builder `*_thread.md` files
|
|
47
47
|
are the opposite: versioned, shipping with each builder PR.
|
|
48
48
|
|
|
49
|
-
3. **Confirm identity + orient
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
49
|
+
3. **Confirm identity + orient.** In one tight block, report: who you now are
|
|
50
|
+
(name + one-line role from the banner, if present), the file you read, and
|
|
51
|
+
the current-state / open-loops summary from the most recent dated section
|
|
52
|
+
(or the file's leading content if it has no dated sections). If the banner
|
|
53
|
+
carries a `NEXT TASK` line, report both halves of it, as
|
|
54
|
+
`Next task from the owner at save time: <verbatim> → resolved: <gloss>`
|
|
55
|
+
(omit `→ resolved: …` when the line carries no `[resolved at save: …]` gloss).
|
|
56
|
+
|
|
57
|
+
4. **Start on the next task, if the banner carries one.** It is the **first
|
|
58
|
+
action of the resumed session**, ahead of the general resume agenda — the
|
|
59
|
+
owner wrote it at save time precisely so it would not have to be typed
|
|
60
|
+
again once you came back. Begin it without waiting for a further prompt.
|
|
61
|
+
- It carries the owner's authority the way any owner message does, **with
|
|
62
|
+
the standard limits unchanged**. A next task never by itself approves a
|
|
63
|
+
porch gate, merges a PR, cuts a release, restarts Tower, or performs any
|
|
64
|
+
other act that needs a per-occasion word. If the next task *is* such an
|
|
65
|
+
act, prepare it and ask for the word live: a saved instruction is an
|
|
66
|
+
instruction, not a pre-spent approval.
|
|
67
|
+
- **The gloss carries the word — for the items it names, and only them.**
|
|
68
|
+
Items named in a `[resolved at save: …]` gloss are approved for the act
|
|
69
|
+
the owner's words name: "merge them all [resolved at save: PRs #1710,
|
|
70
|
+
#1712]" means merge #1710 and #1712 without asking again. The owner gave
|
|
71
|
+
the word at save time, and the saving session pinned it to those items.
|
|
72
|
+
This narrows the rule above; it does not remove it — and a line with no
|
|
73
|
+
gloss pre-approves nothing:
|
|
74
|
+
- The act must be the one the owner's words say. **A gloss never widens
|
|
75
|
+
the verb** — "merge" does not also approve a release.
|
|
76
|
+
- **Anything not in the gloss still needs the word live.** A PR that
|
|
77
|
+
appeared after the save, an item the gloss did not name, a gate the
|
|
78
|
+
words did not mention → prepare and ask, exactly as above.
|
|
79
|
+
- Porch gates are still relayed to the builder, never run by you: the
|
|
80
|
+
gloss lets you *relay* the approval without re-asking; it does not
|
|
81
|
+
change who runs `porch approve`.
|
|
82
|
+
- Ordinary verification still applies: an approved merge still waits for
|
|
83
|
+
green CI, and a gloss item you find already merged, closed, or changed
|
|
84
|
+
is reported, not forced.
|
|
85
|
+
- **A line marked `[carried over — …]` is orientation only.** Its gloss
|
|
86
|
+
was written by an earlier cycle and carries no word: ask for it before
|
|
87
|
+
any gated act.
|
|
88
|
+
- **This does not narrow the gate rule.** The human decision was explicit
|
|
89
|
+
at save time, and the gloss is its record. What the rule forbids —
|
|
90
|
+
inferring approval from a gate notification, from silence, or from an
|
|
91
|
+
agent's own judgment — stays forbidden; a gloss is none of those.
|
|
92
|
+
- **Once you have started, delete the `NEXT TASK` line from the banner**
|
|
93
|
+
and record the pickup as a log entry (`picked up next task: <verbatim>
|
|
94
|
+
→ resolved: <gloss>`, omitting `→ resolved: …` when there was no gloss).
|
|
95
|
+
A second re-init, or the next `/arch-save`, must not re-run it.
|
|
96
|
+
|
|
97
|
+
5. **Then follow the state file.** Carry out whatever it says to do on
|
|
98
|
+
resume. Do not invent a new agenda — resume the one the state file
|
|
55
99
|
describes.
|
|
56
100
|
|
|
57
101
|
## Saving your state (and knowing when to `/clear`)
|
|
@@ -118,9 +162,12 @@ Do not repeat it, and do not prompt for it at any other time.
|
|
|
118
162
|
**`/arch-save` packages this whole loop**, and is the preferred path when the
|
|
119
163
|
owner directs a refresh: it stops your monitors, writes the pruned state file,
|
|
120
164
|
clears, and schedules `/arch-init` to bring you back — in that order, which is
|
|
121
|
-
the part that matters.
|
|
122
|
-
|
|
123
|
-
|
|
165
|
+
the part that matters. It also accepts a **next task** as free text
|
|
166
|
+
(`/arch-save file and spawn that issue`), which it writes into the banner as a
|
|
167
|
+
`NEXT TASK` line for step 4 above to pick up. The save discipline above is
|
|
168
|
+
what it performs at its step 3, so this section remains the source of truth
|
|
169
|
+
for *how to write the file*; `/arch-save` is the source of truth for *the
|
|
170
|
+
sequence*. The manual path
|
|
124
171
|
(save → human clears → `/arch-init`) stays valid and is the fallback when
|
|
125
172
|
Tower is unavailable.
|
|
126
173
|
|