@orchestraworks/cli 0.5.2 → 0.5.4
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 +1 -1
- package/dist/cli/api/compute-provider-check.d.ts +29 -0
- package/dist/cli/api/compute-provider-check.js +207 -0
- package/dist/cli/api/tail.d.ts +66 -0
- package/dist/cli/api/tail.js +564 -0
- package/dist/cli/main.d.ts +5 -1
- package/dist/cli/main.js +22 -0
- package/dist/constructs/agent.d.ts +10 -0
- package/dist/constructs/agent.js +39 -4
- package/dist/constructs/environment.d.ts +29 -1
- package/dist/constructs/environment.js +28 -1
- package/dist/constructs/skill.d.ts +6 -1
- package/dist/constructs/skill.js +21 -2
- package/dist/engine/reconcile.js +15 -1
- package/dist/generated/cli-commands.json +1646 -198
- package/dist/generated/cli-dispatch.js +9 -0
- package/dist/generated/managed-skills.d.ts +2 -0
- package/dist/generated/managed-skills.js +18 -0
- package/dist/index.d.ts +1 -1
- package/docs/REFERENCE.md +21 -1
- package/node_modules/@orchestraworks/client/dist/apis/OrganizationInvitationsApi.d.ts +29 -0
- package/node_modules/@orchestraworks/client/dist/apis/OrganizationInvitationsApi.js +96 -0
- package/node_modules/@orchestraworks/client/dist/esm/apis/OrganizationInvitationsApi.d.ts +29 -0
- package/node_modules/@orchestraworks/client/dist/esm/apis/OrganizationInvitationsApi.js +96 -0
- package/node_modules/@orchestraworks/client/dist/esm/models/ComputeProvider.d.ts +3 -3
- package/node_modules/@orchestraworks/client/dist/esm/models/CreateEnvironmentRequest.d.ts +13 -0
- package/node_modules/@orchestraworks/client/dist/esm/models/CreateEnvironmentRequest.js +5 -0
- package/node_modules/@orchestraworks/client/dist/esm/models/CreateOrganizationInvitationRequest.d.ts +2 -2
- package/node_modules/@orchestraworks/client/dist/esm/models/Environment.d.ts +13 -0
- package/node_modules/@orchestraworks/client/dist/esm/models/Environment.js +5 -0
- package/node_modules/@orchestraworks/client/dist/esm/models/EnvironmentHook.d.ts +38 -0
- package/node_modules/@orchestraworks/client/dist/esm/models/EnvironmentHook.js +45 -0
- package/node_modules/@orchestraworks/client/dist/esm/models/EnvironmentHooks.d.ts +39 -0
- package/node_modules/@orchestraworks/client/dist/esm/models/EnvironmentHooks.js +44 -0
- package/node_modules/@orchestraworks/client/dist/esm/models/EnvironmentHooksRequest.d.ts +39 -0
- package/node_modules/@orchestraworks/client/dist/esm/models/EnvironmentHooksRequest.js +44 -0
- package/node_modules/@orchestraworks/client/dist/esm/models/EnvironmentProvisionSpec.d.ts +2 -1
- package/node_modules/@orchestraworks/client/dist/esm/models/EnvironmentProvisionSpecRequest.d.ts +2 -1
- package/node_modules/@orchestraworks/client/dist/esm/models/EnvironmentSnapshot.d.ts +19 -0
- package/node_modules/@orchestraworks/client/dist/esm/models/EnvironmentSnapshot.js +7 -0
- package/node_modules/@orchestraworks/client/dist/esm/models/Machine.d.ts +7 -1
- package/node_modules/@orchestraworks/client/dist/esm/models/Machine.js +2 -0
- package/node_modules/@orchestraworks/client/dist/esm/models/OrganizationAuthPolicy.d.ts +1 -1
- package/node_modules/@orchestraworks/client/dist/esm/models/OrganizationInvitation.d.ts +14 -1
- package/node_modules/@orchestraworks/client/dist/esm/models/OrganizationInvitation.js +8 -1
- package/node_modules/@orchestraworks/client/dist/esm/models/Principal.d.ts +6 -0
- package/node_modules/@orchestraworks/client/dist/esm/models/Principal.js +2 -0
- package/node_modules/@orchestraworks/client/dist/esm/models/UpdateEnvironmentRequest.d.ts +13 -0
- package/node_modules/@orchestraworks/client/dist/esm/models/UpdateEnvironmentRequest.js +5 -0
- package/node_modules/@orchestraworks/client/dist/esm/models/UpdateOrganizationInvitationRequest.d.ts +2 -1
- package/node_modules/@orchestraworks/client/dist/esm/models/UpdateOrganizationInvitationRequest.js +2 -1
- package/node_modules/@orchestraworks/client/dist/esm/models/User.d.ts +6 -0
- package/node_modules/@orchestraworks/client/dist/esm/models/User.js +4 -0
- package/node_modules/@orchestraworks/client/dist/esm/models/index.d.ts +3 -0
- package/node_modules/@orchestraworks/client/dist/esm/models/index.js +3 -0
- package/node_modules/@orchestraworks/client/dist/models/ComputeProvider.d.ts +3 -3
- package/node_modules/@orchestraworks/client/dist/models/CreateEnvironmentRequest.d.ts +13 -0
- package/node_modules/@orchestraworks/client/dist/models/CreateEnvironmentRequest.js +5 -0
- package/node_modules/@orchestraworks/client/dist/models/CreateOrganizationInvitationRequest.d.ts +2 -2
- package/node_modules/@orchestraworks/client/dist/models/Environment.d.ts +13 -0
- package/node_modules/@orchestraworks/client/dist/models/Environment.js +5 -0
- package/node_modules/@orchestraworks/client/dist/models/EnvironmentHook.d.ts +38 -0
- package/node_modules/@orchestraworks/client/dist/models/EnvironmentHook.js +52 -0
- package/node_modules/@orchestraworks/client/dist/models/EnvironmentHooks.d.ts +39 -0
- package/node_modules/@orchestraworks/client/dist/models/EnvironmentHooks.js +51 -0
- package/node_modules/@orchestraworks/client/dist/models/EnvironmentHooksRequest.d.ts +39 -0
- package/node_modules/@orchestraworks/client/dist/models/EnvironmentHooksRequest.js +51 -0
- package/node_modules/@orchestraworks/client/dist/models/EnvironmentProvisionSpec.d.ts +2 -1
- package/node_modules/@orchestraworks/client/dist/models/EnvironmentProvisionSpecRequest.d.ts +2 -1
- package/node_modules/@orchestraworks/client/dist/models/EnvironmentSnapshot.d.ts +19 -0
- package/node_modules/@orchestraworks/client/dist/models/EnvironmentSnapshot.js +7 -0
- package/node_modules/@orchestraworks/client/dist/models/Machine.d.ts +7 -1
- package/node_modules/@orchestraworks/client/dist/models/Machine.js +2 -0
- package/node_modules/@orchestraworks/client/dist/models/OrganizationAuthPolicy.d.ts +1 -1
- package/node_modules/@orchestraworks/client/dist/models/OrganizationInvitation.d.ts +14 -1
- package/node_modules/@orchestraworks/client/dist/models/OrganizationInvitation.js +8 -1
- package/node_modules/@orchestraworks/client/dist/models/Principal.d.ts +6 -0
- package/node_modules/@orchestraworks/client/dist/models/Principal.js +2 -0
- package/node_modules/@orchestraworks/client/dist/models/UpdateEnvironmentRequest.d.ts +13 -0
- package/node_modules/@orchestraworks/client/dist/models/UpdateEnvironmentRequest.js +5 -0
- package/node_modules/@orchestraworks/client/dist/models/UpdateOrganizationInvitationRequest.d.ts +2 -1
- package/node_modules/@orchestraworks/client/dist/models/UpdateOrganizationInvitationRequest.js +2 -1
- package/node_modules/@orchestraworks/client/dist/models/User.d.ts +6 -0
- package/node_modules/@orchestraworks/client/dist/models/User.js +4 -0
- package/node_modules/@orchestraworks/client/dist/models/index.d.ts +3 -0
- package/node_modules/@orchestraworks/client/dist/models/index.js +3 -0
- package/node_modules/@orchestraworks/client/package.json +1 -1
- package/package.json +4 -4
- package/skills/orchestra/SKILL.md +167 -42
- package/skills/orchestra-fdk/SKILL.md +112 -545
- package/skills/orchestra-fdk/references/authoring.md +29 -2
- package/skills/orchestra-fdk/references/environment.md +295 -41
- package/skills/orchestra-fdk/references/integrations/analytics.md +18 -0
- package/skills/orchestra-fdk/references/integrations/ci-cd.md +20 -0
- package/skills/orchestra-fdk/references/integrations/cloud.md +19 -0
- package/skills/orchestra-fdk/references/integrations/code-repo.md +76 -0
- package/skills/orchestra-fdk/references/integrations/databases.md +22 -0
- package/skills/orchestra-fdk/references/integrations/dependencies.md +29 -0
- package/skills/orchestra-fdk/references/integrations/design.md +18 -0
- package/skills/orchestra-fdk/references/integrations/feature-flags.md +19 -0
- package/skills/orchestra-fdk/references/integrations/incident.md +29 -0
- package/skills/orchestra-fdk/references/integrations/issue-tracker.md +65 -0
- package/skills/orchestra-fdk/references/integrations/knowledge-base.md +43 -0
- package/skills/orchestra-fdk/references/integrations/messaging.md +38 -0
- package/skills/orchestra-fdk/references/integrations/observability.md +36 -0
- package/skills/orchestra-fdk/references/integrations/secrets-managers.md +25 -0
- package/skills/orchestra-fdk/references/integrations/support-desk.md +31 -0
- package/skills/orchestra-fdk/references/phases/0-start.md +62 -0
- package/skills/orchestra-fdk/references/phases/1-discover.md +111 -0
- package/skills/orchestra-fdk/references/phases/2-plan.md +157 -0
- package/skills/orchestra-fdk/references/phases/3-connect.md +99 -0
- package/skills/orchestra-fdk/references/phases/4-build.md +159 -0
- package/skills/orchestra-fdk/references/phases/5-prove.md +107 -0
- package/skills/orchestra-fdk/references/phases/6-handover.md +42 -0
- package/skills/orchestra-fdk/references/troubleshooting.md +128 -0
- package/templates/bug-fix/agents/bugfix.md +1 -1
- package/templates/bug-fix/main.ts +1 -1
- package/templates/engineering-team/README.md +45 -181
- package/templates/engineering-team/agents/engineer-agent.md +10 -7
- package/templates/engineering-team/agents/manager-agent.md +23 -120
- package/templates/engineering-team/inputs.json +1 -3
- package/templates/engineering-team/lib/environment.ts +10 -90
- package/templates/engineering-team/lib/inputs.ts +5 -97
- package/templates/engineering-team/main.ts +22 -69
- package/templates/todo-factory/agents/bugfix.md +1 -1
- package/templates/todo-factory/main.ts +1 -1
- package/templates/engineering-team/agents/engineer-bare.md +0 -22
- package/templates/engineering-team/onboarding/create-score-metrics.sh +0 -33
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Package registries
|
|
2
|
+
|
|
3
|
+
Public registries need no access: egress is open. A private registry or feed needs a Secret the network edge
|
|
4
|
+
adds on the registry's host. Point the package manager at the registry's address with no user name and no
|
|
5
|
+
token in it: in `.npmrc`, `nuget.config`, `pip.conf` or an env value. The edge adds the credential. The agent
|
|
6
|
+
installs or uses whatever client it prefers.
|
|
7
|
+
|
|
8
|
+
Phase 3, "From a recipe to code", turns a recipe into a Secret and a rule.
|
|
9
|
+
|
|
10
|
+
| Provider | Access | Scopes | Check command |
|
|
11
|
+
|---|---|---|---|
|
|
12
|
+
| npm, private registry (GitHub Packages, JFrog, Nexus) | `<registry host> → Authorization: Bearer <SECRET>` | Read packages | `curl -fsS https://<registry host>/<package name>` |
|
|
13
|
+
| PyPI, private index (JFrog, Nexus) | `<index host> → Authorization: Basic <user>:<SECRET>`. Ask which user name the index wants | Read packages | `curl -fsS https://<index host>/simple/<package name>/` |
|
|
14
|
+
| NuGet, Azure Artifacts | `pkgs.dev.azure.com → Authorization: Basic pat:<SECRET>` | Packaging (Read) | `curl -fsS "https://pkgs.dev.azure.com/<organization>/_packaging/<feed>/nuget/v3/index.json"` |
|
|
15
|
+
| NuGet, GitHub Packages | `nuget.pkg.github.com → Authorization: Basic <user>:<SECRET>` | `read:packages` | `curl -fsS https://nuget.pkg.github.com/<owner>/index.json` |
|
|
16
|
+
| Maven or Gradle, private repository | `<repository host> → Authorization: Basic <user>:<SECRET>` (check the vendor page) | Read packages | `curl -fsS https://<repository host>/<path to a known artifact>.pom` |
|
|
17
|
+
|
|
18
|
+
The public registries, such as `registry.npmjs.org`, `pypi.org`, `files.pythonhosted.org` and
|
|
19
|
+
`api.nuget.org`, need no rule.
|
|
20
|
+
|
|
21
|
+
## Never write the token on the machine
|
|
22
|
+
|
|
23
|
+
Never write the token into `.npmrc`, `pip.conf`, `nuget.config`, an env value or the setup script. Every
|
|
24
|
+
process on the machine reads them, and the setup script's output is kept. Keep the codebase's own file when it
|
|
25
|
+
holds the address only, for example:
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
@<scope>:registry=https://<registry host>/
|
|
29
|
+
```
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Design
|
|
2
|
+
|
|
3
|
+
The agents read design files to build what the designer drew. Give access with a Secret the network edge adds,
|
|
4
|
+
with read scopes only. Egress is open, so add only the rule that adds the credential. The platform has no
|
|
5
|
+
design connection, so no design events reach the platform. The agent installs or uses whatever client it
|
|
6
|
+
prefers. The edge adds the credential to its requests.
|
|
7
|
+
|
|
8
|
+
Phase 3, "From a recipe to code", turns a recipe into a Secret and a rule.
|
|
9
|
+
|
|
10
|
+
| Provider | Access | Scopes | Check command |
|
|
11
|
+
|---|---|---|---|
|
|
12
|
+
| Figma | `api.figma.com → X-Figma-Token: <SECRET>` | A personal access token with `file_content:read` | `curl -fsS "https://api.figma.com/v1/files/<file key>?depth=1"` |
|
|
13
|
+
|
|
14
|
+
Token page: Figma **Settings › Security › Personal access tokens**.
|
|
15
|
+
|
|
16
|
+
The file key is the part after `/design/` or `/file/` in the file's address.
|
|
17
|
+
|
|
18
|
+
The token sees every file its user can open. Make it for a user who sees only the team's files.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Feature flags
|
|
2
|
+
|
|
3
|
+
The agents read flag settings to see what each user gets, and turn a flag on only in a test environment.
|
|
4
|
+
Give access with a Secret the network edge adds, with read scopes, or write only on non-production
|
|
5
|
+
environments. Egress is open, so add only the rule that adds the credential. The agent installs or uses
|
|
6
|
+
whatever client it prefers. The edge adds the credential to its requests.
|
|
7
|
+
|
|
8
|
+
Phase 3, "From a recipe to code", turns a recipe into a Secret and a rule.
|
|
9
|
+
|
|
10
|
+
| Provider | Access | Scopes | Check command |
|
|
11
|
+
|---|---|---|---|
|
|
12
|
+
| LaunchDarkly | `app.launchdarkly.com → Authorization: <SECRET>`, with no `Bearer` | An API access token with the Reader role | `curl -fsS https://app.launchdarkly.com/api/v2/projects` |
|
|
13
|
+
| Split | `api.split.io → Authorization: Bearer <SECRET>` | An Admin API key scoped to the test environments (check the vendor page) | `curl -fsS https://api.split.io/internal/api/v2/workspaces` |
|
|
14
|
+
| Unleash | `<unleash host> → Authorization: <SECRET>`, with no `Bearer` | A personal or service account token with read access | `curl -fsS https://<unleash host>/api/admin/projects` |
|
|
15
|
+
| ConfigCat | `api.configcat.com → Authorization: Basic <user>:<SECRET>` | Public API credentials | `curl -fsS https://api.configcat.com/v1/me` |
|
|
16
|
+
| Azure App Configuration | Not released yet: each request is signed with the key, or takes a short-lived Entra token | The App Configuration Data Reader role, when it is released | Not released yet |
|
|
17
|
+
|
|
18
|
+
Token pages: LaunchDarkly **Organization settings › Authorization**; Split **Admin settings › API keys**;
|
|
19
|
+
Unleash **Admin › API access**; ConfigCat **Public API credentials**.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Incidents
|
|
2
|
+
|
|
3
|
+
The agents read incidents and their timelines to find what broke. Give access with a Secret the network edge
|
|
4
|
+
adds, with read scopes only. Egress is open, so add only the rule that adds the credential. The platform has
|
|
5
|
+
no incident connection, so no incident events reach the platform. The agent installs or uses whatever client
|
|
6
|
+
it prefers. The edge adds the credential to its requests.
|
|
7
|
+
|
|
8
|
+
Phase 3, "From a recipe to code", turns a recipe into a Secret and a rule.
|
|
9
|
+
|
|
10
|
+
| Provider | Access | Scopes | Check command |
|
|
11
|
+
|---|---|---|---|
|
|
12
|
+
| PagerDuty | `api.pagerduty.com → Authorization: Token token=<SECRET>` | A read-only REST API key | `curl -fsS https://api.pagerduty.com/abilities -H 'Accept: application/vnd.pagerduty+json;version=2'` |
|
|
13
|
+
| Opsgenie | `api.opsgenie.com → Authorization: GenieKey <SECRET>`. The EU region is `api.eu.opsgenie.com` | An API key with Read access | `curl -fsS https://api.opsgenie.com/v2/account` |
|
|
14
|
+
|
|
15
|
+
Token pages: PagerDuty **Integrations › API Access Keys**; Opsgenie **Settings › API key management**.
|
|
16
|
+
|
|
17
|
+
## A header with its own word
|
|
18
|
+
|
|
19
|
+
Both put a word of their own before the key, so neither is `Bearer` nor `Basic`. Bind them with `inject`:
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
.allow("pagerduty", {
|
|
23
|
+
hosts: ["api.pagerduty.com"],
|
|
24
|
+
priority: 300,
|
|
25
|
+
credential: inject(pagerduty, { headers: [{ name: "authorization", value: "Token token=${secret}" }] }),
|
|
26
|
+
})
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
For Opsgenie, the value is `GenieKey ${secret}`.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Trackers
|
|
2
|
+
|
|
3
|
+
Give access with a Secret the network edge adds, or with the tracker's platform connection. Egress is open,
|
|
4
|
+
so add only the rule that adds the credential. A connection also brings events: a `Trigger` on them makes a
|
|
5
|
+
work item for each new issue. The agent installs or uses whatever client it prefers. The edge adds the
|
|
6
|
+
credential to its requests.
|
|
7
|
+
|
|
8
|
+
Phase 3, "From a recipe to code", turns a recipe into a Secret and a rule.
|
|
9
|
+
|
|
10
|
+
| Provider | Access | Scopes | Check command |
|
|
11
|
+
|---|---|---|---|
|
|
12
|
+
| Jira Cloud, API token | `<site>.atlassian.net → Authorization: Basic <email>:<SECRET>` | API token without scopes | `curl -fsS https://<site>.atlassian.net/rest/api/3/myself` |
|
|
13
|
+
| Jira Cloud, `jira` | Platform connection `jira` (the Orchestra app for Jira), with `.applyPreset(jira.egressPolicy())` | Set by the app | `curl -fsS https://api.atlassian.com/ex/jira/<cloudId>/rest/api/3/myself` |
|
|
14
|
+
| Jira Cloud, `jira-classic` | Platform connection `jira-classic`, with `.allow(jiraClassic)` on `api.atlassian.com` | Set by the consent | `curl -fsS https://api.atlassian.com/ex/jira/<cloudId>/rest/api/3/myself` |
|
|
15
|
+
| Linear | `api.linear.app → Authorization: <SECRET>`, with no `Bearer`. Or platform connection `linear` | Personal API key | `curl -fsS https://api.linear.app/graphql -H 'Content-Type: application/json' -d '{"query":"{ viewer { id } }"}'` |
|
|
16
|
+
| GitHub Issues | The GitHub access of `code-repo.md`, with Issues read and write | Issues: read and write | `curl -fsS "https://api.github.com/repos/<owner>/<name>/issues?per_page=1"` |
|
|
17
|
+
| Azure Boards | The Azure DevOps access of `code-repo.md` | Work Items (Read & write) | `curl -fsS "https://dev.azure.com/<organization>/<project>/_apis/wit/workitems?ids=<id>&api-version=7.1"` |
|
|
18
|
+
|
|
19
|
+
Token pages: Jira `https://id.atlassian.com/manage-profile/security/api-tokens`; Linear **Settings › Account ›
|
|
20
|
+
Security & access**.
|
|
21
|
+
|
|
22
|
+
## Jira: three routes
|
|
23
|
+
|
|
24
|
+
- **API token.** Basic auth over the account email and the token: `SecretValue.basicAuth("<email>",
|
|
25
|
+
SecretValue.fromEnv("<VAR>"))`. Make the token without scopes: a token with scopes
|
|
26
|
+
works only through `api.atlassian.com`, and this rule adds it on the site host. The site host, such as
|
|
27
|
+
`acme.atlassian.net`, is an env value or a constant in the code. No events.
|
|
28
|
+
- **`jira`, the Orchestra app for Jira.** `Auth.forgeApp()`, install field `siteUrl`. A Jira admin installs
|
|
29
|
+
the app from the connection's `auth.authorizationUrl` (`npx orchestra connections get jira --output json`).
|
|
30
|
+
The connection turns `ACTIVE` at the first event from the site. The app's key works only on
|
|
31
|
+
`api.atlassian.com`. Grant it with `.applyPreset(jira.egressPolicy())`: the preset adds the key on
|
|
32
|
+
`api.atlassian.com` only, and opens the site host with no key. A plain `.allow(jira)` would add the key on
|
|
33
|
+
both. Events: `CreatedIssue`, `UpdatedIssue`, `DeletedIssue`, `CommentedIssue`. The field `selfGenerated`
|
|
34
|
+
is true on a change the app made: filter it out with `where`.
|
|
35
|
+
- **`jira-classic`.** Install field `projectKey`. `Auth.oauth()`: the apply prints no link for it. Read
|
|
36
|
+
`auth.authorizationUrl` from `npx orchestra connections get <slug> --output json`, the developer consents,
|
|
37
|
+
and you apply again. The platform registers the webhook. Grant the key with
|
|
38
|
+
`.allow(jiraClassic)`, which adds it on `api.atlassian.com`. Events: `IssueCreated`, `IssueUpdated`,
|
|
39
|
+
`IssueDeleted`, `CommentCreated`.
|
|
40
|
+
|
|
41
|
+
A connection keeps its credential apart from the network rules. Without the grant on an environment, the
|
|
42
|
+
agents on it reach Jira with no key.
|
|
43
|
+
|
|
44
|
+
## GitHub Issues: one item per issue
|
|
45
|
+
|
|
46
|
+
A trigger that makes one work item per issue keys it with a `binding`. Issue numbers repeat across
|
|
47
|
+
repositories, so key on GitHub's global issue id, or put the repository in the key:
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
binding: binding`${context.connection.slug}:${context.event.payload("repository.full_name")}:${context.event.payload("issue.number")}`
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
A comment on a pull request also arrives as `IssueComment`: filter it out with
|
|
54
|
+
`field("issue.pull_request").isAbsent()`.
|
|
55
|
+
|
|
56
|
+
## Linear
|
|
57
|
+
|
|
58
|
+
The key goes bare in the `Authorization` header: `header("Authorization", secret)`. With the `linear`
|
|
59
|
+
connection, `Auth.customerManagedToken(<secret>)` or `Auth.oauth()`, and `.allow(linear)` adds its key. The
|
|
60
|
+
platform registers the webhook. Events: `IssueCreate`, `IssueUpdate`, `IssueRemove`, `CommentCreate`.
|
|
61
|
+
|
|
62
|
+
## Azure Boards
|
|
63
|
+
|
|
64
|
+
A work item comment arrives as `WorkitemUpdated`, with its text at
|
|
65
|
+
`resource.fields["System.History"].newValue`. There is no separate comment event.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Knowledge bases
|
|
2
|
+
|
|
3
|
+
Give access with a Secret the network edge adds, or with the provider's platform connection. Egress is open,
|
|
4
|
+
so add only the rule that adds the credential. The agent installs or uses whatever client it prefers. The
|
|
5
|
+
edge adds the credential to its requests.
|
|
6
|
+
|
|
7
|
+
Phase 3, "From a recipe to code", turns a recipe into a Secret and a rule.
|
|
8
|
+
|
|
9
|
+
| Provider | Access | Scopes | Check command |
|
|
10
|
+
|---|---|---|---|
|
|
11
|
+
| Notion | `api.notion.com → Authorization: Bearer <SECRET>`. Or platform connection `notion`, with `.allow(notion)` | An internal integration, shared with each page or database the agents need | `curl -fsS https://api.notion.com/v1/users/me -H 'Notion-Version: 2022-06-28'` |
|
|
12
|
+
| Confluence Cloud | `<site>.atlassian.net → Authorization: Basic <email>:<SECRET>` | API token without scopes | `curl -fsS "https://<site>.atlassian.net/wiki/api/v2/spaces?limit=1"` |
|
|
13
|
+
| Guru | `api.getguru.com → Authorization: Basic <email>:<SECRET>`. Or platform connection `guru` (OAuth, read only), with `.allow(guru)` | User API token | `curl -fsS https://api.getguru.com/api/v1/whoami` (check the vendor page) |
|
|
14
|
+
|
|
15
|
+
Token pages: Notion `https://www.notion.so/profile/integrations`; Confluence
|
|
16
|
+
`https://id.atlassian.com/manage-profile/security/api-tokens`; Guru, the user's API tokens in Guru's
|
|
17
|
+
settings.
|
|
18
|
+
|
|
19
|
+
## Notion
|
|
20
|
+
|
|
21
|
+
The integration sees only the pages and databases the developer shares with it in Notion. Each Notion API
|
|
22
|
+
call also needs a `Notion-Version` header, which the agent's client sends itself.
|
|
23
|
+
|
|
24
|
+
The `notion` connection takes `Auth.customerManagedToken(<secret>)` or `Auth.oauth()`, install fields
|
|
25
|
+
`workspaceId` and `workspaceUrl`, both optional. Its events are `PageCreated` and `PageContentUpdated`.
|
|
26
|
+
The platform does not register the webhook. The developer adds it by hand in the integration's settings in
|
|
27
|
+
Notion, with the connection's address. Write the address to a file the developer can read, and never print
|
|
28
|
+
it: `npx orchestra connections rotate-webhook-token notion --output-file <path>`. Each run makes a new
|
|
29
|
+
address and ends the old one.
|
|
30
|
+
|
|
31
|
+
## Confluence
|
|
32
|
+
|
|
33
|
+
Basic auth over the account email and the token, on the site host. Make the token without scopes, for the
|
|
34
|
+
same reason as Jira's (`issue-tracker.md`). When the team uses a Jira API token on the same site with the
|
|
35
|
+
same account, reuse that Secret and its rule: one rule on the site host serves both. The platform has no
|
|
36
|
+
Confluence connection, so Confluence sends no events.
|
|
37
|
+
|
|
38
|
+
## Guru
|
|
39
|
+
|
|
40
|
+
The `guru` connection asks Guru for read access with `Auth.oauth()`. The apply prints no link for it: read
|
|
41
|
+
`auth.authorizationUrl` from `npx orchestra connections get <slug> --output json`, the developer consents, and
|
|
42
|
+
you apply again. The platform registers the webhook. Events: `CardCreated`,
|
|
43
|
+
`CardUpdated`, `CardDeleted`.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Chat
|
|
2
|
+
|
|
3
|
+
Slack and Microsoft Teams take no personal token here. Access is the platform connection only: the developer
|
|
4
|
+
or a tenant admin approves the app in the browser, and the network edge adds the app's key to the agent's
|
|
5
|
+
replies. Egress is open, so the connection's own rule, `.allow(<connection>)`, is the only rule to add. The
|
|
6
|
+
agent installs or uses whatever client it prefers. The edge adds the key to its requests.
|
|
7
|
+
|
|
8
|
+
| Provider | Access | Scopes | Check command |
|
|
9
|
+
|---|---|---|---|
|
|
10
|
+
| Slack | Platform connection `slack` (the Orchestra Slack app), `Auth.oauth()`, with `.allow(slack)` on `slack.com` | Set by the app | `curl -sS -X POST https://slack.com/api/auth.test`. Passes only when the answer holds `"ok":true`: Slack answers `200` with `"ok":false` when no key was added |
|
|
11
|
+
| Microsoft Teams | Platform connection `teams` (the Orchestra bot), `Auth.oauth()`, with `.allow(teams)` | Set by the app; a tenant admin consents | The agent sends one message with its own choice of tool, on a conversation where the bot has seen a message. Passes only when the answer carries the new message's `id` and the message shows in Teams |
|
|
12
|
+
|
|
13
|
+
## OAuth only
|
|
14
|
+
|
|
15
|
+
Both apps sign in with OAuth, and the platform fills the install fields, so `install` stays empty. The apply
|
|
16
|
+
prints `connection '<slug>' needs attention — authorize at: <link>`. For Slack, the developer opens it and
|
|
17
|
+
adds the app to the workspace. For Teams, the consent is for the whole Microsoft tenant, so a tenant admin
|
|
18
|
+
must open it. Then run the same apply again.
|
|
19
|
+
|
|
20
|
+
Without `.allow(<connection>)` on the agent's environment, a reply is refused at the network edge, and synth
|
|
21
|
+
prints a warning.
|
|
22
|
+
|
|
23
|
+
## Conversations
|
|
24
|
+
|
|
25
|
+
`Providers.Slack.conversation` and `Providers.Teams.conversation` give the events and the bindings for a
|
|
26
|
+
trigger that starts or wakes an agent's conversation: Slack's `mention`, `dm`, `groupChat` and `threadReply`;
|
|
27
|
+
Teams' `message`, split by `inChannel()`, `inDirectMessage()` and `inGroupChat()`. Both have
|
|
28
|
+
`sessionPerThread()`, `sessionPerConversation()` and `rooms([...])`. Set `attributeConnection: true` on the
|
|
29
|
+
trigger's agent target. `autoRespond` on the connection sets what the app shows on each message: Slack takes
|
|
30
|
+
a reaction, a typing status and a failure notice; Teams takes `typing` and `failureNotice`.
|
|
31
|
+
|
|
32
|
+
The agent replies through the provider's own API: Slack's Web API on `slack.com`, and the Bot Framework for
|
|
33
|
+
Teams. On Teams, the edge adds the bot's key only for a conversation where the bot has already seen a
|
|
34
|
+
message.
|
|
35
|
+
|
|
36
|
+
**Not built yet:** acting as the person who wrote the message (the agent speaks as the app), starting a Teams
|
|
37
|
+
conversation where the bot has not been seen, and dropping the app's own messages before the agent sees
|
|
38
|
+
them.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Observability
|
|
2
|
+
|
|
3
|
+
The agents read errors, traces and metrics to find the cause of a bug. Give access with a Secret the network
|
|
4
|
+
edge adds, with read scopes only. Egress is open, so add only the rule that adds the credential. None of these
|
|
5
|
+
has a platform connection, so none sends events to the platform. The agent installs or uses whatever client
|
|
6
|
+
it prefers. The edge adds the credential to its requests.
|
|
7
|
+
|
|
8
|
+
Phase 3, "From a recipe to code", turns a recipe into a Secret and a rule.
|
|
9
|
+
|
|
10
|
+
| Provider | Access | Scopes | Check command |
|
|
11
|
+
|---|---|---|---|
|
|
12
|
+
| Sentry | `sentry.io → Authorization: Bearer <SECRET>`. The EU region is `de.sentry.io`; a self-hosted Sentry uses its own host | `project:read`, `event:read` | `curl -fsS https://sentry.io/api/0/organizations/` |
|
|
13
|
+
| Datadog | `api.datadoghq.com → DD-API-KEY: <SECRET>` and `DD-APPLICATION-KEY: <SECRET>`, two Secrets on one rule. Other sites use their own host, such as `api.datadoghq.eu` | An application key with read scopes | `curl -fsS https://api.datadoghq.com/api/v1/validate` |
|
|
14
|
+
| New Relic | `api.newrelic.com → API-Key: <SECRET>`. The EU region is `api.eu.newrelic.com` | A user key | `curl -fsS https://api.newrelic.com/graphql -H 'Content-Type: application/json' -d '{"query":"{ actor { user { email } } }"}'` |
|
|
15
|
+
| Grafana Cloud | `<stack>.grafana.net → Authorization: Bearer <SECRET>` | A service account token with the Viewer role | `curl -fsS "https://<stack>.grafana.net/api/search?limit=1"` |
|
|
16
|
+
| Application Insights | `api.applicationinsights.io → x-api-key: <SECRET>` (check the vendor page: Microsoft is moving this API to Entra sign-in) | Read telemetry | `curl -fsS "https://api.applicationinsights.io/v1/apps/<app id>/metadata"` |
|
|
17
|
+
| CloudWatch | Not released yet. AWS signs each request with its key, so the edge cannot add it as a header | Not released yet | Not released yet |
|
|
18
|
+
|
|
19
|
+
Token pages: Sentry **Settings › Auth Tokens**; Datadog **Organization Settings › API Keys** and
|
|
20
|
+
**Application Keys**; New Relic **API keys**; Grafana **Administration › Service accounts**.
|
|
21
|
+
|
|
22
|
+
## Datadog: two headers
|
|
23
|
+
|
|
24
|
+
Datadog wants two keys on each API call: the organization's API key and a user's application key. Store each
|
|
25
|
+
as its own Secret, and add both on one rule:
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
.allow("datadog", {
|
|
29
|
+
hosts: ["api.datadoghq.com"],
|
|
30
|
+
priority: 300,
|
|
31
|
+
credentials: [header("DD-API-KEY", datadogApiKey), header("DD-APPLICATION-KEY", datadogAppKey)],
|
|
32
|
+
})
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
The application key carries the user's rights. Make it for a user, or a service account, with read access
|
|
36
|
+
only.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Secrets managers
|
|
2
|
+
|
|
3
|
+
A secrets manager is a source for the factory's Secrets, not a service the agents call. The developer reads
|
|
4
|
+
each token from the manager into the shell of the apply, on their own computer. The apply stores it as an
|
|
5
|
+
Orchestra Secret, and the network edge adds it. The value is never printed, never in the chat, and never on
|
|
6
|
+
a machine.
|
|
7
|
+
|
|
8
|
+
| Provider | Access | Scopes | Check command |
|
|
9
|
+
|---|---|---|---|
|
|
10
|
+
| 1Password | On the developer's computer: `ORCHESTRA_FDK_<NAME>_TOKEN=$(op read "op://<vault>/<item>/<field>")` in the apply's shell | Read on the vault | `op whoami` |
|
|
11
|
+
| HashiCorp Vault | On the developer's computer: `ORCHESTRA_FDK_<NAME>_TOKEN=$(vault kv get -field=<field> <path>)` in the apply's shell | A policy with `read` on the path | `vault token lookup` |
|
|
12
|
+
| Azure Key Vault | On the developer's computer: `ORCHESTRA_FDK_<NAME>_TOKEN=$(az keyvault secret show --vault-name <vault> --name <name> --query value -o tsv)` in the apply's shell | The Key Vault Secrets User role | `az account show` |
|
|
13
|
+
|
|
14
|
+
The check commands run on the developer's computer, with their own sign-in to the manager.
|
|
15
|
+
|
|
16
|
+
## How the value travels
|
|
17
|
+
|
|
18
|
+
1. The developer exports the variable in the shell that runs the apply. You run the apply in that shell
|
|
19
|
+
only when the developer can export it there. Otherwise the developer writes the value into the private
|
|
20
|
+
token file (phase 2, "The private token file") from the manager.
|
|
21
|
+
2. The factory reads it with `SecretValue.fromEnv("ORCHESTRA_FDK_<NAME>_TOKEN")`.
|
|
22
|
+
3. Never echo the variable, and never pass the value as a command argument: both can reach a log.
|
|
23
|
+
|
|
24
|
+
A Secret keeps the value it had at its last apply. After the developer rotates a token in the manager, apply
|
|
25
|
+
again with the new value loaded.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Support desks
|
|
2
|
+
|
|
3
|
+
Give access with a Secret the network edge adds, or with the provider's platform connection. Egress is open,
|
|
4
|
+
so add only the rule that adds the credential. A connection also brings events: a `Trigger` on them makes a
|
|
5
|
+
work item in the Support pipeline for each new ticket. The agent installs or uses whatever client it prefers.
|
|
6
|
+
The edge adds the credential to its requests.
|
|
7
|
+
|
|
8
|
+
Phase 3, "From a recipe to code", turns a recipe into a Secret and a rule.
|
|
9
|
+
|
|
10
|
+
| Provider | Access | Scopes | Check command |
|
|
11
|
+
|---|---|---|---|
|
|
12
|
+
| Zendesk | Platform connection `zendesk`, install field `subdomain`, with `.allow(zendesk)` on `<subdomain>.zendesk.com`. Or a token: `<subdomain>.zendesk.com → Authorization: Basic <email>/token:<SECRET>` | An agent's API token | `curl -fsS https://<subdomain>.zendesk.com/api/v2/users/me.json` |
|
|
13
|
+
| Intercom | Platform connection `intercom`, with `.allow(intercom)` on `api.intercom.io`. Or a token: `api.intercom.io → Authorization: Bearer <SECRET>` | An access token from a private app | `curl -fsS https://api.intercom.io/me` |
|
|
14
|
+
| Freshdesk | `<domain>.freshdesk.com → Authorization: Basic <SECRET>:X`. The API key is the user name, and `X` is the password | An agent's API key | `curl -fsS https://<domain>.freshdesk.com/api/v2/agents/me` |
|
|
15
|
+
|
|
16
|
+
Token pages: Zendesk **Admin Center › Apps and integrations › APIs**; Intercom **Developer Hub**; Freshdesk
|
|
17
|
+
**Profile settings › API key**.
|
|
18
|
+
|
|
19
|
+
## Basic auth with a fixed suffix
|
|
20
|
+
|
|
21
|
+
- **Zendesk:** the user name is the agent's email followed by `/token`, and the password is the token:
|
|
22
|
+
`SecretValue.basicAuth("<email>/token", SecretValue.fromEnv("ORCHESTRA_FDK_ZENDESK_TOKEN"))`.
|
|
23
|
+
- **Freshdesk:** the API key is the user name, and the password is any fixed text, such as `X`. The kit's
|
|
24
|
+
Basic recipe puts the Secret in the password, so store the whole `<api key>:X` pair, base64-encoded, as the
|
|
25
|
+
Secret's value, and bind it with `basic("Authorization", secret)` (check the vendor page).
|
|
26
|
+
|
|
27
|
+
## Events
|
|
28
|
+
|
|
29
|
+
Each connection's events: `orchestra connections list-event-types <connection>`. The Intercom webhook is set
|
|
30
|
+
up by hand in Intercom's Developer Hub, with the connection's address. Write the address to a file the
|
|
31
|
+
developer can read: `npx orchestra connections rotate-webhook-token <connection> --output-file <path>`.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Phase 0: Start
|
|
2
|
+
|
|
3
|
+
**Goal:** the kit is installed and current, you are signed in to the organization the developer chose, and
|
|
4
|
+
you know what the platform can do.
|
|
5
|
+
|
|
6
|
+
## 1. Install the kit
|
|
7
|
+
|
|
8
|
+
The kit is the `orchestra` command and the library the factory code imports. It was installed before this
|
|
9
|
+
skill was linked, in one of two places. Keep it and its skills current with the command that matches:
|
|
10
|
+
|
|
11
|
+
- Globally, with `npm install -g @orchestraworks/cli`. Update it with `npm update -g @orchestraworks/cli`.
|
|
12
|
+
Then `orchestra` runs in any folder.
|
|
13
|
+
- In the factory folder, with `npm install @orchestraworks/cli` there. Update it with
|
|
14
|
+
`npm update @orchestraworks/cli`, run in that folder. Run the command there as `npx orchestra`.
|
|
15
|
+
|
|
16
|
+
Use one way to run the command in each place:
|
|
17
|
+
|
|
18
|
+
- Where no factory folder with the kit exists yet (phases 0 to 3), run
|
|
19
|
+
`npx --package @orchestraworks/cli orchestra`. With a global install, plain `orchestra` works too.
|
|
20
|
+
- In a factory folder after its `npm install`, run `npx orchestra`.
|
|
21
|
+
|
|
22
|
+
Find the developer's codebase folder. Call it `<codebase>`. Then run
|
|
23
|
+
`npx --package @orchestraworks/cli orchestra --help`. It prints the command list. Node 22 or later is needed.
|
|
24
|
+
|
|
25
|
+
## 2. Sign in
|
|
26
|
+
|
|
27
|
+
1. Tell the developer: "A browser window will open. Sign in to Orchestra there and confirm."
|
|
28
|
+
2. Run the sign-in with a command timeout of at least five minutes. The CLI opens the browser and waits for
|
|
29
|
+
the answer on a local port of this computer, so the browser must run on this same computer. When the
|
|
30
|
+
developer belongs to one organization, the login selects it. When they belong to several, the login stops
|
|
31
|
+
and asks you to name one. Ask the developer which, then run:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npx --package @orchestraworks/cli orchestra auth login --org <organization>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
This sign-in renews itself, so a long run stays signed in. The address it signs in to is its first line.
|
|
38
|
+
3. Use this browser sign-in. `orchestra auth login --no-browser` asks for a token at a hidden prompt
|
|
39
|
+
instead, and a typed token cannot renew itself: it stops working when it expires. Use it only for a short
|
|
40
|
+
run, with a token someone hands the developer. Users cannot create their own API keys in the console
|
|
41
|
+
yet; that is coming. If no browser can open on this computer, tell the developer. Ask them to run you on
|
|
42
|
+
a computer where one can.
|
|
43
|
+
4. Read the two lines the login prints: `Signed in as <email>.` and
|
|
44
|
+
`Logged in to organization <id> (<slug>).` Tell the developer both, and confirm the organization.
|
|
45
|
+
|
|
46
|
+
## 3. Read the orchestra skill
|
|
47
|
+
|
|
48
|
+
Read `orchestra/SKILL.md` in your skill folder, in full, before phase 1. It says what each idea is for, what
|
|
49
|
+
the starter declares, and what the platform cannot do yet. The later phases point at its sections. Never
|
|
50
|
+
promise one of its "Cannot yet" lines.
|
|
51
|
+
|
|
52
|
+
## Exit check
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
npx --package @orchestraworks/cli orchestra me get --output json
|
|
56
|
+
node -p 'require(require("os").homedir() + "/.config/orchestra/config.json").profiles.default.organizationId'
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The first answer's `email` is the developer's. A signed-in person's answer names no organization, so the
|
|
60
|
+
second command reads the organization from the profile the sign-in saved. It prints only that id, never the
|
|
61
|
+
token. The id is the one in `Logged in to organization <id> (<slug>).`, which the developer confirmed. You
|
|
62
|
+
have read the orchestra skill. If the check fails, read `../troubleshooting.md`, "The sign-in stops working".
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# Phase 1: Discover
|
|
2
|
+
|
|
3
|
+
**Goal:** you know what to build: a new factory or a new environment, what the codebase needs to run, and
|
|
4
|
+
which services the agents must reach. You write it down before any factory code exists.
|
|
5
|
+
|
|
6
|
+
Write every finding into `<codebase>/../orchestra-factory-notes.md`, one line for each item, with the file,
|
|
7
|
+
page or command that shows it.
|
|
8
|
+
|
|
9
|
+
## 1. Read the account: a new factory or a new environment
|
|
10
|
+
|
|
11
|
+
An organization usually holds one factory, or none yet. Read what it holds before you ask the developer
|
|
12
|
+
anything. These commands only read. `--all-pages` follows every page, and prints the rows as one array:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npx --package @orchestraworks/cli orchestra agents list --all-pages --output json
|
|
16
|
+
npx --package @orchestraworks/cli orchestra environments list --all-pages --output json
|
|
17
|
+
npx --package @orchestraworks/cli orchestra pipelines list --all-pages --output json
|
|
18
|
+
npx --package @orchestraworks/cli orchestra workflows list --all-pages --output json
|
|
19
|
+
npx --package @orchestraworks/cli orchestra connections list --output json
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
A row that an apply made carries the label `sfdk.managedBy`, whose value is the factory's name.
|
|
23
|
+
|
|
24
|
+
1. Infer what the developer most likely wants:
|
|
25
|
+
- *No agents and no pipelines:* the account is empty. Infer **a new factory**.
|
|
26
|
+
- *Rows labeled with a factory name:* a factory exists. Infer **a new environment for that factory**,
|
|
27
|
+
such as another repository, a bigger machine, or a machine of the team's own.
|
|
28
|
+
- *Rows with no label:* someone made them by hand or with the CLI. Infer a new factory. If a row's slug
|
|
29
|
+
is one the starter declares, such as `manager-agent`, the apply updates that row. Say so in phase 2.
|
|
30
|
+
2. Tell the developer what you found, in one or two sentences, for example: "This organization already has
|
|
31
|
+
the factory `factory`, with the agents Manager Agent, Engineer Agent lg, md and sm."
|
|
32
|
+
3. Ask once, with your question tool, with the inferred choice first and marked as the recommendation.
|
|
33
|
+
|
|
34
|
+
**A new factory.** Go on with section 2.
|
|
35
|
+
|
|
36
|
+
The starters build one factory per organization. When the organization already holds a factory and the
|
|
37
|
+
developer wants another one, make a separate organization for it:
|
|
38
|
+
|
|
39
|
+
1. Create it: `npx --package @orchestraworks/cli orchestra organizations create --name "<name>"`. Read
|
|
40
|
+
`organizations create --help` for its other flags. When the command refuses, the developer creates the
|
|
41
|
+
organization in the console at `https://app.orchestraworks.ai`.
|
|
42
|
+
2. Sign in to it as phase 0 says, with `--org <the new organization>`.
|
|
43
|
+
3. Start this phase again, in the new organization.
|
|
44
|
+
|
|
45
|
+
**A new environment for the existing factory.** Do not run `orchestra fdk init` in phase 4. Edit the factory
|
|
46
|
+
that exists instead:
|
|
47
|
+
|
|
48
|
+
1. Find the existing factory's folder: the folder with `fdk.json` and `main.ts`. Ask the developer where it
|
|
49
|
+
is when it is not on this computer.
|
|
50
|
+
2. Load the factory's inputs, the same way every earlier apply loaded them. The engineering-team starter
|
|
51
|
+
reads `~/.config/orchestra/tokens.env`; the bug-fix starter reads `~/.config/orchestra/fdk-inputs.env`.
|
|
52
|
+
Load the file with `set -a; . <file>; set +a`, and never print it. Ask the developer when the file is not
|
|
53
|
+
there. An apply without these inputs removes the token rules the factory has now.
|
|
54
|
+
3. With the inputs loaded, run `npm install` and `npx orchestra fdk diff` in that folder. It must be a clean
|
|
55
|
+
diff before you edit anything. If it is not, show the changes to the developer and ask what to keep.
|
|
56
|
+
4. Then read the repository (section 2) for the new environment only. Phase 2 plans the new environment and
|
|
57
|
+
the agent that works on it, and phase 4 adds them to the existing code.
|
|
58
|
+
|
|
59
|
+
## 2. Read the repository
|
|
60
|
+
|
|
61
|
+
Read the codebase before you write any factory code. The factory must match it, and the machines most of
|
|
62
|
+
all. Note each item:
|
|
63
|
+
|
|
64
|
+
- **The operating system it builds and runs on.** These mean Windows: a `.sln` or `.csproj` that targets
|
|
65
|
+
.NET Framework, WinForms, WPF or IIS, PowerShell build scripts, or `windows-latest` in CI.
|
|
66
|
+
- **The runtime it needs.** A kernel feature, a GPU, nested virtualization, an Android emulator, or a tool
|
|
67
|
+
for another operating system, such as Xcode, means a full virtual machine or the team's own machine.
|
|
68
|
+
- The languages and toolchains, with their versions: `global.json`, `.nvmrc`, `.tool-versions`, the CI's
|
|
69
|
+
setup steps.
|
|
70
|
+
- The build and test commands, from the CI file first, then the README and the build scripts.
|
|
71
|
+
- The package feeds, private ones included: `nuget.config`, `.npmrc`, `pip.conf`, a feed in the CI file.
|
|
72
|
+
- The services it needs, such as a database or a queue: a compose file, test containers, connection
|
|
73
|
+
settings.
|
|
74
|
+
- Docker use: a `Dockerfile`, a compose file, Testcontainers.
|
|
75
|
+
- The repository size: `du -sh <codebase>` and `git -C <codebase> count-objects -vH`.
|
|
76
|
+
- The code host and the tracker: the remote URL (`git -C <codebase> remote get-url origin`), and links in
|
|
77
|
+
the README, the branch names or the CI file.
|
|
78
|
+
|
|
79
|
+
These are facts for the later phases. Ask the developer only what the files cannot answer.
|
|
80
|
+
|
|
81
|
+
## 3. Name each service, by category and provider
|
|
82
|
+
|
|
83
|
+
For each outside service the agents need, name its category and its provider. Each category has one file in
|
|
84
|
+
`../integrations/`:
|
|
85
|
+
|
|
86
|
+
| Category | File | Examples |
|
|
87
|
+
|---|---|---|
|
|
88
|
+
| Code host | `code-repo.md` | GitHub, Bitbucket, GitLab, Azure DevOps |
|
|
89
|
+
| Tracker | `issue-tracker.md` | Jira, Linear, GitHub Issues, Azure Boards |
|
|
90
|
+
| Knowledge base | `knowledge-base.md` | Notion, Confluence, Guru |
|
|
91
|
+
| Chat | `messaging.md` | Slack, Microsoft Teams |
|
|
92
|
+
| Package registries | `dependencies.md` | npm, PyPI, NuGet, Maven |
|
|
93
|
+
| CI and CD | `ci-cd.md` | GitHub Actions, Azure Pipelines, Jenkins, CircleCI |
|
|
94
|
+
| Observability | `observability.md` | Sentry, Datadog, New Relic, Grafana |
|
|
95
|
+
| Support desk | `support-desk.md` | Zendesk, Intercom, Freshdesk |
|
|
96
|
+
| Design | `design.md` | Figma |
|
|
97
|
+
| Cloud | `cloud.md` | AWS, Azure, Google Cloud |
|
|
98
|
+
| Databases | `databases.md` | A staging database or a read replica |
|
|
99
|
+
| Secrets managers | `secrets-managers.md` | 1Password, Vault, Azure Key Vault |
|
|
100
|
+
| Incidents | `incident.md` | PagerDuty, Opsgenie |
|
|
101
|
+
| Analytics | `analytics.md` | Pendo, Mixpanel, Amplitude |
|
|
102
|
+
| Feature flags | `feature-flags.md` | LaunchDarkly, Split, Unleash, ConfigCat |
|
|
103
|
+
|
|
104
|
+
Infer each one from the codebase and the connections list. Then tell the developer what you found, and ask
|
|
105
|
+
once, with your question tool, which code host, which tracker and which other services the agents need.
|
|
106
|
+
Put your inference first, marked as the recommendation. No provider is a default.
|
|
107
|
+
|
|
108
|
+
## Exit check
|
|
109
|
+
|
|
110
|
+
`orchestra-factory-notes.md` has a line for each item in sections 2 and 3, or says the item does not apply,
|
|
111
|
+
and it records the answer to section 1: a new factory, or a new environment for a named factory.
|