@amsterdamdatalabs/enact-extensions 0.1.5 → 0.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/README.md +2 -2
  2. package/dist/index.d.ts +2 -0
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +1 -0
  5. package/dist/index.js.map +1 -1
  6. package/dist/install.d.ts.map +1 -1
  7. package/dist/install.js +15 -1
  8. package/dist/install.js.map +1 -1
  9. package/dist/internal/agents.d.ts +29 -0
  10. package/dist/internal/agents.d.ts.map +1 -0
  11. package/dist/internal/agents.js +83 -0
  12. package/dist/internal/agents.js.map +1 -0
  13. package/extensions/enact-context/hooks/hooks.json +20 -0
  14. package/extensions/enact-core/.agents/plugin.json +39 -0
  15. package/extensions/enact-core/hooks/hooks.json +14 -0
  16. package/extensions/enact-factory/.agents/plugin.json +9 -3
  17. package/extensions/enact-factory/agents/architect.toml +30 -0
  18. package/extensions/enact-factory/agents/code-reviewer.toml +29 -0
  19. package/extensions/enact-factory/agents/critic.toml +35 -0
  20. package/extensions/enact-factory/agents/executor.toml +23 -0
  21. package/extensions/enact-factory/agents/explore.toml +22 -0
  22. package/extensions/enact-factory/agents/planner.toml +23 -0
  23. package/extensions/enact-factory/agents/verifier.toml +29 -0
  24. package/extensions/enact-factory/skills/ai-slop-cleaner/SKILL.md +52 -0
  25. package/extensions/enact-factory/skills/azdo-ci-strategy/SKILL.md +262 -0
  26. package/extensions/enact-factory/skills/azdo-ci-strategy/references/build-failures.md +60 -0
  27. package/extensions/enact-factory/skills/azdo-ci-strategy/references/cli-reference.md +87 -0
  28. package/extensions/enact-factory/skills/azdo-ci-strategy/references/policies-and-pipelines.md +132 -0
  29. package/extensions/enact-factory/skills/azdo-ci-strategy/references/troubleshooting.md +53 -0
  30. package/extensions/enact-factory/skills/deep-interview/SKILL.md +72 -0
  31. package/extensions/enact-factory/skills/drive-loop/SKILL.md +259 -0
  32. package/extensions/enact-factory/skills/drive-loop/references/contract-schema.md +107 -0
  33. package/extensions/enact-factory/skills/hyperplan/SKILL.md +51 -0
  34. package/extensions/enact-factory/skills/looplan/SKILL.md +103 -0
  35. package/extensions/enact-factory/skills/plan/SKILL.md +71 -0
  36. package/extensions/enact-factory/skills/remove-deadcode/SKILL.md +41 -0
  37. package/extensions/enact-factory/skills/research/SKILL.md +73 -0
  38. package/extensions/enact-factory/skills/review/SKILL.md +48 -0
  39. package/extensions/enact-factory/skills/security-research/SKILL.md +54 -0
  40. package/extensions/enact-factory/skills/tdd/SKILL.md +56 -0
  41. package/extensions/enact-factory/skills/trace/SKILL.md +37 -0
  42. package/extensions/enact-factory/skills/ultraqa/SKILL.md +79 -0
  43. package/extensions/enact-factory/skills/work-with-workitem/SKILL.md +51 -0
  44. package/extensions/enact-factory/skills/workitem-triage/SKILL.md +15 -0
  45. package/extensions/enact-loop/.agents/plugin.json +46 -0
  46. package/extensions/enact-loop/.mcp.json +1 -0
  47. package/extensions/enact-loop/hooks/hooks.json +27 -0
  48. package/extensions/enact-loop/skills/enact-loop/SKILL.md +327 -0
  49. package/extensions/enact-operator/.agents/plugin.json +0 -1
  50. package/extensions/enact-operator/hooks/hooks.json +0 -35
  51. package/extensions/enact-wiki/skills/wiki/SKILL.md +42 -0
  52. package/extensions/plugin-dev/.agents/plugin.json +4 -6
  53. package/extensions/plugin-dev/agents/plugin-validator.md +1 -1
  54. package/extensions/plugin-dev/skills/agent-development/SKILL.md +7 -7
  55. package/extensions/plugin-dev/{commands/create-plugin.md → skills/create-plugin/SKILL.md} +44 -37
  56. package/extensions/plugin-dev/skills/plugin-dev-guide/SKILL.md +13 -14
  57. package/extensions/plugin-dev/skills/skill-development/SKILL.md +0 -2
  58. package/extensions/plugin-dev/{commands/start.md → skills/start/SKILL.md} +7 -6
  59. package/package.json +11 -6
  60. package/scripts/check-hooks.mjs +174 -0
  61. package/scripts/check-principles.mjs +101 -0
  62. package/scripts/enact-extensions.mjs +87 -3
  63. package/scripts/lib/run-validate.mjs +36 -2
  64. package/scripts/lib/ups-router.mjs +432 -0
  65. package/spec/enact.json +4 -0
  66. package/spec/enact.md +5 -2
  67. package/extensions/cmux/.agents/plugin.json +0 -37
  68. package/extensions/cmux/skills/cmux/SKILL.md +0 -82
  69. package/extensions/cmux/skills/cmux/agents/openai.yaml +0 -4
  70. package/extensions/cmux/skills/cmux/references/handles-and-identify.md +0 -35
  71. package/extensions/cmux/skills/cmux/references/panes-surfaces.md +0 -37
  72. package/extensions/cmux/skills/cmux/references/trigger-flash-and-health.md +0 -23
  73. package/extensions/cmux/skills/cmux/references/windows-workspaces.md +0 -31
  74. package/extensions/cmux/skills/cmux-vm-monitor/SKILL.md +0 -122
  75. package/extensions/cmux/skills/cmux-vm-monitor/agents/openai.yaml +0 -4
  76. package/extensions/cmux/skills/cmux-vm-monitor/references/cmux-commands.md +0 -66
  77. package/extensions/cmux/skills/cmux-vm-monitor/scripts/codex_vm_monitor.sh +0 -45
  78. package/extensions/cmux/skills/cmux-workspace/SKILL.md +0 -93
  79. package/extensions/devops/.agents/plugin.json +0 -36
  80. package/extensions/devops/skills/azure-devops-cli/SKILL.md +0 -431
  81. package/extensions/devops/skills/azure-devops-cli/agents/openai.yaml +0 -4
  82. package/extensions/devops/skills/ci-pipeline-strategy/SKILL.md +0 -217
  83. package/extensions/devops/skills/ci-pipeline-strategy/agents/openai.yaml +0 -4
  84. package/extensions/enact-factory/hooks/user-prompt-submit.mjs +0 -67
  85. package/extensions/enact-operator/commands/doctor.md +0 -39
  86. package/extensions/enact-operator/commands/setup.md +0 -51
  87. package/extensions/plugin-dev/.mcp.json +0 -3
  88. package/extensions/plugin-dev/commands/_archive/create-marketplace.md +0 -427
  89. package/extensions/plugin-dev/commands/_archive/plugin-dev-guide.md +0 -12
  90. package/extensions/plugin-dev/hooks/hooks.json +0 -3
  91. package/extensions/plugin-dev/skills/command-development/SKILL.md +0 -763
  92. package/extensions/plugin-dev/skills/command-development/examples/plugin-commands.md +0 -612
  93. package/extensions/plugin-dev/skills/command-development/examples/simple-commands.md +0 -527
  94. package/extensions/plugin-dev/skills/command-development/references/advanced-workflows.md +0 -762
  95. package/extensions/plugin-dev/skills/command-development/references/documentation-patterns.md +0 -769
  96. package/extensions/plugin-dev/skills/command-development/references/frontmatter-reference.md +0 -508
  97. package/extensions/plugin-dev/skills/command-development/references/interactive-commands.md +0 -966
  98. package/extensions/plugin-dev/skills/command-development/references/marketplace-considerations.md +0 -943
  99. package/extensions/plugin-dev/skills/command-development/references/plugin-features-reference.md +0 -637
  100. package/extensions/plugin-dev/skills/command-development/references/plugin-integration.md +0 -191
  101. package/extensions/plugin-dev/skills/command-development/references/skill-tool.md +0 -447
  102. package/extensions/plugin-dev/skills/command-development/references/testing-strategies.md +0 -723
  103. package/extensions/plugin-dev/skills/command-development/scripts/check-frontmatter.sh +0 -234
  104. package/extensions/plugin-dev/skills/command-development/scripts/validate-command.sh +0 -160
  105. /package/extensions/enact-operator/{skills/_variants.md → docs/skill-variants.md} +0 -0
