chore: add sigit-factory config and align agentic resources
Add .sigit config (factory, code-cloud-agent, code-review) and restructure the agent doc to match the onde repo layout: CLAUDE.md is moved to the canonical .agents/AGENTS.md, with root AGENTS.md and CLAUDE.md as symlinks. Co-Authored-By: siGit Code v1.6.6-acp <noreply@sigit.si>
Seto Elkahfi committed
Oct 11, 2026 at 15:10 UTC
be5afd54b4bbec0917136f485b41e6c8a31e46d3
7 files changed
+152
-104
.agents/AGENTS.md
new
+136
@@ -0,0 +1,136 @@
1
+# AGENTS.md
2
+
3
+This file provides guidance to AI coding agents (siGit Code, Claude Code, etc.) when working with code in this repository. It is the canonical agent doc, symlinked from the repo root as both `AGENTS.md` and `CLAUDE.md`.
4
+
5
+Guidance for AI coding agents working in this repository.
6
+
7
+## What this is
8
+
9
+`smbcloud-ascapi` is a Rust workspace wrapping the App Store Connect API. It
10
+ships two front ends over one shared core:
11
+
12
+- the `asc` CLI (`crates/cli`), and
13
+- an MCP stdio server (`crates/mcp`, reachable via `asc --mcp`).
14
+
15
+Both go through `smbcloud-ascapi-frontend` so they can't drift. See `README.md`
16
+for the full crate table.
17
+
18
+## Workspace layout
19
+
20
+Domain crates (`aso`, `pricing`, `signing`, `reports`) know nothing about each
21
+other or the front ends. Each extends `smbcloud_ascapi_core::Client` with an
22
+**extension trait** (Rust only allows inherent impls in the crate that owns the
23
+type). Import a domain's `prelude::*` to pull its traits in at once.
24
+
25
+## Conventions
26
+
27
+- JSON:API responses deserialize through `ListDocument<T>` / the core
28
+ envelopes; `Resource.id` is the ASC id.
29
+- CLI `ValueEnum` wrappers (`CliPlatform`, `CliBundleIdPlatform`,
30
+ `CliProfileType`, …) wrap the domain enums so clap owns the arg parsing;
31
+ map them to the domain type in the match arm (e.g. `.map(Platform::from)`).
32
+- Tests live in-module: `#[cfg(test)] mod tests { use super::*; … }` with plain
33
+ `#[test]` fns (see `crates/aso/src/bundle_id.rs`, `crates/aso/src/build.rs`).
34
+- Pin exact ASC filter keys in assertions — e.g.
35
+ `filter[preReleaseVersion.version]` vs `filter[version]`; the wrong key
36
+ silently returns the wrong rows.
37
+
38
+## Builds API (CLI)
39
+
40
+All are subcommands of `apps` (clap kebab-cases the command names):
41
+
42
+```sh
43
+# GET /v1/builds?filter[app]={id} — newest first. Check processingState
44
+# (VALID / INVALID / PROCESSING / FAILED).
45
+asc apps builds <APP_ID> \
46
+ [--version <BUILD_NUMBER>] \ # filter[version], e.g. 42
47
+ [--pre-release-version <MARKETING>] \ # filter[preReleaseVersion.version], e.g. 1.1.0
48
+ [--processing-state <STATE>] # filter[processingState]
49
+
50
+# GET /v1/builds/{id} — a single build by its ASC id.
51
+asc apps build <BUILD_ID>
52
+
53
+# GET /v1/preReleaseVersions?filter[app]={id} — the marketing version strings
54
+# TestFlight groups builds under.
55
+asc apps pre-release-versions <APP_ID> [--platform <ios|mac-os|tv-os|vision-os>]
56
+
57
+# xcrun altool --upload-package, authenticated with the same key id, issuer
58
+# and .p8 (--p8-file-path) as every other command. --dry-run prints the argv.
59
+asc apps upload <PATH.ipa|PATH.pkg> [--wait]
60
+```
61
+
62
+The underlying API lives in `crates/aso/src/build.rs`: `BuildsApi` (in the
63
+`aso` prelude) plus `BuildFilter`, whose private `query_pairs` maps each set
64
+field to its ASC filter key. The upload lives in
65
+`crates/frontend/src/upload.rs`. It always passes `--p8-file-path` and never
66
+`--auth-string`: letting altool search its key directories can pick up a
67
+stale `AuthKey_<id>.p8` and fail with a 401, and `--auth-string` would put
68
+the key in the process table. Upload is CLI-only, because a tool call that
69
+blocks for minutes and publishes a build doesn't belong in MCP.
70
+
71
+## Verify before committing
72
+
73
+CI (`.github/workflows/ci.yml`, ubuntu + macOS) runs these, and warnings are
74
+errors, so run the strict forms locally:
75
+
76
+```sh
77
+cargo fmt --all -- --check
78
+cargo clippy --workspace --all-targets --locked -- -D warnings
79
+cargo test --workspace --locked
80
+RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --workspace --locked
81
+cargo check -p smbcloud-ascapi-core --locked # also -aso, -signing: each lower crate must build alone
82
+```
83
+
84
+Single test: `cargo test -p smbcloud-ascapi-aso build::tests::<name>`.
85
+Intra-doc links are load-bearing (a broken one fails CI), and the CSR tests
86
+shell out to `openssl`, whose output differs between OpenSSL 3 and macOS
87
+LibreSSL.
88
+
89
+## Architecture notes
90
+
91
+- Layering is `core` → `aso`/`pricing`/`signing`/`reports` → `frontend` →
92
+ `mcp` / `cli`. Don't add a dependency that points up or sideways; CI checks
93
+ the lower crates build alone.
94
+- The MCP tool set is declared by the `ascapi_mcp_tools!` macro
95
+ (`crates/mcp/src/lib.rs`), which takes every tool name as a literal;
96
+ `crates/mcp/src/server.rs` supplies them. Adding a tool means touching the
97
+ macro, the invocation, and `requests.rs`.
98
+- stdout belongs to the MCP JSON-RPC stream: nothing under a tool call may
99
+ `println!`. Results sent to a model never contain private keys or
100
+ certificate/profile bodies; return the path written instead. That is
101
+ enforced by the result types in `crates/frontend`, so keep new result types
102
+ free of key material rather than filtering at the edge.
103
+- Destructive or irreversible operations stay CLI-only (certificate revoke,
104
+ review submission, upload). Recreatable deletes may be MCP tools, annotated
105
+ destructive.
106
+- `.agents/plans/` holds design plans from past release sessions; check them
107
+ before reworking upload or signing-identity behaviour.
108
+
109
+## Credentials
110
+
111
+The CLI needs an ASC API key: `--key-id`/`ASC_API_KEY`,
112
+`--issuer-id`/`ASC_ISSUER_ID`, and the `.p8` at
113
+`--private-key-path`/`ASC_PRIVATE_KEY_PATH` (defaults to
114
+`~/.appstoreconnect/private_keys/AuthKey_<key-id>.p8`). `--mcp` resolves
115
+credentials per tool call, so the server can list tools unconfigured.
116
+
117
+## Review submissions (CLI)
118
+
119
+```sh
120
+# GET /v1/reviewSubmissions?filter[app]={id}
121
+asc review-submissions list <APP_ID> [--platform <...>] [--state READY_FOR_REVIEW]
122
+
123
+# Reuse the platform's open (READY_FOR_REVIEW) submission or create one, add
124
+# the version as an item, then PATCH submitted: true. --dry-run reads and
125
+# prints the plan. Refuses a version that is already WAITING_FOR_REVIEW,
126
+# IN_REVIEW or live, before any write.
127
+asc review-submissions submit <APP_ID> --version-id <APP_STORE_VERSION_ID>
128
+
129
+# PATCH canceled: true, for a submission App Review hasn't picked up.
130
+asc review-submissions cancel <SUBMISSION_ID>
131
+```
132
+
133
+The API is `ReviewSubmissionsApi` in `crates/aso/src/review_submission.rs`;
134
+the plan/submit orchestration is `crates/frontend/src/review.rs`. Submitting is
135
+CLI-only on purpose: it sends a build to App Review, which an MCP tool call
136
+shouldn't do on a model's say-so.
.sigit/code-cloud-agent/config.toml
new
+2
@@ -0,0 +1,2 @@
1
+[agent]
2
+model = "onde-balance"
.sigit/code-review/config.toml
new
+3
@@ -0,0 +1,3 @@
1
+[agent]
2
+login = "sigit-code-review"
3
+display_name = "siGit Code Review"
.sigit/factory/config.toml
new
+9
@@ -0,0 +1,9 @@
1
+[agent]
2
+model = "onde-large"
3
+
4
+[harvest]
5
+state = "closed"
6
+limit = 50
7
+since = "2026-09-01"
8
+cadence = "weekly"
9
+day_of_week = "Mon"
AGENTS.md
new
+1
@@ -0,0 +1 @@
1
+.agents/AGENTS.md
\ No newline at end of file
CLAUDE.md
deleted
-104
@@ -1,104 +0,0 @@
1
-# CLAUDE.md
2
-
3
-Guidance for Claude Code (and other agents) working in this repository.
4
-
5
-## What this is
6
-
7
-`smbcloud-ascapi` is a Rust workspace wrapping the App Store Connect API. It
8
-ships two front ends over one shared core:
9
-
10
-- the `asc` CLI (`crates/cli`), and
11
-- an MCP stdio server (`crates/mcp`, reachable via `asc --mcp`).
12
-
13
-Both go through `smbcloud-ascapi-frontend` so they can't drift. See `README.md`
14
-for the full crate table.
15
-
16
-## Workspace layout
17
-
18
-Domain crates (`aso`, `pricing`, `signing`, `reports`) know nothing about each
19
-other or the front ends. Each extends `smbcloud_ascapi_core::Client` with an
20
-**extension trait** (Rust only allows inherent impls in the crate that owns the
21
-type). Import a domain's `prelude::*` to pull its traits in at once.
22
-
23
-## Conventions
24
-
25
-- JSON:API responses deserialize through `ListDocument<T>` / the core
26
- envelopes; `Resource.id` is the ASC id.
27
-- CLI `ValueEnum` wrappers (`CliPlatform`, `CliBundleIdPlatform`,
28
- `CliProfileType`, …) wrap the domain enums so clap owns the arg parsing;
29
- map them to the domain type in the match arm (e.g. `.map(Platform::from)`).
30
-- Tests live in-module: `#[cfg(test)] mod tests { use super::*; … }` with plain
31
- `#[test]` fns (see `crates/aso/src/bundle_id.rs`, `crates/aso/src/build.rs`).
32
-- Pin exact ASC filter keys in assertions — e.g.
33
- `filter[preReleaseVersion.version]` vs `filter[version]`; the wrong key
34
- silently returns the wrong rows.
35
-
36
-## Builds API (CLI)
37
-
38
-All are subcommands of `apps` (clap kebab-cases the command names):
39
-
40
-```sh
41
-# GET /v1/builds?filter[app]={id} — newest first. Check processingState
42
-# (VALID / INVALID / PROCESSING / FAILED).
43
-asc apps builds <APP_ID> \
44
- [--version <BUILD_NUMBER>] \ # filter[version], e.g. 42
45
- [--pre-release-version <MARKETING>] \ # filter[preReleaseVersion.version], e.g. 1.1.0
46
- [--processing-state <STATE>] # filter[processingState]
47
-
48
-# GET /v1/builds/{id} — a single build by its ASC id.
49
-asc apps build <BUILD_ID>
50
-
51
-# GET /v1/preReleaseVersions?filter[app]={id} — the marketing version strings
52
-# TestFlight groups builds under.
53
-asc apps pre-release-versions <APP_ID> [--platform <ios|mac-os|tv-os|vision-os>]
54
-
55
-# xcrun altool --upload-package, authenticated with the same key id, issuer
56
-# and .p8 (--p8-file-path) as every other command. --dry-run prints the argv.
57
-asc apps upload <PATH.ipa|PATH.pkg> [--wait]
58
-```
59
-
60
-The underlying API lives in `crates/aso/src/build.rs`: `BuildsApi` (in the
61
-`aso` prelude) plus `BuildFilter`, whose private `query_pairs` maps each set
62
-field to its ASC filter key. The upload lives in
63
-`crates/frontend/src/upload.rs`. It always passes `--p8-file-path` and never
64
-`--auth-string`: letting altool search its key directories can pick up a
65
-stale `AuthKey_<id>.p8` and fail with a 401, and `--auth-string` would put
66
-the key in the process table. Upload is CLI-only, because a tool call that
67
-blocks for minutes and publishes a build doesn't belong in MCP.
68
-
69
-## Verify before committing
70
-
71
-```sh
72
-cargo fmt --all
73
-cargo clippy --all-targets
74
-cargo test
75
-```
76
-
77
-## Credentials
78
-
79
-The CLI needs an ASC API key: `--key-id`/`ASC_API_KEY`,
80
-`--issuer-id`/`ASC_ISSUER_ID`, and the `.p8` at
81
-`--private-key-path`/`ASC_PRIVATE_KEY_PATH` (defaults to
82
-`~/.appstoreconnect/private_keys/AuthKey_<key-id>.p8`). `--mcp` resolves
83
-credentials per tool call, so the server can list tools unconfigured.
84
-
85
-## Review submissions (CLI)
86
-
87
-```sh
88
-# GET /v1/reviewSubmissions?filter[app]={id}
89
-asc review-submissions list <APP_ID> [--platform <...>] [--state READY_FOR_REVIEW]
90
-
91
-# Reuse the platform's open (READY_FOR_REVIEW) submission or create one, add
92
-# the version as an item, then PATCH submitted: true. --dry-run reads and
93
-# prints the plan. Refuses a version that is already WAITING_FOR_REVIEW,
94
-# IN_REVIEW or live, before any write.
95
-asc review-submissions submit <APP_ID> --version-id <APP_STORE_VERSION_ID>
96
-
97
-# PATCH canceled: true, for a submission App Review hasn't picked up.
98
-asc review-submissions cancel <SUBMISSION_ID>
99
-```
100
-
101
-The API is `ReviewSubmissionsApi` in `crates/aso/src/review_submission.rs`;
102
-the plan/submit orchestration is `crates/frontend/src/review.rs`. Submitting is
103
-CLI-only on purpose: it sends a build to App Review, which an MCP tool call
104
-shouldn't do on a model's say-so.
CLAUDE.md
new
+1
@@ -0,0 +1 @@
1
+.agents/AGENTS.md
\ No newline at end of file