generated from coulomb/repo-seed
Compare commits
7 Commits
3a60623730
...
v0.2.1
| Author | SHA1 | Date | |
|---|---|---|---|
| 3c66148205 | |||
| 2f40dea6a1 | |||
| 8c01f07c2d | |||
| 7693ef8680 | |||
| 4854bda118 | |||
| 19d4bc96df | |||
| d50ab96a8a |
@@ -1,11 +1,11 @@
|
|||||||
## First Session Protocol
|
## First Session Protocol
|
||||||
|
|
||||||
Triggered when `get_domain_summary("custodian")` shows **no workstreams**.
|
Triggered when `get_domain_summary("infotech")` shows **no workstreams**.
|
||||||
The project is registered but work has not yet been structured.
|
The project is registered but work has not yet been structured.
|
||||||
|
|
||||||
**Step 1 — Read, don't write**
|
**Step 1 — Read, don't write**
|
||||||
- `~/the-custodian/canon/projects/custodian/project_charter_v0.1.md` — purpose, scope
|
- `~/the-custodian/canon/projects/infotech/project_charter_v0.1.md` — purpose, scope
|
||||||
- `~/the-custodian/canon/projects/custodian/roadmap_v0.1.md` — planned phases
|
- `~/the-custodian/canon/projects/infotech/roadmap_v0.1.md` — planned phases
|
||||||
- Scan repo root: README, directory structure, existing code or docs
|
- Scan repo root: README, directory structure, existing code or docs
|
||||||
|
|
||||||
**Step 2 — Survey in-progress work**
|
**Step 2 — Survey in-progress work**
|
||||||
@@ -17,7 +17,7 @@ roadmap phase. **Wait for approval before creating.**
|
|||||||
|
|
||||||
**Step 4 — Create workplan file first, then DB record (ADR-001)**
|
**Step 4 — Create workplan file first, then DB record (ADR-001)**
|
||||||
```
|
```
|
||||||
workplans/issue-core-WP-NNNN-<slug>.md ← write this first
|
workplans/ISSUE-WP-NNNN-<slug>.md ← write this first
|
||||||
```
|
```
|
||||||
Then register in the hub:
|
Then register in the hub:
|
||||||
```
|
```
|
||||||
@@ -28,7 +28,7 @@ create_task(workstream_id="<id>", title="...", priority="high|medium|low")
|
|||||||
**Step 5 — Record the setup**
|
**Step 5 — Record the setup**
|
||||||
```
|
```
|
||||||
add_progress_event(
|
add_progress_event(
|
||||||
summary="First session: structured custodian into N workstreams, M tasks",
|
summary="First session: structured infotech into N workstreams, M tasks",
|
||||||
event_type="milestone",
|
event_type="milestone",
|
||||||
topic_id="cee7bedf-2b48-46ef-8601-006474f2ad7a",
|
topic_id="cee7bedf-2b48-46ef-8601-006474f2ad7a",
|
||||||
detail={"workstreams": [...], "tasks_created": M}
|
detail={"workstreams": [...], "tasks_created": M}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
**Purpose:** Authoritative task lifecycle manager for the Coulomb org. Backend-agnostic CLI + REST ingestion endpoint for tasks from activity-core's IssueSink. Pluggable backends (Gitea, SQLite, GitHub). Renamed from issue-facade on 2026-05-17.
|
**Purpose:** Authoritative task lifecycle manager for the Coulomb org. Backend-agnostic CLI + REST ingestion endpoint for tasks from activity-core's IssueSink. Pluggable backends (Gitea, SQLite, GitHub). Renamed from issue-facade on 2026-05-17.
|
||||||
|
|
||||||
**Domain:** custodian
|
**Domain:** infotech
|
||||||
**Repo slug:** issue-core
|
**Repo slug:** issue-core
|
||||||
**Topic ID:** cee7bedf-2b48-46ef-8601-006474f2ad7a
|
**Topic ID:** cee7bedf-2b48-46ef-8601-006474f2ad7a
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
## Session Protocol
|
## Session Protocol
|
||||||
|
|
||||||
State Hub: http://127.0.0.1:8000
|
Dev Hub (State Hub API): http://127.0.0.1:8000
|
||||||
|
MCP server name in `~/.claude.json`: `dev-hub`
|
||||||
|
|
||||||
**Step 1 — Orient**
|
**Step 1 — Orient**
|
||||||
|
|
||||||
@@ -10,7 +11,7 @@ cat .custodian-brief.md
|
|||||||
```
|
```
|
||||||
Then call the MCP tool for richer cross-domain context when MCP tools are exposed:
|
Then call the MCP tool for richer cross-domain context when MCP tools are exposed:
|
||||||
```
|
```
|
||||||
get_domain_summary("custodian")
|
get_domain_summary("infotech")
|
||||||
```
|
```
|
||||||
If MCP tools are unavailable in the current agent session, use the REST API:
|
If MCP tools are unavailable in the current agent session, use the REST API:
|
||||||
```bash
|
```bash
|
||||||
@@ -39,11 +40,11 @@ curl -s -X PATCH "http://127.0.0.1:8000/messages/<id>/read" \
|
|||||||
ls workplans/
|
ls workplans/
|
||||||
```
|
```
|
||||||
For each file with `status: ready`, `active`, or `blocked`, note pending
|
For each file with `status: ready`, `active`, or `blocked`, note pending
|
||||||
`todo`/`in_progress` tasks.
|
`wait`/`todo`/`progress` tasks.
|
||||||
|
|
||||||
**Step 4 — Present brief**
|
**Step 4 — Present brief**
|
||||||
|
|
||||||
1. **Active workstreams** for `custodian` — title, task counts, blocking decisions
|
1. **Active workstreams** for `infotech` — title, task counts, blocking decisions
|
||||||
2. **Pending tasks** from `workplans/` + any `[repo:issue-core]` hub tasks
|
2. **Pending tasks** from `workplans/` + any `[repo:issue-core]` hub tasks
|
||||||
3. **Goal guidance** — if `goal_guidance` in summary:
|
3. **Goal guidance** — if `goal_guidance` in summary:
|
||||||
- `needs_workplan`: surface as top action — *"Repo goal '{title}' has no workplan yet"*
|
- `needs_workplan`: surface as top action — *"Repo goal '{title}' has no workplan yet"*
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
## Workplan Convention (ADR-001)
|
## Workplan Convention (ADR-001)
|
||||||
|
|
||||||
File location: `workplans/issue-core-WP-NNNN-<slug>.md`
|
File location: `workplans/ISSUE-WP-NNNN-<slug>.md`
|
||||||
ID prefix: `ISSUE-WP`
|
ID prefix: `ISSUE-WP-`
|
||||||
|
|
||||||
Work items originate as files in this repo **before** being registered in the hub.
|
Work items originate as files in this repo **before** being registered in the hub.
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ repo state, and `finished` when implementation is complete. `stalled` and
|
|||||||
`needs_review` are derived health labels, not stored statuses.
|
`needs_review` are derived health labels, not stored statuses.
|
||||||
|
|
||||||
Closed workplans may be moved to `workplans/archived/` with a completion-date
|
Closed workplans may be moved to `workplans/archived/` with a completion-date
|
||||||
prefix: `YYMMDD-issue-core-WP-NNNN-<slug>.md`. The frontmatter id remains
|
prefix: `YYMMDD-ISSUE-WP-NNNN-<slug>.md`. The frontmatter id remains
|
||||||
unchanged; the prefix is only for quick visual reference.
|
unchanged; the prefix is only for quick visual reference.
|
||||||
|
|
||||||
Small opportunistic tasks discovered during another session use **Ad Hoc Tasks**:
|
Small opportunistic tasks discovered during another session use **Ad Hoc Tasks**:
|
||||||
@@ -25,4 +25,16 @@ Ecosystem todos from other agents arrive as `[repo:issue-core]` hub tasks —
|
|||||||
visible at session start. Pick one up by creating the workplan file, then registering
|
visible at session start. Pick one up by creating the workplan file, then registering
|
||||||
the workstream.
|
the workstream.
|
||||||
|
|
||||||
|
Task blocks use this shape:
|
||||||
|
|
||||||
|
```task
|
||||||
|
id: ISSUE-WP-NNNN-T01
|
||||||
|
status: wait | todo | progress | done | cancel
|
||||||
|
priority: high | medium | low
|
||||||
|
state_hub_task_id: "<uuid>" # written by fix-consistency — do not edit
|
||||||
|
```
|
||||||
|
|
||||||
|
Status progression is `todo` → `progress` → `done`; use `wait` for waiting or
|
||||||
|
blocked work and `cancel` for stopped work.
|
||||||
|
|
||||||
<!-- Ralph Loop rules and HEUREKA sequence: ~/.claude/CLAUDE.md — do not duplicate here -->
|
<!-- Ralph Loop rules and HEUREKA sequence: ~/.claude/CLAUDE.md — do not duplicate here -->
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<!-- custodian-brief: generated by fix-consistency — do not edit manually -->
|
<!-- custodian-brief: generated by fix-consistency — do not edit manually -->
|
||||||
# Custodian Brief — issue-core
|
# Custodian Brief — issue-core
|
||||||
|
|
||||||
**Domain:** custodian
|
**Domain:** infotech
|
||||||
**Last synced:** 2026-06-19 19:09 UTC
|
**Last synced:** 2026-06-23 12:26 UTC
|
||||||
**State Hub:** http://127.0.0.1:8000 *(adjust if running on a remote machine)*
|
**State Hub:** http://127.0.0.1:8000 *(adjust if running on a remote machine)*
|
||||||
|
|
||||||
## Active Workstreams
|
## Active Workstreams
|
||||||
@@ -12,16 +12,16 @@ Progress: 1/7 done | workstream_id: `896ace77-21b3-450b-8fb7-254aefc8c570`
|
|||||||
|
|
||||||
**Open tasks:**
|
**Open tasks:**
|
||||||
- ! ArgoCD bootstrap (railiance-platform dependency) + issue-core Application `9b199b1d`
|
- ! ArgoCD bootstrap (railiance-platform dependency) + issue-core Application `9b199b1d`
|
||||||
|
- ! OpenBao secret: ISSUE_CORE_API_KEY `ad52527f`
|
||||||
- ► Kubernetes manifests (namespace, Deployment, Service) in GitOps source `38887dd6`
|
- ► Kubernetes manifests (namespace, Deployment, Service) in GitOps source `38887dd6`
|
||||||
- ► In-cluster backend config (cluster Gitea / markitect) `10923f1e`
|
- ► In-cluster backend config (cluster Gitea / markitect) `10923f1e`
|
||||||
- · OpenBao secret: ISSUE_CORE_API_KEY `ad52527f`
|
- ► Wire activity-core to the live service `96b14cdb`
|
||||||
- · Wire activity-core to the live service `96b14cdb`
|
- ► End-to-end verification + GitOps runbook `8d853b8e`
|
||||||
- · End-to-end verification + GitOps runbook `8d853b8e`
|
|
||||||
|
|
||||||
---
|
---
|
||||||
## MCP Orientation (when available)
|
## MCP Orientation (when available)
|
||||||
|
|
||||||
If the state-hub MCP server is reachable, call:
|
If the state-hub MCP server is reachable, call:
|
||||||
`get_domain_summary("custodian")`
|
`get_domain_summary("infotech")`
|
||||||
This provides richer cross-domain context.
|
This provides richer cross-domain context.
|
||||||
If the MCP call fails, use this file as your orientation source.
|
If the MCP call fails, use this file as your orientation source.
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
# Repo classification (Repo Classification Standard v1.0).
|
# Repo classification (Repo Classification Standard v1.0).
|
||||||
# First-pass agent classification (CUST-WP-0050 T02) — pending human review.
|
|
||||||
|
|
||||||
repo_classification:
|
repo_classification:
|
||||||
standard: Repo Classification Standard
|
standard: Repo Classification Standard
|
||||||
version: '1.0'
|
version: '1.0'
|
||||||
classified_at: '2026-06-22'
|
classified_at: '2026-06-22'
|
||||||
classified_by: agent
|
classified_by: human
|
||||||
category: tooling
|
category: tooling
|
||||||
domain: infotech
|
domain: infotech
|
||||||
secondary_domains:
|
secondary_domains:
|
||||||
|
|||||||
41
AGENTS.md
41
AGENTS.md
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
**Purpose:** Authoritative task lifecycle manager for the Coulomb org. Backend-agnostic CLI + REST ingestion endpoint for tasks from activity-core's IssueSink. Pluggable backends (Gitea, SQLite, GitHub). Renamed from issue-facade on 2026-05-17.
|
**Purpose:** Authoritative task lifecycle manager for the Coulomb org. Backend-agnostic CLI + REST ingestion endpoint for tasks from activity-core's IssueSink. Pluggable backends (Gitea, SQLite, GitHub). Renamed from issue-facade on 2026-05-17.
|
||||||
|
|
||||||
**Domain:** custodian
|
**Domain:** infotech
|
||||||
**Repo slug:** issue-core
|
**Repo slug:** issue-core
|
||||||
**Topic ID:** `cee7bedf-2b48-46ef-8601-006474f2ad7a`
|
**Topic ID:** `cee7bedf-2b48-46ef-8601-006474f2ad7a`
|
||||||
**Workplan prefix:** `ISSUE-WP-`
|
**Workplan prefix:** `ISSUE-WP-`
|
||||||
@@ -63,8 +63,8 @@ Omit `workstream_id` / `task_id` when not applicable.
|
|||||||
```bash
|
```bash
|
||||||
curl -s -X PATCH "http://127.0.0.1:8000/tasks/<task_id>" \
|
curl -s -X PATCH "http://127.0.0.1:8000/tasks/<task_id>" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d '{"status": "in_progress"}'
|
-d '{"status": "progress"}'
|
||||||
# values: todo | in_progress | done | blocked
|
# values: wait | todo | progress | done | cancel
|
||||||
```
|
```
|
||||||
|
|
||||||
### Flag a task for human review
|
### Flag a task for human review
|
||||||
@@ -83,7 +83,7 @@ curl -s -X PATCH "http://127.0.0.1:8000/tasks/<task_id>" \
|
|||||||
1. `cat .custodian-brief.md` — domain goal and open workstreams (offline-safe)
|
1. `cat .custodian-brief.md` — domain goal and open workstreams (offline-safe)
|
||||||
2. Check inbox: `GET /messages/?to_agent=issue-core&unread_only=true`; mark read
|
2. Check inbox: `GET /messages/?to_agent=issue-core&unread_only=true`; mark read
|
||||||
3. Scan workplans: `ls workplans/` — note `status: ready`, `active`, or `blocked` files and open tasks
|
3. Scan workplans: `ls workplans/` — note `status: ready`, `active`, or `blocked` files and open tasks
|
||||||
4. Check blocked tasks: `GET /tasks/?needs_human=true`
|
4. Check human-needed tasks: `GET /tasks/?needs_human=true`
|
||||||
|
|
||||||
**During work:**
|
**During work:**
|
||||||
- Update task statuses in workplan files as tasks progress
|
- Update task statuses in workplan files as tasks progress
|
||||||
@@ -151,31 +151,10 @@ every repo's agent instructions because it is high-frequency, high-risk, and eas
|
|||||||
get wrong.
|
get wrong.
|
||||||
|
|
||||||
**Canon:** `~/ops-warden/wiki/CredentialRouting.md` · catalog `~/ops-warden/registry/routing/catalog.yaml`
|
**Canon:** `~/ops-warden/wiki/CredentialRouting.md` · catalog `~/ops-warden/registry/routing/catalog.yaml`
|
||||||
---
|
|
||||||
|
|
||||||
## REST ingestion API key
|
<!-- REPO-AGENTS-EXTENSIONS -->
|
||||||
|
<!-- Append repo-specific agent instructions below this marker.
|
||||||
`POST /issues/` requires a shared key in `ISSUE_CORE_API_KEY`. The server
|
The state-hub template sync preserves content after this line. -->
|
||||||
refuses to start without it. activity-core's `IssueCoreRestSink` sends the same
|
|
||||||
value as `Authorization: Bearer <key>` (also accepts `X-API-Key`).
|
|
||||||
|
|
||||||
**Do not request this key from ops-warden** — pair env vars locally or via
|
|
||||||
OpenBao/K8s on both repos. Routing lookup:
|
|
||||||
`warden route show activity-core-issue-sink --json`.
|
|
||||||
|
|
||||||
**Local dev:**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
export ISSUE_CORE_API_KEY="$(python3 -c 'import secrets; print(secrets.token_urlsafe(32))')"
|
|
||||||
issue serve --host 127.0.0.1 --port 8765
|
|
||||||
```
|
|
||||||
|
|
||||||
Set the same `ISSUE_CORE_API_KEY` in activity-core when `ISSUE_SINK_TYPE=rest`.
|
|
||||||
For local ingest smoke, set `default: local` in `~/.config/issue-tracker/backends.json`
|
|
||||||
— a remote Gitea default backend will hang on `POST /issues/`.
|
|
||||||
|
|
||||||
See `README.md` (REST Ingestion Server) and activity-core
|
|
||||||
`docs/issue-core-emission-boundary.md`.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -202,7 +181,7 @@ anything needing analysis, design, approval, dependencies, or multiple phases.
|
|||||||
id: ISSUE-WP-NNNN
|
id: ISSUE-WP-NNNN
|
||||||
type: workplan
|
type: workplan
|
||||||
title: "..."
|
title: "..."
|
||||||
domain: custodian
|
domain: infotech
|
||||||
repo: issue-core
|
repo: issue-core
|
||||||
status: proposed | ready | active | blocked | backlog | finished | archived
|
status: proposed | ready | active | blocked | backlog | finished | archived
|
||||||
owner: codex
|
owner: codex
|
||||||
@@ -224,7 +203,7 @@ derived health labels, not frontmatter statuses.
|
|||||||
|
|
||||||
` ` `task
|
` ` `task
|
||||||
id: ISSUE-WP-NNNN-T01
|
id: ISSUE-WP-NNNN-T01
|
||||||
status: todo | in_progress | done | blocked
|
status: wait | todo | progress | done | cancel
|
||||||
priority: high | medium | low
|
priority: high | medium | low
|
||||||
state_hub_task_id: "<uuid>" # written by fix-consistency — do not edit
|
state_hub_task_id: "<uuid>" # written by fix-consistency — do not edit
|
||||||
` ` `
|
` ` `
|
||||||
@@ -232,7 +211,7 @@ state_hub_task_id: "<uuid>" # written by fix-consistency — do not edit
|
|||||||
Task description text.
|
Task description text.
|
||||||
```
|
```
|
||||||
|
|
||||||
Status progression: `todo` → `in_progress` → `done` (or `blocked`)
|
Status progression: `todo` → `progress` → `done`; use `wait` for waiting/blocked work and `cancel` for stopped work.
|
||||||
|
|
||||||
To create a new workplan:
|
To create a new workplan:
|
||||||
1. Write the file following the format above
|
1. Write the file following the format above
|
||||||
|
|||||||
8
SCOPE.md
8
SCOPE.md
@@ -135,11 +135,17 @@ user directory.
|
|||||||
"due_in_days": 7,
|
"due_in_days": 7,
|
||||||
"source_type": "rule | instruction",
|
"source_type": "rule | instruction",
|
||||||
"source_id": "string",
|
"source_id": "string",
|
||||||
"triggering_event_id": "uuid",
|
"triggering_event_id": "event uuid or stable source key",
|
||||||
"activity_definition_id": "string"
|
"activity_definition_id": "string"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
`triggering_event_id` is accepted as a non-empty string. Event-driven
|
||||||
|
emissions should send the upstream activity event UUID. Scheduled or cron
|
||||||
|
emissions that do not have a concrete event row may send a stable source key
|
||||||
|
such as `scheduled`; issue-core stores the value verbatim in ingestion
|
||||||
|
metadata for traceability.
|
||||||
|
|
||||||
### `POST /issues/` response
|
### `POST /issues/` response
|
||||||
|
|
||||||
```json
|
```json
|
||||||
|
|||||||
168
docs/argocd-gitops.md
Normal file
168
docs/argocd-gitops.md
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
# ArgoCD GitOps deployment - railiance01
|
||||||
|
|
||||||
|
This runbook captures the issue-core side of the railiance01 GitOps pilot.
|
||||||
|
It keeps secrets out of Git and leaves platform-owned bootstrap steps in
|
||||||
|
railiance-platform.
|
||||||
|
|
||||||
|
## Source layout
|
||||||
|
|
||||||
|
- Workload bundle: `issue-core/k8s/railiance/`
|
||||||
|
- Image: `gitea.coulomb.social/coulomb/issue-core:0.2.0`
|
||||||
|
- Container port and Service port: `8765`
|
||||||
|
- Cluster Service URL: `http://issue-core.issue-core.svc.cluster.local:8765`
|
||||||
|
- Tenant Application: `railiance-platform/argocd/applications/issue-core.application.yaml`
|
||||||
|
|
||||||
|
The `Application` should point at this repo's `k8s/railiance` path and use
|
||||||
|
`CreateNamespace=true` for the `issue-core` namespace. The namespace itself is
|
||||||
|
therefore intentionally not duplicated in this bundle.
|
||||||
|
|
||||||
|
## Platform gates
|
||||||
|
|
||||||
|
The following pieces are owned by railiance-platform before the workload can
|
||||||
|
be fully reconciled:
|
||||||
|
|
||||||
|
- ArgoCD repository credentials and the project/app-of-apps convention.
|
||||||
|
- The `issue-core` ArgoCD `Application`.
|
||||||
|
- External Secrets Operator and a `ClusterSecretStore` named `openbao`.
|
||||||
|
- OpenBao entries for the issue-core runtime Secret.
|
||||||
|
|
||||||
|
Until those gates exist, `kubectl kustomize k8s/railiance` can render locally,
|
||||||
|
but the live `ExternalSecret` and `Deployment` are expected to wait.
|
||||||
|
|
||||||
|
## Secret contract
|
||||||
|
|
||||||
|
Kubernetes Secret name: `issue-core-runtime`
|
||||||
|
|
||||||
|
Current issue-core manifest path, pending railiance-platform confirmation:
|
||||||
|
|
||||||
|
```text
|
||||||
|
platform/workloads/issue-core/issue-core/issue-core-runtime
|
||||||
|
```
|
||||||
|
|
||||||
|
Credential route catalog id `issue-core-ingestion-api-key` is owned by
|
||||||
|
railiance-platform/OpenBao and is still marked draft/path TBD in the local
|
||||||
|
ops-warden catalog reviewed 2026-06-18. Confirm the canonical path before
|
||||||
|
provisioning the live Secret.
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
|
||||||
|
- `ISSUE_CORE_API_KEY` - shared ingestion key used by issue-core and
|
||||||
|
activity-core.
|
||||||
|
- `GITEA_BACKEND_TOKEN` - token for creating issues in cluster Gitea.
|
||||||
|
|
||||||
|
Never write either value to Git, State Hub, workplans, logs, or chat. Record
|
||||||
|
only non-secret evidence such as Secret key count, ExternalSecret readiness,
|
||||||
|
HTTP status codes, and created issue URLs.
|
||||||
|
|
||||||
|
## Build and publish
|
||||||
|
|
||||||
|
Use the published package as the image input. For a reproducible release image,
|
||||||
|
pin the package version to the image tag:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker build --build-arg ISSUE_CORE_VERSION="==0.2.0" -t gitea.coulomb.social/coulomb/issue-core:0.2.0 .
|
||||||
|
docker push gitea.coulomb.social/coulomb/issue-core:0.2.0
|
||||||
|
```
|
||||||
|
|
||||||
|
The Coulomb Gitea package is public-pullable for this image, so the workload
|
||||||
|
does not use an `imagePullSecret`.
|
||||||
|
|
||||||
|
## Pre-sync validation
|
||||||
|
|
||||||
|
From the issue-core repo:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl kustomize k8s/railiance
|
||||||
|
```
|
||||||
|
|
||||||
|
The rendered resources should be:
|
||||||
|
|
||||||
|
- `ExternalSecret/issue-core-runtime`
|
||||||
|
- `ConfigMap/issue-core-backends`
|
||||||
|
- `Deployment/issue-core`
|
||||||
|
- `Service/issue-core`
|
||||||
|
|
||||||
|
## Sync verification
|
||||||
|
|
||||||
|
After railiance-platform syncs the tenant `Application`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl get application issue-core -n argocd
|
||||||
|
kubectl -n issue-core get externalsecret issue-core-runtime
|
||||||
|
kubectl -n issue-core get secret issue-core-runtime
|
||||||
|
kubectl -n issue-core get deploy,pod,svc
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected non-secret evidence:
|
||||||
|
|
||||||
|
- ArgoCD Application reports `Synced` and `Healthy`.
|
||||||
|
- `ExternalSecret/issue-core-runtime` reports Ready.
|
||||||
|
- `Secret/issue-core-runtime` exists with two data keys.
|
||||||
|
- `Deployment/issue-core` has one available replica.
|
||||||
|
- `Service/issue-core` exposes port `8765`.
|
||||||
|
|
||||||
|
Health check from inside the cluster:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl -n issue-core run issue-core-health --rm -i --restart=Never --image=curlimages/curl:8.8.0 -- http://issue-core:8765/healthz
|
||||||
|
```
|
||||||
|
|
||||||
|
## Ingestion smoke
|
||||||
|
|
||||||
|
Run the authenticated smoke from a short-lived Job so the API key is mounted
|
||||||
|
from the Kubernetes Secret without printing it:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl -n issue-core delete job issue-core-smoke --ignore-not-found
|
||||||
|
kubectl -n issue-core apply -f - <<'YAML'
|
||||||
|
apiVersion: batch/v1
|
||||||
|
kind: Job
|
||||||
|
metadata:
|
||||||
|
name: issue-core-smoke
|
||||||
|
spec:
|
||||||
|
ttlSecondsAfterFinished: 600
|
||||||
|
backoffLimit: 0
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
restartPolicy: Never
|
||||||
|
containers:
|
||||||
|
- name: smoke
|
||||||
|
image: curlimages/curl:8.8.0
|
||||||
|
env:
|
||||||
|
- name: ISSUE_CORE_API_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: issue-core-runtime
|
||||||
|
key: ISSUE_CORE_API_KEY
|
||||||
|
command: ["/bin/sh", "-ceu"]
|
||||||
|
args:
|
||||||
|
- |
|
||||||
|
curl -fsS -X POST "http://issue-core:8765/issues/" -H "Authorization: Bearer ${ISSUE_CORE_API_KEY}" -H "Content-Type: application/json" --data '{"title":"issue-core railiance01 smoke","description":"GitOps smoke created by the issue-core deployment runbook.","target_repo":"coulomb/markitect-main","priority":"low","labels":["smoke","issue-core"],"source_type":"rule","source_id":"issue-core-gitops-smoke","triggering_event_id":"scheduled","activity_definition_id":"issue-core-gitops-smoke"}'
|
||||||
|
YAML
|
||||||
|
kubectl -n issue-core wait --for=condition=complete job/issue-core-smoke --timeout=90s
|
||||||
|
kubectl -n issue-core logs job/issue-core-smoke
|
||||||
|
```
|
||||||
|
|
||||||
|
Acceptance evidence is HTTP 201 plus a response body containing `issue_id`,
|
||||||
|
`backend: "gitea"`, and an `issue_url` for cluster Gitea.
|
||||||
|
|
||||||
|
Cleanup:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl -n issue-core delete job issue-core-smoke
|
||||||
|
```
|
||||||
|
|
||||||
|
## Activity-core handoff
|
||||||
|
|
||||||
|
After issue-core is Ready and the shared `ISSUE_CORE_API_KEY` is available to
|
||||||
|
activity-core from the same approved OpenBao source:
|
||||||
|
|
||||||
|
- Set `ISSUE_CORE_URL=http://issue-core.issue-core.svc.cluster.local:8765`.
|
||||||
|
- Set `ISSUE_SINK_TYPE=rest`.
|
||||||
|
- Inject the same `ISSUE_CORE_API_KEY` into the activity-core worker.
|
||||||
|
- Keep cron-triggered emissions explicit: `triggering_event_id` may be a stable
|
||||||
|
non-empty scheduler key such as `scheduled`; event-driven emissions should
|
||||||
|
continue to send the event UUID.
|
||||||
|
|
||||||
|
Verify by running an activity-core emission and confirming that issue-core
|
||||||
|
returns HTTP 201 and creates a Gitea issue.
|
||||||
82
integration/gitea-backend.integration.yaml
Normal file
82
integration/gitea-backend.integration.yaml
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
schema_version: open-reuse.integration.v0.1
|
||||||
|
id: issue-core-gitea
|
||||||
|
name: issue-core Gitea Backend
|
||||||
|
description: >
|
||||||
|
Pluggable remote backend that maps the issue-core unified task model onto the
|
||||||
|
Gitea issues API for cross-repo task landing and synchronization.
|
||||||
|
status: registered
|
||||||
|
owner: issue-core
|
||||||
|
|
||||||
|
local:
|
||||||
|
repo: issue-core
|
||||||
|
path: integration/gitea-backend.integration.yaml
|
||||||
|
system: issue-core
|
||||||
|
|
||||||
|
upstream:
|
||||||
|
name: Gitea
|
||||||
|
project_url: https://github.com/go-gitea/gitea
|
||||||
|
homepage: https://about.gitea.com/
|
||||||
|
version_policy: gitea-api-v1
|
||||||
|
monitor:
|
||||||
|
releases: true
|
||||||
|
tags: true
|
||||||
|
security_advisories: true
|
||||||
|
license_changes: true
|
||||||
|
|
||||||
|
reuse:
|
||||||
|
primary_reuse_mode: adapter
|
||||||
|
secondary_reuse_modes:
|
||||||
|
- plugin
|
||||||
|
risk_level: medium
|
||||||
|
rationale: >
|
||||||
|
Gitea REST API is wrapped behind the RemoteBackend interface; local task
|
||||||
|
lifecycle semantics remain stable across backend swaps.
|
||||||
|
|
||||||
|
boundary:
|
||||||
|
type: adapter
|
||||||
|
local_adapter: issue_core.backends.gitea.backend.GiteaBackend
|
||||||
|
local_interface: issue_core.core.interfaces.RemoteBackend
|
||||||
|
reused_surface: Gitea /api/v1 issues, labels, milestones, comments
|
||||||
|
contracts:
|
||||||
|
- issue-core.backend.v1
|
||||||
|
fragility_points:
|
||||||
|
- Gitea API field changes
|
||||||
|
- issue state mapping differences
|
||||||
|
- pagination and rate-limit behavior
|
||||||
|
- authentication token scopes
|
||||||
|
|
||||||
|
validation:
|
||||||
|
harness: python3 -m pytest tests/test_gitea_backend.py
|
||||||
|
skip_without_runtime: true
|
||||||
|
checks:
|
||||||
|
- API client request shaping
|
||||||
|
- issue state mapping
|
||||||
|
- error handling for rate limits
|
||||||
|
policy: required-before-update
|
||||||
|
|
||||||
|
update_policy:
|
||||||
|
default_action: require-maintainer-review
|
||||||
|
auto_eligible: false
|
||||||
|
|
||||||
|
risks:
|
||||||
|
sensitivity:
|
||||||
|
- Gitea API breaking changes
|
||||||
|
- authentication model changes
|
||||||
|
- rate-limit policy changes
|
||||||
|
- license changes
|
||||||
|
escalation_triggers:
|
||||||
|
- validation failure
|
||||||
|
- Gitea major release
|
||||||
|
- production sync errors
|
||||||
|
|
||||||
|
maintenance:
|
||||||
|
maintainers:
|
||||||
|
- issue-core
|
||||||
|
escalation_conditions:
|
||||||
|
- Gitea API compatibility failure
|
||||||
|
- validation failure
|
||||||
|
- production backend sync regression
|
||||||
|
|
||||||
|
audit:
|
||||||
|
registered_at: "2026-06-24"
|
||||||
|
registered_by: open-reuse
|
||||||
@@ -19,6 +19,6 @@ Supported Backends:
|
|||||||
- Future: GitHub, GitLab, JIRA, Redmine
|
- Future: GitHub, GitLab, JIRA, Redmine
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__version__ = "0.2.0"
|
__version__ = "0.2.1"
|
||||||
__author__ = "Coulomb / MarkiTect Project"
|
__author__ = "Coulomb / MarkiTect Project"
|
||||||
__description__ = "Authoritative task lifecycle manager with plugin architecture"
|
__description__ = "Authoritative task lifecycle manager with plugin architecture"
|
||||||
|
|||||||
@@ -2,14 +2,12 @@
|
|||||||
Pydantic schemas for the issue-core REST API.
|
Pydantic schemas for the issue-core REST API.
|
||||||
|
|
||||||
The TaskIngestionRequest schema matches activity-core's IssueSink TaskSpec
|
The TaskIngestionRequest schema matches activity-core's IssueSink TaskSpec
|
||||||
payload exactly. See:
|
payload. See:
|
||||||
- SCOPE.md "TaskSpec payload" section
|
- SCOPE.md "TaskSpec payload" section
|
||||||
- activity-core docs/adr/adr-001-event-bridge-architecture.md
|
- activity-core docs/adr/adr-001-event-bridge-architecture.md
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import List, Literal, Optional
|
from typing import List, Literal, Optional
|
||||||
from uuid import UUID
|
|
||||||
|
|
||||||
from pydantic import BaseModel, ConfigDict, Field
|
from pydantic import BaseModel, ConfigDict, Field
|
||||||
|
|
||||||
|
|
||||||
@@ -31,7 +29,14 @@ class TaskIngestionRequest(BaseModel):
|
|||||||
due_in_days: Optional[int] = Field(default=None, ge=0)
|
due_in_days: Optional[int] = Field(default=None, ge=0)
|
||||||
source_type: SourceType
|
source_type: SourceType
|
||||||
source_id: str = Field(..., min_length=1)
|
source_id: str = Field(..., min_length=1)
|
||||||
triggering_event_id: UUID
|
triggering_event_id: str = Field(
|
||||||
|
...,
|
||||||
|
min_length=1,
|
||||||
|
description=(
|
||||||
|
"Activity event UUID, or a stable scheduler/source key when no "
|
||||||
|
"event row exists."
|
||||||
|
),
|
||||||
|
)
|
||||||
activity_definition_id: str = Field(..., min_length=1)
|
activity_definition_id: str = Field(..., min_length=1)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -195,9 +195,19 @@ class GiteaBackend(RemoteBackend, SyncableBackend):
|
|||||||
if issue.milestone:
|
if issue.milestone:
|
||||||
data['milestone'] = int(issue.milestone.backend_id) if issue.milestone.backend_id else None
|
data['milestone'] = int(issue.milestone.backend_id) if issue.milestone.backend_id else None
|
||||||
|
|
||||||
# Convert labels
|
# Gitea expects numeric label IDs on issue create/update. Name-only
|
||||||
if issue.labels:
|
# labels are preserved in issue-core metadata but omitted from the API
|
||||||
data['labels'] = [label.name for label in issue.labels]
|
# payload until a label-resolution step exists.
|
||||||
|
label_ids = []
|
||||||
|
for label in issue.labels:
|
||||||
|
if not label.backend_id:
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
label_ids.append(int(label.backend_id))
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
continue
|
||||||
|
if label_ids:
|
||||||
|
data['labels'] = label_ids
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ data:
|
|||||||
"type": "gitea",
|
"type": "gitea",
|
||||||
"base_url": "http://gitea-http.default.svc.cluster.local:3000",
|
"base_url": "http://gitea-http.default.svc.cluster.local:3000",
|
||||||
"owner": "coulomb",
|
"owner": "coulomb",
|
||||||
"repo": "markitect_project",
|
"repo": "markitect-main",
|
||||||
"token": "__FROM_ENV__"
|
"token": "__FROM_ENV__"
|
||||||
},
|
},
|
||||||
"default": "markitect"
|
"default": "markitect"
|
||||||
|
|||||||
@@ -67,5 +67,6 @@ spec:
|
|||||||
allowPrivilegeEscalation: false
|
allowPrivilegeEscalation: false
|
||||||
readOnlyRootFilesystem: false
|
readOnlyRootFilesystem: false
|
||||||
runAsNonRoot: true
|
runAsNonRoot: true
|
||||||
|
runAsUser: 10001
|
||||||
capabilities:
|
capabilities:
|
||||||
drop: ["ALL"]
|
drop: ["ALL"]
|
||||||
|
|||||||
@@ -112,6 +112,30 @@ def test_ingest_creates_issue_with_x_api_key(client, valid_payload):
|
|||||||
assert response.status_code == 201, response.text
|
assert response.status_code == 201, response.text
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.unit
|
||||||
|
def test_ingest_accepts_non_uuid_triggering_event_id(client, valid_payload, tmp_issue_store):
|
||||||
|
valid_payload["triggering_event_id"] = "scheduled"
|
||||||
|
response = client.post(
|
||||||
|
"/issues/",
|
||||||
|
json=valid_payload,
|
||||||
|
headers={"Authorization": f"Bearer {API_KEY}"},
|
||||||
|
)
|
||||||
|
assert response.status_code == 201, response.text
|
||||||
|
issue_id = response.json()["issue_id"]
|
||||||
|
|
||||||
|
from issue_core.backends.local import LocalSQLiteBackend
|
||||||
|
|
||||||
|
backend = LocalSQLiteBackend()
|
||||||
|
backend.connect({"type": "local", "db_path": str(tmp_issue_store / "issues.db")})
|
||||||
|
try:
|
||||||
|
stored = backend.get_issue(issue_id)
|
||||||
|
assert stored is not None
|
||||||
|
ingestion = stored.sync_metadata.get("ingestion") or {}
|
||||||
|
assert ingestion["triggering_event_id"] == "scheduled"
|
||||||
|
finally:
|
||||||
|
backend.disconnect()
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.unit
|
@pytest.mark.unit
|
||||||
def test_ingest_rejects_invalid_payload(client):
|
def test_ingest_rejects_invalid_payload(client):
|
||||||
bad = {"title": "no required fields"}
|
bad = {"title": "no required fields"}
|
||||||
|
|||||||
@@ -6,8 +6,10 @@ These tests ensure the Gitea backend works correctly with the API.
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
import json
|
import json
|
||||||
|
from datetime import datetime, timezone
|
||||||
from unittest.mock import Mock, patch, MagicMock
|
from unittest.mock import Mock, patch, MagicMock
|
||||||
from issue_core.backends.gitea.backend import GiteaBackend, GiteaAPIError
|
from issue_core.backends.gitea.backend import GiteaBackend, GiteaAPIError
|
||||||
|
from issue_core.core.models import Issue, IssueState, Label
|
||||||
|
|
||||||
|
|
||||||
class TestGiteaBackend:
|
class TestGiteaBackend:
|
||||||
@@ -96,6 +98,29 @@ class TestGiteaBackend:
|
|||||||
called_url = mock_request.call_args[1]['url'] if 'url' in mock_request.call_args[1] else mock_request.call_args[0][1]
|
called_url = mock_request.call_args[1]['url'] if 'url' in mock_request.call_args[1] else mock_request.call_args[0][1]
|
||||||
assert called_url == 'https://git.example.com/api/v1/repos/owner/repo'
|
assert called_url == 'https://git.example.com/api/v1/repos/owner/repo'
|
||||||
|
|
||||||
|
def test_gitea_payload_omits_name_only_labels(self):
|
||||||
|
"""Gitea issue payloads only include numeric label IDs."""
|
||||||
|
now = datetime.now(timezone.utc)
|
||||||
|
issue = Issue(
|
||||||
|
id="",
|
||||||
|
number=0,
|
||||||
|
title="Test issue",
|
||||||
|
description="Test description",
|
||||||
|
state=IssueState.OPEN,
|
||||||
|
created_at=now,
|
||||||
|
updated_at=now,
|
||||||
|
labels=[
|
||||||
|
Label(name="priority:low"),
|
||||||
|
Label(name="source:rule", backend_id="not-a-number"),
|
||||||
|
Label(name="existing", backend_id="42"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
payload = self.backend._unified_issue_to_gitea(issue)
|
||||||
|
|
||||||
|
assert payload["labels"] == [42]
|
||||||
|
assert payload["title"] == "Test issue"
|
||||||
|
|
||||||
@patch('issue_core.backends.gitea.backend.requests.Session')
|
@patch('issue_core.backends.gitea.backend.requests.Session')
|
||||||
def test_test_connection_success(self, mock_session_class):
|
def test_test_connection_success(self, mock_session_class):
|
||||||
"""Test test_connection method works correctly."""
|
"""Test test_connection method works correctly."""
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
id: ISSC-WP-0001
|
id: ISSC-WP-0001
|
||||||
type: workplan
|
type: workplan
|
||||||
domain: custodian
|
domain: infotech
|
||||||
repo: issue-core
|
repo: issue-core
|
||||||
status: done
|
status: done
|
||||||
state_hub_workstream_id: 1135fc1d-1f46-4e35-886d-04cc3b8050b6
|
state_hub_workstream_id: 1135fc1d-1f46-4e35-886d-04cc3b8050b6
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
id: ISSUE-WP-0002
|
id: ISSUE-WP-0002
|
||||||
type: workplan
|
type: workplan
|
||||||
title: "Publish issue-core to Gitea PyPI"
|
title: "Publish issue-core to Gitea PyPI"
|
||||||
domain: custodian
|
domain: infotech
|
||||||
repo: issue-core
|
repo: issue-core
|
||||||
status: finished
|
status: finished
|
||||||
owner: codex
|
owner: codex
|
||||||
|
|||||||
@@ -2,13 +2,13 @@
|
|||||||
id: ISSUE-WP-0003
|
id: ISSUE-WP-0003
|
||||||
type: workplan
|
type: workplan
|
||||||
title: "Deploy issue-core as a service on railiance01 (ArgoCD GitOps pilot)"
|
title: "Deploy issue-core as a service on railiance01 (ArgoCD GitOps pilot)"
|
||||||
domain: custodian
|
domain: infotech
|
||||||
repo: issue-core
|
repo: issue-core
|
||||||
status: active
|
status: active
|
||||||
owner: claude
|
owner: claude
|
||||||
topic_slug: custodian
|
topic_slug: custodian
|
||||||
created: "2026-06-19"
|
created: "2026-06-19"
|
||||||
updated: "2026-06-19"
|
updated: "2026-06-23"
|
||||||
state_hub_workstream_id: "896ace77-21b3-450b-8fb7-254aefc8c570"
|
state_hub_workstream_id: "896ace77-21b3-450b-8fb7-254aefc8c570"
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -52,6 +52,15 @@ declarative Application and turning on the idle GitOps capability.
|
|||||||
registry) → `rsync` manifests → `kubectl apply` (see
|
registry) → `rsync` manifests → `kubectl apply` (see
|
||||||
`activity-core/k8s/railiance/README.md`).
|
`activity-core/k8s/railiance/README.md`).
|
||||||
|
|
||||||
|
## Repo-side progress (2026-06-23)
|
||||||
|
|
||||||
|
- Added `docs/argocd-gitops.md` with the issue-core GitOps runbook, including
|
||||||
|
image publish, ArgoCD sync checks, OpenBao/ExternalSecret contract, health
|
||||||
|
probe, authenticated ingestion smoke, cleanup, and activity-core handoff.
|
||||||
|
- Broadened `POST /issues/` so `triggering_event_id` accepts any non-empty
|
||||||
|
traceability string. Event-driven activity-core paths can still send UUIDs;
|
||||||
|
scheduled/cron paths may now send a stable key such as `scheduled`.
|
||||||
|
|
||||||
## Decisions
|
## Decisions
|
||||||
|
|
||||||
- **Deployment method = ArgoCD GitOps** (operator decision 2026-06-19).
|
- **Deployment method = ArgoCD GitOps** (operator decision 2026-06-19).
|
||||||
@@ -136,7 +145,7 @@ workload manifests into the layout platform defines.
|
|||||||
|
|
||||||
```task
|
```task
|
||||||
id: ISSUE-WP-0003-T03
|
id: ISSUE-WP-0003-T03
|
||||||
status: in_progress
|
status: progress
|
||||||
priority: high
|
priority: high
|
||||||
state_hub_task_id: "38887dd6-0988-4ad1-bc6b-2a1b8839829f"
|
state_hub_task_id: "38887dd6-0988-4ad1-bc6b-2a1b8839829f"
|
||||||
```
|
```
|
||||||
@@ -156,7 +165,7 @@ state_hub_task_id: "38887dd6-0988-4ad1-bc6b-2a1b8839829f"
|
|||||||
|
|
||||||
```task
|
```task
|
||||||
id: ISSUE-WP-0003-T04
|
id: ISSUE-WP-0003-T04
|
||||||
status: todo
|
status: wait
|
||||||
priority: high
|
priority: high
|
||||||
state_hub_task_id: "ad52527f-6222-4c11-9284-d8a3ed3b49ad"
|
state_hub_task_id: "ad52527f-6222-4c11-9284-d8a3ed3b49ad"
|
||||||
```
|
```
|
||||||
@@ -171,12 +180,15 @@ state_hub_task_id: "ad52527f-6222-4c11-9284-d8a3ed3b49ad"
|
|||||||
- Never write the value to Git, manifests, State Hub, or logs.
|
- Never write the value to Git, manifests, State Hub, or logs.
|
||||||
- Verify: both pods resolve a non-empty key; auth round-trip (401 without,
|
- Verify: both pods resolve a non-empty key; auth round-trip (401 without,
|
||||||
201 with).
|
201 with).
|
||||||
|
- Current wait reason: requires railiance-platform/OpenBao operator action to
|
||||||
|
confirm/provision the canonical path and `ClusterSecretStore`;
|
||||||
|
issue-core records only the Secret contract and non-secret verification steps.
|
||||||
|
|
||||||
## In-cluster backend config (cluster Gitea / markitect)
|
## In-cluster backend config (cluster Gitea / markitect)
|
||||||
|
|
||||||
```task
|
```task
|
||||||
id: ISSUE-WP-0003-T05
|
id: ISSUE-WP-0003-T05
|
||||||
status: in_progress
|
status: progress
|
||||||
priority: medium
|
priority: medium
|
||||||
state_hub_task_id: "10923f1e-050d-4f3e-980e-b061fef5f33a"
|
state_hub_task_id: "10923f1e-050d-4f3e-980e-b061fef5f33a"
|
||||||
```
|
```
|
||||||
@@ -195,7 +207,7 @@ the cluster Gitea (markitect) backend.
|
|||||||
|
|
||||||
```task
|
```task
|
||||||
id: ISSUE-WP-0003-T06
|
id: ISSUE-WP-0003-T06
|
||||||
status: todo
|
status: progress
|
||||||
priority: high
|
priority: high
|
||||||
state_hub_task_id: "96b14cdb-364f-4eab-a80e-dd8b3859c694"
|
state_hub_task_id: "96b14cdb-364f-4eab-a80e-dd8b3859c694"
|
||||||
```
|
```
|
||||||
@@ -207,11 +219,10 @@ state_hub_task_id: "96b14cdb-364f-4eab-a80e-dd8b3859c694"
|
|||||||
once issue-core is Ready.
|
once issue-core is Ready.
|
||||||
- Inject `ISSUE_CORE_API_KEY` into the activity-core worker from the same
|
- Inject `ISSUE_CORE_API_KEY` into the activity-core worker from the same
|
||||||
OpenBao secret (T04).
|
OpenBao secret (T04).
|
||||||
- **Contract gap:** issue-core requires `triggering_event_id` as a UUID;
|
- [x] **Contract gap closed on the issue-core side:** `POST /issues/` now
|
||||||
activity-core cron paths may send non-UUID keys (e.g. `"scheduled"`).
|
accepts `triggering_event_id` as a non-empty traceability string, so
|
||||||
Event-driven emission with real event UUIDs works (the `str()` guard in
|
event-driven paths can send UUIDs and cron paths can send stable keys such as
|
||||||
`issue_sink.py`, commit f05c56e, handles UUID objects). Align schemas before
|
`"scheduled"`.
|
||||||
enabling `rest` for cron-triggered rules.
|
|
||||||
- Verify: an activity-core run emits a task that lands in cluster Gitea via
|
- Verify: an activity-core run emits a task that lands in cluster Gitea via
|
||||||
issue-core.
|
issue-core.
|
||||||
|
|
||||||
@@ -219,7 +230,7 @@ state_hub_task_id: "96b14cdb-364f-4eab-a80e-dd8b3859c694"
|
|||||||
|
|
||||||
```task
|
```task
|
||||||
id: ISSUE-WP-0003-T07
|
id: ISSUE-WP-0003-T07
|
||||||
status: todo
|
status: progress
|
||||||
priority: medium
|
priority: medium
|
||||||
state_hub_task_id: "8d853b8e-cfca-441d-b817-0a29e37bd66e"
|
state_hub_task_id: "8d853b8e-cfca-441d-b817-0a29e37bd66e"
|
||||||
```
|
```
|
||||||
@@ -229,8 +240,8 @@ state_hub_task_id: "8d853b8e-cfca-441d-b817-0a29e37bd66e"
|
|||||||
- ArgoCD Application Synced/Healthy; issue-core Pod Ready; Service reachable
|
- ArgoCD Application Synced/Healthy; issue-core Pod Ready; Service reachable
|
||||||
cluster-internal.
|
cluster-internal.
|
||||||
- activity-core → issue-core emission returns 201 and creates a Gitea issue.
|
- activity-core → issue-core emission returns 201 and creates a Gitea issue.
|
||||||
- Document the GitOps runbook (image build/push, ArgoCD sync, secret rotation,
|
- [x] Document the GitOps runbook (image build/push, ArgoCD sync, secret
|
||||||
rollback) in `docs/`.
|
contract, smoke, activity-core handoff) in `docs/argocd-gitops.md`.
|
||||||
- Emit an `add_progress_event` milestone to the hub on completion.
|
- Emit an `add_progress_event` milestone to the hub on completion.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
Reference in New Issue
Block a user