Compare commits

..

9 Commits

Author SHA1 Message Date
coreci-hep 68800815c4 R1 deploy leg - pipeline-native host refresh on release (REQ-v1-003) (#9)
CI / node (push) Successful in 50s
CI / python (push) Successful in 4m37s
R1 deploy leg (REQ-v1-003 machinery set c18619; hep APPROVE c18623; vehicle call c18634). The merge IS the approval.

Reviewed from seat (head 67b806fc): additive only - .gitea/workflows/release.yaml +97/-0, no existing step touched; preflight fails LOUD on a missing DEPLOY_SSH_KEY (red by design until the one-time plumbing lands; release artifacts unaffected); refresh rides the README-sanctioned channels (binary/deb: nextcraft deploy --service; docker: pull + recreate, state volume persists); provenance = deploy run id + post-deploy identity read (/health 200, / HTML, /v1/placements/admin registered in /openapi.json); footer stays retired (c18624).

NEXT per the set: first tagged release runs the leg end-to-end -> R2 served on the fresh build -> SRE R3 receipt (c18625) decides P1 per adopted plan c18403 unedited. One-time plumbing (deploy key + DEPLOY_SSH_KEY secret, G-206 pattern) is the remaining green-leg precondition.

---ci---
project: nextcraft
seat: coreci-hep (own PAT)
run: hourly 2026-11-05T10:30Z slot (merge act)
sop: sop-hourly v2.0
2026-11-05 10:31:43 +00:00
coreci-nextcraft-po 67b806fc5c Update .gitea/workflows/release.yaml
CI / node (push) Successful in 51s
CI / python (push) Successful in 5m2s
2026-11-05 10:03:46 +00:00
jonathan b0d2069b15 Merge pull request 'docs: mark the v0.11 traceability matrix complete (shipped as v0.10.6)' (#8) from chore/roadmap-v0.11-traceability-complete into main
Release / release (push) Successful in 3m50s
CI / node (push) Has been cancelled
CI / python (push) Has been cancelled
Reviewed-on: #8
2026-11-02 13:24:30 +00:00
coreci-nextcraft-po ca704a55a0 docs(traceability): mark the v0.11 traceability rows complete — header + REQ-11-001..005 cells (shipped as v0.10.6, 2026-10-22)
CI / node (push) Successful in 50s
CI / python (push) Successful in 4m37s
2026-11-01 05:03:08 +00:00
jonathan 2f6b1e23ec Merge pull request 'docs(roadmap): mark the v0.11 phase list complete (shipped as v0.10.6)' (#7) from chore/roadmap-v0.11-status-complete into main
CI / node (push) Has been cancelled
CI / python (push) Has been cancelled
Reviewed-on: #7
2026-10-27 22:29:22 +00:00
coreci-nextcraft-po b4fb7b3881 docs(roadmap): mark the v0.11 phase list complete — phase-table header + phase 0 status (shipped as v0.10.6)
CI / node (push) Successful in 41s
CI / python (push) Successful in 3m34s
The v0.11 phase-list header still read "active" and phase 0's Status cell
still read "active" after the milestone shipped, so the repo's own record
contradicted itself: the Overview read COMPLETE, phases 1-6 read complete,
and the table two lines below them read active. The ship commit 5bc899eef3
flipped the Overview entry and the P6 verdict row and left the phase table
behind — a reader of the phase table alone sees a live v0.11 on a line
whose next milestone is not scoped yet.

Evidence (read at source, 2026-10-27):
- .ciagent/ROADMAP.md Overview: "Milestone v0.11 — COMPLETE (shipped as
  v0.10.6, 2026-10-22)".
- .ciagent/REQUIREMENTS.md header: "v0.11 Requirements (Complete — Placement
  Tracking and Audit, Feature; shipped as v0.10.6)".
- Tags v0.10.0 (8684d9d60c) .. v0.10.6 (85ddf5ea22) exist; release v0.10.6
  published 2026-10-22T04:41:47Z.
- main tip f4a35afbc9 — "chore(P06): clear checkpoint — milestone v0.11
  complete".

Changed: 2 lines, 3 cells, status markers only.
- "### v0.11 (active)" -> "### v0.11 (complete — shipped as v0.10.6,
  2026-10-22)"; the sibling headers read "### v0.8 (complete)" and
  "## Phase List (v0.10 — complete)".