@@ -0,0 +1,23 @@
1
+ name = "planner"
2
+ description = "Structured implementation planner that never writes production code"
3
+ model_reasoning_effort = "medium"
4
+ sandbox_mode = "danger-full-access"
5
+ developer_instructions = """
6
+ You are the Enact Loop planner agent.
7
+
8
+ Role:
9
+ - Turn a goal into a small, reviewable execution plan with clear acceptance criteria.
10
+ - You do not implement code.
11
+
12
+ Rules:
13
+ - Never write production code.
14
+ - Prefer 3 to 6 concrete steps.
15
+ - Include dependencies, risks, and verification expectations.
16
+ - Escalate unresolved product-direction choices instead of guessing.
17
+
18
+ Output contract:
19
+ - plan_summary
20
+ - steps
21
+ - acceptance_criteria
22
+ - risks_and_open_questions
23
+ """
@@ -0,0 +1,29 @@
1
+ name = "verifier"
2
+ description = "Evidence-first verifier for real-surface QA and completion claims — independent grader"
3
+ model_reasoning_effort = "high"
4
+ sandbox_mode = "danger-full-access"
5
+ tools = "Read, Grep, Glob, Bash"
6
+ developer_instructions = """
7
+ You are the Enact Loop verifier agent. You are an INDEPENDENT GRADER.
8
+
9
+ You run on a different model and vendor from the executor. You must reach your own verdict
10
+ independently — do not defer to the executor's self-assessment. Your verdict is recorded by
11
+ `loop_grader_verdict` and is required before the judgment stage can close.
12
+
13
+ Role:
14
+ - Check whether completion claims are supported by fresh evidence.
15
+ - Focus on commands run, outputs observed, and uncovered gaps.
16
+
17
+ Rules:
18
+ - Never edit files.
19
+ - Do not trust prior claims without rerunning or directly reading evidence.
20
+ - Mark each requirement VERIFIED, PARTIAL, or MISSING.
21
+ - Separate missing evidence from failing behavior.
22
+ - Record your GO/NO-GO verdict via loop_grader_verdict — do not self-report on behalf of the executor.
23
+
24
+ Output contract:
25
+ - verdict: PASS, FAIL, or INCOMPLETE
26
+ - evidence: commands and observed results
27
+ - requirement_matrix
28
+ - remaining_gaps
29
+ """
@@ -0,0 +1,52 @@
1
+ ---
2
+ name: ai-slop-cleaner
3
+ description: "Walk the diff for TODO/placeholder/silent-catch noise and replace each with a concrete implementation or remove it entirely."
4
+ ---
5
+
6
+ # AI Slop Cleaner
7
+
8
+ ## Purpose
9
+
10
+ Removes low-quality AI-generated residue from code produced in a loop session: `// TODO`,
11
+ "for now", "later", silent empty catch blocks, unreachable fallback layers, and placeholder strings.
12
+ Each removal is replaced with a real implementation or an explicit compile-time error — never just
13
+ deleted.
14
+
15
+ ## Use When
16
+
17
+ - after an implementation pass before the loop reaches closure
18
+ - before verification stages run
19
+ - when a diff review reveals TODO comments, "for now" strings, or swallowed exceptions
20
+
21
+ ## Workflow
22
+
23
+ 1. Identify the files changed in the current session (use `git diff --name-only`).
24
+ 2. For each changed file, scan for these patterns:
25
+ - `// TODO`, `// FIXME`, `// HACK`, `// XXX`
26
+ - String literals containing "for now", "placeholder", "stub", "later", "not yet implemented"
27
+ - Empty catch blocks or catch blocks that only log without re-throwing or handling
28
+ - Fallback return values that hide real errors (e.g., `return null`, `return []` with no explanation)
29
+ - Dead code gated on `if (false)` or `if (process.env.NEVER)`
30
+ 3. For each hit, choose one action:
31
+ - Replace with a real implementation if the intent is clear
32
+ - Replace with an explicit thrown error if the path should never be reached
33
+ - Remove the dead code entirely if it adds no value
34
+ 4. After cleanup, re-run the project's doctor/lint check to confirm nothing broken.
35
+ 5. Re-run the project's test suite to confirm no regressions.
36
+ 6. Run a second grep pass to confirm zero hits remain:
37
+ ```
38
+ grep -rE "TODO|FIXME|HACK|for now|placeholder|stub" <changed-files>
39
+ ```
40
+
41
+ ## State Contract
42
+
43
+ - Reads: changed files in the working tree
44
+ - Writes: same files (in-place edits only); no new files, no new state in `.enact/loop/`
45
+
46
+ ## Final Check
47
+
48
+ - Zero `TODO`, `FIXME`, `HACK`, or placeholder strings in changed files
49
+ - No empty or swallowed catch blocks remain
50
+ - Doctor/lint still passes after cleanup
51
+ - Test suite still passes after cleanup
52
+ - No code was deleted without a replacement or explicit error
@@ -0,0 +1,262 @@
1
+ ---
2
+ name: azdo-ci-strategy
3
+ description: >-
4
+ Azure DevOps CI/CD for enact-os: the branch / PR / release strategy plus the
5
+ az CLI + REST commands to run it. Use when opening or promoting PRs (to
6
+ integration or main), setting branch policies (merge-strategy,
7
+ build-validation), registering pipelines, diagnosing why a pipeline did not
8
+ trigger, or reading build failures. Triggers on "PR to integration", "promote
9
+ to main", "pipeline failing", "branch policy", "az repos", "az pipelines".
10
+ compatibility: >-
11
+ Requires the az CLI (>= 2.30) with the azure-devops extension, an
12
+ authenticated `az login`, and network access to an Azure DevOps organization.
13
+ metadata:
14
+ author: Amsterdam Data Labs
15
+ version: 1.0.0
16
+ ---
17
+
18
+ # Azure DevOps CI/CD Strategy — enact-os
19
+
20
+ The enact-os branch / release strategy and pipeline conventions. The `az` CLI
21
+ and REST command catalogs live in `references/` (see [Reference files](#reference-files))
22
+ and load on demand — this file holds the strategy and the everyday workflow.
23
+
24
+ > **Relationship to the `enact-factory` MCP server.** This is a standalone
25
+ > knowledge skill — it needs only the `az` CLI, no MCP server. When the
26
+ > `enact-factory` MCP *is* available, prefer its tools (`factory_workitem_*`,
27
+ > pipeline governance) for **live board/WorkItem/pipeline state**; use the
28
+ > CLI/REST recipes here for **branch & merge policies, PR creation/promotion,
29
+ > and build-failure diagnosis** — the operations the MCP doesn't cover, or for
30
+ > when it isn't connected. See the sibling `workitem-triage` skill for the
31
+ > read-only WorkItem triage surface.
32
+
33
+ ## Branch flow
34
+
35
+ ```text
36
+ feat/* PR to integration ── PR CI ──► auto-merge to integration
37
+ fix/* PR to integration ── PR CI ──► auto-merge to integration
38
+ integration ── automation creates or updates one PR to main ──► main
39
+ main ── manual approval + CI ──► publish
40
+ ```
41
+
42
+ - Branch from `integration` (never from `main`). One branch per logical unit,
43
+ kebab-case. Never commit directly to `integration` or `main`.
44
+ - **Create a fresh branch only when no open PR to `integration` is left
45
+ outstanding** for your prior work — let that PR merge (or close it) first. Keep
46
+ one open `integration` PR at a time so the branch → PR → merge cycle stays
47
+ serialized and you never stack new work on a base that's still moving. Check
48
+ before branching:
49
+
50
+ ```bash
51
+ az repos pr list --target-branch integration --status active \
52
+ --creator "$(az account show --query user.name -o tsv)" -o table
53
+ ```
54
+ - `feat/*` — new functionality, tooling, or docs. `fix/*` — bug/CI/config fixes.
55
+
56
+ ## Setup
57
+
58
+ ```bash
59
+ az extension add --name azure-devops # az cli 2.30+
60
+ az login
61
+ ```
62
+
63
+ For any command surface not spelled out in the references, run `az <group>
64
+ --help` — e.g. `az repos pr --help`, `az pipelines --help`, `az devops --help`.
65
+ The references document only the non-obvious flags, gotchas, and the REST calls
66
+ the CLI can't make; the CLI's own help covers the rest.
67
+
68
+ ## Variables
69
+
70
+ Every command and URL in this skill (including the reference files) references
71
+ these. Set them once per shell (or pass `--detect` inside a repo to infer
72
+ org/project from the git remote). Nothing here is tied to one tenant —
73
+ substitute your own org/project:
74
+
75
+ ```bash
76
+ ORG_URL="https://dev.azure.com/<your-org>" # e.g. .../amsterdamdatalabs
77
+ PROJECT="<your-project>" # e.g. Enact
78
+ AZDO_RESOURCE="499b84ac-1321-427f-aa17-267ca6975798" # constant AAD app id for AzDO access tokens
79
+
80
+ # Optional: set CLI defaults so --org/--project can be omitted on every command.
81
+ az devops configure --defaults organization="$ORG_URL" project="$PROJECT"
82
+ ```
83
+
84
+ ## Developer workflow
85
+
86
+ 0. Before starting any task: confirm you have no open `integration` PR left from
87
+ prior work, then sync local `integration` and branch from it:
88
+
89
+ ```bash
90
+ # Gate: must return nothing before you branch (let any prior PR merge/close first)
91
+ az repos pr list --target-branch integration --status active \
92
+ --creator "$(az account show --query user.name -o tsv)" -o table
93
+
94
+ git checkout integration
95
+ git pull --ff-only origin integration
96
+ git checkout -b feat/my-branch # or fix/my-branch
97
+ ```
98
+
99
+ 1. Work on a `feat/*` or `fix/*` branch.
100
+ 2. Run local Docker CI before opening a PR. Each package has a wrapper at
101
+ `./scripts/ci-local-<package>.sh` (run from the `enact-os` workspace root):
102
+
103
+ - `ci-local-agent.sh` · `ci-local-context.sh` · `ci-local-eval.sh`
104
+ - `ci-local-factory.sh` · `ci-local-gateway.sh` · `ci-local-observe.sh`
105
+ - `ci-local-operator.sh` · `ci-local-proc-tap.sh` · `ci-local-runtime.sh`
106
+ - `ci-local-voice.sh` · `ci-local-watchdog.sh` · `ci-local-wiki.sh`
107
+
108
+ (Verify the exact set with `ls scripts/ci-local-*.sh` — it grows as packages
109
+ are added.) For `enact-factory` and `enact-wiki`, the Docker wrapper is the
110
+ source of truth for Azure parity; direct host-local Vitest can differ because
111
+ of optional native bindings on non-Linux machines.
112
+
113
+ 3. Open a PR targeting **`integration`** only — never directly to `main`. Always
114
+ pass **both** `--auto-complete true` and `--delete-source-branch true` (these
115
+ are NOT inherited by CLI-created PRs — see the auto-complete gotcha in
116
+ `references/cli-reference.md`):
117
+
118
+ ```bash
119
+ az repos pr create \
120
+ --source-branch feat/my-branch \
121
+ --target-branch integration \
122
+ --title "feat: description" \
123
+ --auto-complete true \
124
+ --delete-source-branch true \
125
+ --detect
126
+ ```
127
+
128
+ 4. CI runs automatically on the PR. When CI passes the PR **auto-merges** into
129
+ `integration`. No reviewer is required on integration.
130
+ 5. After each successful merge to `integration`, automation creates or updates
131
+ one open `integration → main` PR.
132
+ 6. The `integration → main` PR stays **manual** — owner approval on it is the
133
+ release gate. (Create/update commands: `references/cli-reference.md`.)
134
+
135
+ ## CI triggers
136
+
137
+ | Trigger | What runs |
138
+ | ------------------------------------------- | ----------------------------------------------------------------------------------------------- |
139
+ | Push to `feat/*` | Build + test + lint |
140
+ | Push to `fix/*` | **Nothing** — local Docker CI is the gate |
141
+ | PR opened / updated targeting `integration` | Build + test + lint |
142
+ | Push to `integration` (after PR merged) | Build + test + lint |
143
+ | Push to `main` (after PR merged) | Build + test + lint + **Publish** for publishable packages; CI only for internal-only packages |
144
+
145
+ > **⛔ NEVER use `az pipelines run` to manually trigger CI as a substitute for a
146
+ > PR push.** Manual runs do not update PR build status and give false
147
+ > confidence. If CI is not triggering on a PR, push a new commit (even empty):
148
+ >
149
+ > ```bash
150
+ > git commit --allow-empty -m "ci: re-trigger pipeline"
151
+ > git push
152
+ > ```
153
+ >
154
+ > The only permitted use of `az pipelines run` is a deliberate Publish-stage
155
+ > retag/hotfix on `main`, performed explicitly by the repo owner.
156
+
157
+ ## Publish gate
158
+
159
+ - Publish only runs on `refs/heads/main`.
160
+ - `main` is branch-protected — direct push blocked; only PR merges allowed.
161
+ - Internal-only packages can omit a publish stage while keeping the same
162
+ `integration` / `main` CI trigger pattern.
163
+ - Merging the `integration → main` PR IS the manual approval for publish.
164
+ - Version bumps are done manually by the repo owner before approving that PR.
165
+
166
+ ## Version management
167
+
168
+ - No automated changesets or version bots.
169
+ - Repo owner bumps `package.json` / `Cargo.toml` version manually.
170
+ - Automation opens or updates the `integration → main` PR.
171
+ - Repo owner merges that PR to trigger publish.
172
+
173
+ ## Pipeline trigger config (all packages)
174
+
175
+ ```yaml
176
+ trigger:
177
+ branches:
178
+ include:
179
+ - integration
180
+ - feat/*
181
+ - main
182
+
183
+ pr:
184
+ branches:
185
+ include:
186
+ - integration
187
+ ```
188
+
189
+ `feat/*` is included so pushes to feature branches run CI (per the table above);
190
+ `fix/*` is intentionally excluded — local Docker CI is its only gate.
191
+
192
+ Publish stage condition:
193
+
194
+ ```yaml
195
+ condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
196
+ ```
197
+
198
+ ## Version pins for local CI scripts
199
+
200
+ Tool versions for all `ci-local-*.sh` scripts are pinned in
201
+ `scripts/ci-versions.env`:
202
+
203
+ ```bash
204
+ NODE_IMAGE="node:22-bookworm"
205
+ ZIG_VERSION="0.14.0"
206
+ PYTHON_IMAGE="python:3.12-bookworm"
207
+ UV_VERSION="0.11.8" # must match enact-observe/pyproject.toml [tool.uv]
208
+ ```
209
+
210
+ When upgrading a tool version: (1) update `scripts/ci-versions.env`, **then**
211
+ (2) update the `variables:` block in the relevant `azure-pipelines.yml` — Azure
212
+ Pipelines does NOT read this file; keep the two in sync manually.
213
+
214
+ ## Version-skip pattern
215
+
216
+ All publish steps must handle already-published versions gracefully:
217
+
218
+ - **npm public**: check `npm view <pkg> version`, skip if matches local.
219
+ - **Azure Artifacts**: catch `403|409|already exist|upstream sources`, exit 0.
220
+ - **cargo**: check the Azure Artifacts sparse index or crates.io API, skip if
221
+ the version already exists.
222
+
223
+ ## Examples
224
+
225
+ **"Open a PR for my fix branch."**
226
+ → Run the step-0 gate (no open integration PR), then `az repos pr create` to
227
+ `integration` with `--auto-complete true --delete-source-branch true`.
228
+ → Result: PR opens, CI runs, and on green it auto-merges — no reviewer needed.
229
+
230
+ **"Promote integration to main."**
231
+ → Create/update the `integration → main` PR (NO `--auto-complete`,
232
+ `references/cli-reference.md`). → Result: PR awaits the owner's approval; merging
233
+ it triggers the versioned publish.
234
+
235
+ **"Why didn't CI run on my PR?"**
236
+ → Follow the diagnosis in `references/build-failures.md`: push an empty commit,
237
+ confirm the build-validation policy is enabled, ensure the PR is open and
238
+ targets `integration`. → Result: the pipeline re-queues on the next push event.
239
+
240
+ **"The pipeline is red — what failed?"**
241
+ → Pull the build timeline via token + curl (`references/build-failures.md`) while
242
+ logs are still live. → Result: a printed list of failed Task/Job/Stage records
243
+ with their first error messages.
244
+
245
+ ## Reference files
246
+
247
+ Detailed command catalogs live under `references/` and load on demand. They all
248
+ assume the [Variables](#variables) above are set.
249
+
250
+ - **`references/cli-reference.md`** — az command catalog (PRs, work items,
251
+ pipelines, repos), the full PR workflow, the auto-complete gotcha, common flags.
252
+ - **`references/policies-and-pipelines.md`** — REST recipes for merge-strategy
253
+ and build-validation policies, registering a pipeline, variable-group
254
+ authorization.
255
+ - **`references/build-failures.md`** — pull failing-build timelines/logs via
256
+ token + curl; diagnose why CI did not trigger.
257
+ - **`references/troubleshooting.md`** — `msrestazure` fix, `az repos` vs
258
+ `az devops`, pipeline bootstrap gotchas, first-run checklist.
259
+
260
+ ## Canonical doc
261
+
262
+ `enact-docs/05-operations/cross-package/git-branching-strategy.md`
@@ -0,0 +1,60 @@
1
+ # Reading build failures & diagnosing CI
2
+
3
+ Assumes the **Variables** block from `../SKILL.md` is set (`$ORG_URL`,
4
+ `$PROJECT`, `$AZDO_RESOURCE`).
5
+
6
+ ## Reading build failure output
7
+
8
+ AzDO pipeline logs expire quickly (timeline returns HTTP 204 after ~24h). Get
9
+ them while the run is fresh. **`az rest` does NOT work for AzDO URLs** — it
10
+ cannot derive the right AAD scope; use a bearer token + `curl`.
11
+
12
+ ```bash
13
+ TOKEN=$(az account get-access-token \
14
+ --resource "$AZDO_RESOURCE" \
15
+ --query accessToken -o tsv)
16
+
17
+ # Failure summary from the build timeline (works while logs are live)
18
+ curl -s -H "Authorization: Bearer $TOKEN" \
19
+ "$ORG_URL/$PROJECT/_apis/build/builds/<buildId>/timeline?api-version=7.1" \
20
+ | python3 -c "
21
+ import sys, json
22
+ d = json.load(sys.stdin)
23
+ failed = [r for r in d.get('records', [])
24
+ if r.get('result') == 'failed' and r.get('type') in ('Task','Job','Stage')]
25
+ for r in sorted(failed, key=lambda x: x.get('order', 0)):
26
+ print(r.get('type'), '|', r.get('name'))
27
+ for i in (r.get('issues') or [])[:3]:
28
+ print(' !', i.get('message', '')[:300])
29
+ "
30
+
31
+ # Logs container URL from a run
32
+ az pipelines runs show --id <run-id> --output json \
33
+ | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['logs']['url'])"
34
+
35
+ # Fetch a specific log entry (<logId> from the logs index)
36
+ curl -s -H "Authorization: Bearer $TOKEN" \
37
+ "$ORG_URL/$PROJECT/_apis/build/builds/<buildId>/logs/<logId>?api-version=7.1"
38
+ ```
39
+
40
+ Timeline returns HTTP 204 (empty) once logs expire — check the AzDO web UI then.
41
+
42
+ ## Diagnosing why CI did not trigger on a PR
43
+
44
+ CI should trigger automatically when commits land on a PR source branch. If it
45
+ doesn't, do NOT manually queue a run:
46
+
47
+ 1. **Push a new commit** (even empty) to the source branch:
48
+ ```bash
49
+ git commit --allow-empty -m "ci: re-trigger pipeline"
50
+ git push
51
+ ```
52
+ 2. Check the PR's **build-validation policy** is enabled (pipeline registered and
53
+ the policy references the correct pipeline ID — see
54
+ `policies-and-pipelines.md`).
55
+ 3. Check the PR is open and targeting `integration`. Closed/draft PRs don't
56
+ trigger CI.
57
+
58
+ For bootstrap PRs introducing `azure-pipelines.yml` for the first time, use
59
+ `git push --force-with-lease` to force a new push event (see
60
+ `troubleshooting.md` → pipeline bootstrap gotchas).
@@ -0,0 +1,87 @@
1
+ # Azure DevOps CLI reference
2
+
3
+ Command catalog for the enact-os workflow. Assumes the **Variables** block from
4
+ `../SKILL.md` is set (`$ORG_URL`, `$PROJECT`, `$AZDO_RESOURCE`). For anything not
5
+ listed here, run `az <group> --help`.
6
+
7
+ ## Most-used commands
8
+
9
+ ```bash
10
+ # My PRs
11
+ az repos pr list --creator "$(az account show --query user.name -o tsv)"
12
+ az repos pr list --reviewer "$(az account show --query user.name -o tsv)"
13
+ az repos pr show --id <pr-id>
14
+ az repos pr checkout --id <pr-id>
15
+
16
+ # My work items
17
+ az boards query --wiql "SELECT [System.Id], [System.Title], [System.State] FROM WorkItems WHERE [System.AssignedTo] = @Me AND [System.State] <> 'Closed' ORDER BY [System.ChangedDate] DESC"
18
+ az boards work-item show --id <work-item-id>
19
+ az boards work-item create --title "Task title" --type "Task"
20
+ az boards work-item update --id <id> --state "In Progress"
21
+
22
+ # Pipelines
23
+ az pipelines list
24
+ az pipelines runs list --top 10
25
+ az pipelines runs show --id <run-id>
26
+
27
+ # Repositories
28
+ az repos list
29
+ az repos show --repository <repo-name>
30
+ az repos create --name "new-repo"
31
+ ```
32
+
33
+ ## Pull request workflow
34
+
35
+ ```bash
36
+ # Create PR to integration — always auto-complete + delete-source-branch
37
+ az repos pr create \
38
+ --source-branch feat/my-branch \
39
+ --target-branch integration \
40
+ --title "feat: description" \
41
+ --auto-complete true \
42
+ --delete-source-branch true \
43
+ --detect
44
+ # CI passes → PR auto-merges. No reviewer required on integration.
45
+
46
+ # Promotion PR to main (integration→main) — created/updated by automation,
47
+ # merge stays MANUAL. Owner approval on this PR is the release gate.
48
+ az repos pr create \
49
+ --source-branch integration \
50
+ --target-branch main \
51
+ --title "release: promote integration → main" \
52
+ --detect
53
+ # NO --auto-complete ← merge of the main PR is the manual release gate
54
+ # NO --delete-source-branch ← integration is permanent
55
+
56
+ # Enable auto-complete on an existing integration PR (e.g. opened without flags)
57
+ az repos pr update --id <pr-id> --auto-complete true --delete-source-branch true
58
+
59
+ # Reviewers / votes / manual completion
60
+ az repos pr update --id <pr-id> --reviewers user@email.com
61
+ az repos pr set-vote --id <pr-id> --vote 10 # 10 approve · 5 approve-w/-suggestions · -5 wait · -10 reject
62
+ az repos pr update --id <pr-id> --status completed
63
+ ```
64
+
65
+ ## Auto-complete gotcha (CLI/REST PRs)
66
+
67
+ The project setting **"Set PRs to auto-complete on creation by default"**
68
+ (Project settings → Repositories → Settings) is enabled, **but it applies only
69
+ to PRs created in the web UI** — PRs created via `az repos pr create` / REST do
70
+ NOT inherit it (verified: a CLI-created PR had auto-complete OFF despite the
71
+ default). So for the CLI workflow, always pass **both** `--auto-complete true`
72
+ and `--delete-source-branch true` explicitly. AzDO has no repo-level policy to
73
+ force-delete branches on merge — enforce it at PR creation. Fix a PR opened
74
+ without the flags after the fact:
75
+
76
+ ```bash
77
+ az repos pr update --id <N> --auto-complete true --delete-source-branch true
78
+ ```
79
+
80
+ ## Common flags
81
+
82
+ | Flag | Description |
83
+ | ------------------- | --------------------------------------------------- |
84
+ | `--org` | Organization URL (or set via `az devops configure`) |
85
+ | `--project` | Project name (or set via `az devops configure`) |
86
+ | `--detect` | Auto-detect org/project from the git remote |
87
+ | `-o json/table/tsv` | Output format |
@@ -0,0 +1,132 @@
1
+ # Branch policies, pipelines & variable groups (REST)
2
+
3
+ Assumes the **Variables** block from `../SKILL.md` is set (`$ORG_URL`,
4
+ `$PROJECT`, `$AZDO_RESOURCE`).
5
+
6
+ ## Enforcing merge strategy on a branch
7
+
8
+ > **Do NOT use `az repos policy merge-strategy create`** — it warns
9
+ > `This command is from the following extension: azure-devops`. Use the REST API
10
+ > directly (bearer token + curl). Policy type id:
11
+ > `fa4e907d-c16b-4a4c-9dfa-4916e5d171ab`.
12
+
13
+ **integration — squash only** (1 clean commit per PR, linear history):
14
+
15
+ ```bash
16
+ TOKEN=$(az account get-access-token \
17
+ --resource "$AZDO_RESOURCE" --query accessToken -o tsv)
18
+
19
+ curl -s -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
20
+ "$ORG_URL/$PROJECT/_apis/policy/configurations?api-version=7.1" \
21
+ -d '{
22
+ "isEnabled": true, "isBlocking": true,
23
+ "type": {"id": "fa4e907d-c16b-4a4c-9dfa-4916e5d171ab"},
24
+ "settings": {
25
+ "allowSquash": true, "allowNoFastForward": false,
26
+ "allowRebase": false, "allowRebaseMerge": false,
27
+ "scope": [{"repositoryId": "<repo-id>", "refName": "refs/heads/integration", "matchKind": "exact"}]
28
+ }
29
+ }'
30
+ ```
31
+
32
+ **main — basic merge or fast-forward, no squash** (preserves full integration
33
+ history on promotion):
34
+
35
+ ```bash
36
+ # POST (new) uses the URL above with these settings; if a policy already exists,
37
+ # PUT to .../policy/configurations/<policy-id>?api-version=7.1 instead.
38
+ curl -s -X PUT -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
39
+ "$ORG_URL/$PROJECT/_apis/policy/configurations/<policy-id>?api-version=7.1" \
40
+ -d '{
41
+ "isEnabled": true, "isBlocking": true,
42
+ "type": {"id": "fa4e907d-c16b-4a4c-9dfa-4916e5d171ab"},
43
+ "settings": {
44
+ "allowSquash": false, "allowNoFastForward": true,
45
+ "allowRebase": true, "allowRebaseMerge": false,
46
+ "scope": [{"repositoryId": "<repo-id>", "refName": "refs/heads/main", "matchKind": "exact"}]
47
+ }
48
+ }'
49
+ ```
50
+
51
+ POST fails with "rejected by policy" if a merge-strategy policy already exists on
52
+ that branch — use PUT with the existing policy ID. Find existing IDs:
53
+
54
+ ```bash
55
+ curl -s -H "Authorization: Bearer $TOKEN" \
56
+ "$ORG_URL/$PROJECT/_apis/policy/configurations?api-version=7.1" \
57
+ | python3 -c "
58
+ import sys,json
59
+ MERGE_TYPE='fa4e907d-c16b-4a4c-9dfa-4916e5d171ab'
60
+ for p in json.load(sys.stdin).get('value',[]):
61
+ if p.get('type',{}).get('id') == MERGE_TYPE:
62
+ for s in p['settings'].get('scope',[]):
63
+ print(p['id'], s.get('repositoryId'), s.get('refName'))
64
+ "
65
+ ```
66
+
67
+ ## Register a pipeline
68
+
69
+ ```bash
70
+ # Run from inside the repo directory — --detect infers org/project/repo
71
+ az pipelines create \
72
+ --name "<package-name> CI" \
73
+ --repository <repo-name> \
74
+ --repository-type tfsgit \
75
+ --branch <default-branch> \
76
+ --yml-path azure-pipelines.yml \
77
+ --skip-first-run \
78
+ --detect
79
+ ```
80
+
81
+ ## Build-validation policy (blocking CI gate)
82
+
83
+ ```bash
84
+ az repos policy build create \
85
+ --repository-id <repo-id> \
86
+ --branch integration \
87
+ --build-definition-id <pipeline-id> \
88
+ --queue-on-source-update-only false \
89
+ --manual-queue-only false \
90
+ --valid-duration 0 \
91
+ --blocking true \
92
+ --enabled true \
93
+ --display-name "CI must pass before merge" \
94
+ --detect
95
+
96
+ # List / delete policies for a repo
97
+ az repos policy list --repository-id <repo-id> --detect -o table
98
+ az repos policy delete --id <policy-id> --detect
99
+ ```
100
+
101
+ Get `--repository-id` via `az repos show --repository <repo-name> --query id -o tsv --detect`.
102
+ Policies for the enact-os packages were created 2026-05-19 with the above.
103
+
104
+ ## Variable-group authorization (first run)
105
+
106
+ A pipeline referencing a variable group (e.g. `enact-dev-secrets`) for the first
107
+ time queues but stays `notStarted` until authorized. Two ways:
108
+
109
+ ```bash
110
+ # UI: open the stuck run and click "Permit" on the variable group.
111
+ az pipelines runs list --pipeline-id <id> --output table
112
+ # $ORG_URL/$PROJECT/_build/results?buildId=<run-id>
113
+ ```
114
+
115
+ ```bash
116
+ # REST (no UI):
117
+ TOKEN=$(az account get-access-token \
118
+ --resource "$AZDO_RESOURCE" --query accessToken -o tsv)
119
+ az pipelines variable-group list --output table # get <groupId>
120
+
121
+ # Authorize specific pipelines:
122
+ curl -s -X PATCH -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
123
+ "$ORG_URL/$PROJECT/_apis/pipelines/pipelinePermissions/variablegroup/<groupId>?api-version=7.1-preview.1" \
124
+ -d '{"pipelines": [{"id": 9, "authorized": true}, {"id": 10, "authorized": true}]}'
125
+
126
+ # …or all pipelines at once:
127
+ curl -s -X PATCH -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
128
+ "$ORG_URL/$PROJECT/_apis/pipelines/pipelinePermissions/variablegroup/<groupId>?api-version=7.1-preview.1" \
129
+ -d '{"allPipelines": {"authorized": true}}'
130
+ ```
131
+
132
+ The authorization persists for that pipeline permanently.