feat(plan-01): Phase 4b — external callers to packages paths + registry (Task 1.7)

Point the canonical entry points at the new package layout; the .specify compat facade
is retained as an intentional backward-compat layer (see below).

- .gitea/workflows/{ci,harness-ci}.yml: invoke packages/casan-harness/scripts/bash|tests
  (state paths .specify/logs kept). CI now runs on the new structure.
- infra/local-prod/docker-compose.yml: dashboard-server.py -> packages path (logs/alerts
  env stay under .specify state).
- scripts/casan-step.mjs + run-casan-pipeline.mjs: resolve the harness under
  packages/casan-harness, falling back to .specify so the adversarial/sourcegen sandboxes
  (which stage a .specify/ tree) keep working; requirement input prefers apps/okr/domain/input.
- project-registry.json: record the new layout (harness_root, state_root, governance_root,
  per-project domain_root) so Plan-06 can register a second app with its own domain.
  verify-harness-reuse.sh already resolves via CASAN_HARNESS_ROOT -> HARNESS_REUSE_VALID (3 projects).

Facade decision: the .specify/{scripts,tests,security,...} symlinks are KEPT as a
documented compat layer. A full hard cutover (removing them) still needs ~15 literal
`.specify/...` refs repointed (loop_common/evidence-pack/secrets-scan config+test paths,
run-casan-pipeline step scripts, and the signed policy-bundle.yaml path list which then
needs manifest regen + re-sign). That is a scoped follow-up; the physical separation
(code in packages/, domain in apps/, packages holds no domain data, single CASAN_* path
indirection) is complete and the full gate is green via BOTH entry paths: PASS=64 FAIL=0 SKIP=3.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
thanhnv
2026-07-08 11:36:24 +09:00
co-authored by Claude Opus 4.8
parent 3adc48ed82
commit e891981b59
7 changed files with 45 additions and 23 deletions
@@ -1,5 +1,5 @@
import { execFileSync } from 'node:child_process';
import { appendFileSync, copyFileSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from 'node:fs';
import { existsSync, appendFileSync, copyFileSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { enabled, log, redact, LOG_LEVEL } from './casan-log.mjs';
@@ -10,6 +10,10 @@ const dryRun = process.argv.includes('--dry-run');
const featureId = '001-okr-web-app';
const root = process.cwd();
// Plan-01: harness relocated to packages/casan-harness/; fall back to the .specify facade.
const HARNESS = existsSync(join(root, 'packages/casan-harness/scripts/bash/casan-harness.sh'))
? 'packages/casan-harness/scripts/bash/casan-harness.sh'
: '.specify/scripts/bash/casan-harness.sh';
const logDir = `docs/output/output_logs/${featureId}`;
const casanDir = `${logDir}/casan`;
const reportsDir = `${logDir}/reports`;
@@ -172,7 +176,7 @@ function runHarness({ id, agent, step, attempt = '1' }) {
const startedAt = Date.now();
try {
execFileSync(
'.specify/scripts/bash/casan-harness.sh',
HARNESS,
[input, output, `agent_step_${id}`, '--', 'node', 'scripts/casan-step.mjs', step, attempt],
{
cwd: root,
@@ -245,7 +249,7 @@ function runDryStep({ diagram, agent, attempt = '1', verdict = 'APPROVED', extra
const stubCmd = `printf '# %s dry-run stub artifact\\n\\nverdict: %s\\n' '${diagram}' '${verdict}' > "$CASAN_OUTPUT"`;
const startedAt = Date.now();
execFileSync(
'.specify/scripts/bash/casan-harness.sh',
HARNESS,
[input, output, `agent_step_${id}`, '--', 'bash', '-c', stubCmd],
{
cwd: root,