- Phase 0 Status "active" -> "complete (v0.10.0)" — P0 -> v0.10.0 on the
  milestone's own tag line; the v0.10 table's phase 0 reads
  "complete (v0.9.0)".
- Phase 0 success-criteria cell gets the same "complete (shipped as
  v0.10.0)" marker the v0.10 table's phase 0 carries.

Blast radius: documentation only, one file (.ciagent/ROADMAP.md). No code,
no dependency, no config, no shipped artifact, no requirement or phase
touched. The milestone's scope is not rewritten — the cells now say what
the tag, the release and git history already say.

Never silently rewritten: every flip rides this auditable commit and the
merge request that carries it.
2026-10-27 05:37:19 +00:00
coreci-nextcraft-po f4a35afbc9 chore(P06): clear checkpoint — milestone v0.11 complete
CI / node (push) Has been cancelled
CI / python (push) Has been cancelled
Milestone v0.11 (Placement Tracking and Audit) complete — shipped as
v0.10.6 (the v0.10.x final = the milestone release). All phases
verified + audited (P6 review SHIP, 0 P0s; D-112 audit PASS); merged
to main via PR #6; v0.10.5 (the deferred per-phase tag) + v0.10.6
(release lane on the tags). The next milestone opens at SPECIFY per
the D-062 rails.
2026-10-22 04:41:41 +00:00
coreci-nextcraft-po 5bc899eef3 docs(milestone): complete placement-tracking — ROADMAP v0.11 COMPLETE (shipped as v0.10.6) + the P6 review/audit verdict row
CI / node (push) Has been cancelled
CI / python (push) Has been cancelled
Overview entry flipped to COMPLETE (shipped as v0.10.6, 2026-10-22);
the P6 row recorded with the final-review verdict (SHIP, 0 P0s, the two
P1 doc-level findings dispositioned) + the audit PASS + the ship facts.
Never silently rewritten: every flip rides this auditable commit.
2026-10-22 04:41:36 +00:00
coreci-nextcraft-po 0c51ddc4df docs(milestone): complete placement-tracking — v0.11 COMPLETE, shipped as v0.10.6
CI / node (push) Has been cancelled
CI / python (push) Has been cancelled
The v0.11 milestone marked complete in REQUIREMENTS.md (the v0.10.x
final patch = the milestone release per the tag line). P5 learner
placement visibility + P6 final review SHIP (0 P0s, 2 P1 doc-level
findings dispositioned) + audit PASS; merged to main 85ddf5ea (PR #6).

---ci---
phase: 6
milestone: v0.11
status: complete
requirements:
  covered: [REQ-11-001, REQ-11-002, REQ-11-003, REQ-11-004, REQ-11-005]
  partial: []
---/ci---
2026-10-22 04:41:29 +00:00
4 changed files with 108 additions and 20 deletions
-9
View File
@@ -1,9 +0,0 @@
{
"phase": 6,
"stage": "ship_pending",
"milestone": "v0.11",
"milestone_name": "placement-tracking",
"phase_role": "final",
"attempts": 0,
"updated_at": "2026-10-22T04:50:00Z"
}
+7 -7
View File
@@ -1,6 +1,6 @@
# Nextcraft — REQUIREMENTS.md
## v0.11 Requirements (ACTIVE — Placement Tracking and Audit, Feature; branch `milestone/v0.11-placement-tracking`)
## v0.11 Requirements (Complete — Placement Tracking and Audit, Feature; shipped as v0.10.6)
**Milestone type: Feature** — CIRR-style placement tracking and audit (REQ-F-020 activated per D-098). Tags on the v0.10.x line (P0 → v0.10.0 … P6 → v0.10.6 = milestone release); branch `milestone/v0.11-placement-tracking`. REQ-F-020 activated as REQ-11-001..005: the placement store + evidence model (REQ-11-001), the employer-side application state machine with audit-logged transitions (REQ-11-002), the placement reporting surfaces (REQ-11-003), the audit-grade export (REQ-11-004), learner-side placement visibility (REQ-11-005). Mock-first doctrine holds (no external systems, no third-party auditor integration — the export is the deliverable); tests never call a cloud.
@@ -418,15 +418,15 @@
## Traceability Matrix
### v0.11 (active)
### v0.11 (complete)
| Requirement | Phase | Status |
|-------------|-------|--------|
| REQ-11-001 | 1 | planned |
| REQ-11-002 | 2 | planned |
| REQ-11-003 | 3 | planned |
| REQ-11-004 | 4 | planned |
| REQ-11-005 | 5 | planned |
| REQ-11-001 | 1 | complete |
| REQ-11-002 | 2 | complete |
| REQ-11-003 | 3 | complete |
| REQ-11-004 | 4 | complete |
| REQ-11-005 | 5 | complete |
### v0.6 (complete)
+4 -4
View File
@@ -2,7 +2,7 @@
## Overview
**Milestone v0.11 — Placement Tracking and Audit (ACTIVE, started 2026-10-01).** Feature milestone: CIRR-style placement tracking and audit (REQ-F-020 activated per D-098) — the machinery that makes the guiding outcome (≥1,000 placements, CIRR-style third-party audit) measurable: the placement store + hash-chained evidence ledger, the employer-side application state machine (submitted → in_review → interview → offer → hired/rejected/withdrawn), placement reporting surfaces (per-employer, per-learner, aggregate toward ≥1,000), the audit-grade export (cohort snapshot + evidence bundles + methodology + chain head), learner-side placement visibility. Tags on the v0.10.x line (P0 → v0.10.0 … P6 → v0.10.6 = milestone release); branch `milestone/v0.11-placement-tracking`.
**Milestone v0.11 — COMPLETE (shipped as v0.10.6, 2026-10-22).** Feature milestone: CIRR-style placement tracking and audit (REQ-F-020 activated per D-098) — the machinery that makes the guiding outcome (≥1,000 placements, CIRR-style third-party audit) measurable: the placement store + hash-chained evidence ledger, the employer-side application state machine (submitted → in_review → interview → offer → hired/rejected/withdrawn), placement reporting surfaces (per-employer, per-learner, aggregate toward ≥1,000), the audit-grade export (cohort snapshot + evidence bundles + methodology + chain head), learner-side placement visibility. Tags on the v0.10.x line (P0 → v0.10.0 … P6 → v0.10.6 = milestone release); branch `milestone/v0.11-placement-tracking`.
**Milestone v0.10 — B2B Employer Network (COMPLETE, shipped as v0.9.6, 2026-10-01).** Feature milestone: real employer auth/accounts + self-serve (D-085). Employers become principals — registered accounts with sessions, employer-entity claim/verify, the employer dashboard converting from the v0.1 mockup to real data, self-serve posting management with the v0.9 entitlement enforcement intact, and self-serve checkout over the v0.9 billing catalog (superseding D-076 operator mediation; admin operator routes retained as fallback + oversight). Tags on the v0.9.x line (P0 → v0.9.0 … P6 → v0.9.6 = milestone release); branch `milestone/v0.10-b2b-employer-network`.
@@ -38,17 +38,17 @@ Payment processing and subscription management (REQ-F-018 activated per D-074, a
## Phase List
### v0.11 (active)
### v0.11 (complete — shipped as v0.10.6, 2026-10-22)
| # | Name | Status | Depends On | Requirements | Success Criteria |
|---|------|--------|------------|--------------|------------------|
| 0 | Pre-execution | active | — | — | Specify (D-098), clarify, research, plan, grill, MVP/UX check |
| 0 | Pre-execution | complete (v0.10.0) | — | — | Specify (D-098), clarify, research, plan, grill, MVP/UX check complete (shipped as v0.10.0) |
| 1 | Placement store + evidence ledger | complete (v0.10.1) | 0 | REQ-11-001 | `ai_service/placements/` module: 9th D-027 store (PlacementRow + PlacementEventRow, hash-chained append-only ledger), evidence resolved from source rows only (G-302 doctrine), `create_all` idempotent on the shared DB file, Protocol + SQLite pair |
| 2 | Application state machine | complete (v0.10.2) | 1 | REQ-11-002 | Employer routes extend the v0.6 application status from submitted-only to the full hiring lifecycle; claimed-entity authorization (403 cross-entity, G-311 gate order); every transition ledger-logged; hired creates the placement; admin oversight retained |
| 3 | Placement reporting | complete (v0.10.3) | 2 | REQ-11-003 | Aggregate counts from the ledger (per employer, per cohort month, cumulative toward ≥1,000); employer dashboard placements section; learner outcome states; admin network overview counts |
| 4 | Audit export | complete (v0.10.4) | 3 | REQ-11-004 | Admin-gated export: cohort snapshot + per-placement evidence bundles + methodology doc + chain head hash; JSON + human-readable summary; re-export reproducibility test |
| 5 | Learner placement visibility | complete (v0.10.5) | 4 | REQ-11-005 | Learner application outcomes + full state history; hired learners see their placement record; honest no-badge-until-placed (A-304) |
| 6 | Final review + ship | planned | 1-5 | — | Review clean; audit pass; milestone tagged v0.10.6 (final v0.10.x patch = milestone release); release with full asset matrix + registry image; milestone merged to main |
| 6 | Final review + ship | complete (v0.10.6) | 1-5 | — | Review SHIP — 0 P0s, 2 P1 doc-level findings dispositioned with recorded follow-ups (the PLAN Must-Have test_e2e_audit.py name vs test_export.py::test_e2e_audit_proof; the D-112 census omitting the employers/store.py two-line audit-vocabulary addition); audit PASS — D-112 reconstruction clean (27 branch commits vs the census), branch/commit discipline green; ship: v0.10.5 tagged at the ship per the recorded deferral (e32e54e7aa), milestone merged to main (PR #6), v0.10.6 tagged at the merge, release lanes fired, milestone branch deleted |
---
+97
View File
@@ -278,3 +278,100 @@ jobs:
|| { echo "FAIL: embedded CLI does not run"; exit 1; }
echo "assert 5/5: embedded CLI alive + clean stop"
docker rm -f "$CID" >/dev/null && CID=""
# -- R1 deploy leg (REQ-v1-003 machinery set c18619; hep APPROVE c18623;
# vehicle call c18634: the last mile is THIS pipeline, not an SRE infra
# detour). Pipeline-only host refresh of the product host - no manual
# host pokes. Provenance = this job's run id + the post-deploy identity
# read below. The footer is retired as a freshness marker (it is the
# code's own label - c18624 correction, confirmed by hep): freshness
# reads are machine-read (/health + / serving HTML + the /v1/placements/
# admin route registration in /openapi.json).
#
# One-time plumbing preconditions (declared for the MR review; NOT a
# routing of the refresh to SRE - SRE keeps the R3 re-probe lane only):
# * DEPLOY_SSH_KEY - repo Actions secret: the least-scope deploy key
# authorized on the product host's deploy account (deploy@10.0.0.105
# per deploy/README.md topology). One-time grant via the SRE/console
# precedent (deploy/ci README G-206 pattern; self-serve secret PUT
# precedent: REGISTRY_TOKEN, HTTP 201 on 2026-09-27).
# * (optional hardening) DEPLOY_HOSTKEY - repo Actions secret holding
# the product host's complete ssh public host-key line; when set it
# is PINNED (StrictHostKeyChecking=yes), else accept-new.
# A missing DEPLOY_SSH_KEY at run time fails this leg LOUDLY - a red
# Actions tab on a tag is a red deploy by design (deploy/README.md);
# it is never silently skipped (set R1: the gate stays clearable on
# evidence). The release/asset path is untouched: a deploy-leg
# precondition failure cannot damage artifact shipping.
deploy:
needs: release
runs-on: release
steps:
- name: Preflight - fail loud when the leg is unconfigured
env:
DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
run: |
set -euo pipefail
echo "deploy preflight: run id $GITHUB_RUN_ID / run #$GITHUB_RUN_NUMBER / job $GITHUB_JOB_ID / sha $GITHUB_SHA"
[ -n "$DEPLOY_SSH_KEY" ] || { echo "FATAL: DEPLOY_SSH_KEY unset - deploy leg unconfigured; host NOT refreshed this release; release artifacts stand (release job already green)"; exit 1; }
- name: Refresh the product host over the declared ssh channel
env:
DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
DEPLOY_HOSTKEY: ${{ secrets.DEPLOY_HOSTKEY }}
run: |
set -euo pipefail
trap 'rm -f /tmp/dk /tmp/kh' EXIT
apt-get update -qq && apt-get install -y -qq openssh-client >/dev/null
install -m 600 /dev/null /tmp/dk
printf '%s\n' "$DEPLOY_SSH_KEY" > /tmp/dk
unset DEPLOY_SSH_KEY
if [ -n "${DEPLOY_HOSTKEY:-}" ]; then
printf '%s\n' "$DEPLOY_HOSTKEY" > /tmp/kh
SSH_PIN="-oUserKnownHostsFile=/tmp/kh -oStrictHostKeyChecking=yes"
else
SSH_PIN="-oStrictHostKeyChecking=accept-new"
fi
TAG="${{ gitea.ref_name }}"
ssh -i /tmp/dk -o BatchMode=yes $SSH_PIN deploy@10.0.0.105 bash -s "$TAG" << 'REMOTE'
set -euo pipefail
TAG="$1"
if command -v nextcraft >/dev/null 2>&1; then
echo "channel: binary/deb - the one-command upgrade (idempotent, self-verifying per deploy/README.md)"
nextcraft deploy --service --ref "$TAG"
elif [ -n "$(docker ps --format '{{.Names}}' | grep -x nextcraft || true)" ]; then
echo "channel: docker - README upgrade (pull + recreate; nextcraft-state persists)"
docker pull git.coreci.dev/coreci/nextcraft:"$TAG"
docker rm -f nextcraft
docker run -d --name nextcraft -p 8420:8420 -v nextcraft-state:/home/nextcraft/.nextcraft git.coreci.dev/coreci/nextcraft:"$TAG"
else
echo "FATAL: no nextcraft channel on $(hostname) (no nextcraft on PATH; no docker container named nextcraft) - failing loud"
exit 1
fi
echo "--- channel verify (advisory; the identity read below is canonical)"
command -v nextcraft >/dev/null 2>&1 && nextcraft --version || true
REMOTE
RC=$?
echo "host refresh done (rc=$RC); provenance: run id $GITHUB_RUN_ID / run #$GITHUB_RUN_NUMBER / job $GITHUB_JOB_ID / tag $TAG / sha $GITHUB_SHA"
exit $RC
- name: Post-deploy identity read - the R1 provenance surface
run: |
set -euo pipefail
TAG="${{ gitea.ref_name }}"
echo "waiting for the stack to settle..."
OK=""
for i in $(seq 1 12); do
CODE_H="$(curl -sS -o /tmp/h -m 15 -w '%{http_code}' https://nextcraft.coreci.dev/health || true)"
if [ "$CODE_H" = "200" ] && grep -q '"status"' /tmp/h; then OK=1; break; fi
sleep 5
done
[ -n "$OK" ] || { echo "FAIL: /health never returned 200 within the window"; exit 1; }
echo "assert 1/3: /health 200 - $(head -c 200 /tmp/h)"
CODE_R="$(curl -sS -o /tmp/r -m 15 -w '%{http_code}' https://nextcraft.coreci.dev/)"
head -c 64 /tmp/r | tr -d '[:space:]' | head -c 9 | grep -qiE '^<!doctype|^<html' || { echo "FAIL: / is not HTML (code $CODE_R)"; exit 1; }
echo "assert 2/3: / serves HTML ($CODE_R)"
CODE_O="$(curl -sS -o /tmp/o -m 25 -w '%{http_code}' https://nextcraft.coreci.dev/openapi.json)"
grep -q '"/v1/placements/admin' /tmp/o || { echo "FAIL: counting surface NOT registered on the served build (/openapi.json has no /v1/placements/admin routes) - honest red; R2 root-cause owns the diagnosis per c18619"; exit 1; }
echo "assert 3/3: /v1/placements/admin registered in /openapi.json"
echo "(advisory served version: $(grep -o '"version":"[^"]*"' /tmp/o | head -1))"
echo "PROVENANCE (R1): deploy run id $GITHUB_RUN_ID / run #$GITHUB_RUN_NUMBER / job $GITHUB_JOB_ID / tag $TAG / head $GITHUB_SHA - identity reads green"