@indigoai-us/hq-cli 5.77.14 → 5.78.0
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/CHANGELOG.md +23 -0
- package/assets/scaffold/core/scripts/archive-old-threads.sh +86 -0
- package/assets/scaffold/core/scripts/backfill-company-skill-mirrors.sh +73 -0
- package/assets/scaffold/core/scripts/backfill-workspace-mirror.sh +51 -0
- package/assets/scaffold/core/scripts/codex-skill-bridge.sh +550 -0
- package/assets/scaffold/core/scripts/detect-stale-core-policy-mirror.sh +185 -0
- package/assets/scaffold/core/scripts/hq-status-summary.sh +187 -0
- package/assets/scaffold/core/scripts/ontology-readme-drift.sh +264 -0
- package/assets/scaffold/core/scripts/qmd-reindex-after-sync.sh +93 -0
- package/assets/scaffold/core/scripts/rebuild-all-indexes.sh +69 -0
- package/assets/scaffold/core/scripts/rebuild-companies-index.sh +206 -0
- package/assets/scaffold/core/scripts/rebuild-company-knowledge-index.sh +127 -0
- package/assets/scaffold/core/scripts/rebuild-orchestrator-index.sh +86 -0
- package/assets/scaffold/core/scripts/rebuild-projects-index.sh +105 -0
- package/assets/scaffold/core/scripts/rebuild-public-knowledge-index.sh +83 -0
- package/assets/scaffold/core/scripts/rebuild-reports-index.sh +114 -0
- package/assets/scaffold/core/scripts/rebuild-social-drafts-index.sh +135 -0
- package/assets/scaffold/core/scripts/rebuild-threads-index.sh +82 -0
- package/assets/scaffold/core/scripts/rebuild-workers-index.sh +97 -0
- package/assets/scaffold/core/scripts/resize-screenshot.sh +47 -0
- package/assets/scaffold/core/scripts/token-usage-report.sh +254 -0
- package/assets/scaffold/core/scripts/worktree.sh +136 -0
- package/dist/commands/agents.js +28 -12
- package/dist/commands/api-keys.js +100 -20
- package/dist/commands/core.d.ts +90 -0
- package/dist/commands/core.js +279 -0
- package/dist/commands/files-browse.d.ts +21 -0
- package/dist/commands/files-browse.js +145 -24
- package/dist/commands/files.js +33 -7
- package/dist/commands/members.js +16 -5
- package/dist/commands/pack-install.d.ts +14 -0
- package/dist/commands/pack-install.js +42 -2
- package/dist/commands/pkg-install.js +39 -2
- package/dist/commands/run.js +6 -2
- package/dist/commands/secrets.js +120 -65
- package/dist/main.js +6 -0
- package/dist/utils/api-key-command-gate.d.ts +45 -0
- package/dist/utils/api-key-command-gate.js +51 -0
- package/dist/utils/hq-roots.d.ts +91 -0
- package/dist/utils/hq-roots.js +212 -0
- package/dist/utils/resolve-vault-credential.d.ts +63 -3
- package/dist/utils/resolve-vault-credential.js +152 -6
- package/dist/utils/run-bundled-script.d.ts +66 -0
- package/dist/utils/run-bundled-script.js +80 -0
- package/dist/utils/vault-api.d.ts +21 -0
- package/dist/utils/vault-api.js +74 -3
- package/package.json +7 -1
- package/.claude/policies/hq-cli-interactive-reads-use-sts-vend.md +0 -49
- package/.github/workflows/ci.yml +0 -46
- package/.github/workflows/publish.yml +0 -36
- package/.github/workflows/scripts/smoke-test-pkg.sh +0 -97
- package/e2e/cli.test.ts +0 -128
- package/eslint.config.js +0 -37
- package/pnpm-workspace.yaml +0 -4
- package/scripts/chmod-bins.mjs +0 -49
- package/scripts/generate-dsn.mjs +0 -26
- package/scripts/generate-scan-packages-table.mjs +0 -113
- package/scripts/smoke-sources-signals.sh +0 -103
- package/src/bin/hq-auth-refresh.ts +0 -43
- package/src/cli-version.ts +0 -13
- package/src/commands/__fixtures__/make-tar.ts +0 -126
- package/src/commands/_patterns.ts +0 -10
- package/src/commands/add.ts +0 -75
- package/src/commands/agents.test.ts +0 -527
- package/src/commands/agents.ts +0 -923
- package/src/commands/api-keys.test.ts +0 -291
- package/src/commands/api-keys.ts +0 -382
- package/src/commands/artifact-verify.test.ts +0 -177
- package/src/commands/auth.test.ts +0 -82
- package/src/commands/auth.ts +0 -213
- package/src/commands/billing.test.ts +0 -158
- package/src/commands/billing.ts +0 -146
- package/src/commands/channels.test.ts +0 -74
- package/src/commands/channels.ts +0 -91
- package/src/commands/cloud-demote.test.ts +0 -401
- package/src/commands/cloud-demote.ts +0 -278
- package/src/commands/cloud-provision.test.ts +0 -1117
- package/src/commands/cloud-provision.ts +0 -942
- package/src/commands/cloud.pull-all.test.ts +0 -711
- package/src/commands/cloud.pull-per-company.test.ts +0 -188
- package/src/commands/cloud.push-all.test.ts +0 -485
- package/src/commands/cloud.scope-excluded-warning.test.ts +0 -22
- package/src/commands/cloud.selectors.test.ts +0 -208
- package/src/commands/cloud.status.test.ts +0 -160
- package/src/commands/cloud.test.ts +0 -41
- package/src/commands/cloud.ts +0 -2130
- package/src/commands/company.test.ts +0 -202
- package/src/commands/company.ts +0 -148
- package/src/commands/creators.test.ts +0 -60
- package/src/commands/creators.ts +0 -117
- package/src/commands/crm.test.ts +0 -179
- package/src/commands/crm.ts +0 -236
- package/src/commands/db-migrate.ts +0 -55
- package/src/commands/db-provision.ts +0 -114
- package/src/commands/db-sql.ts +0 -124
- package/src/commands/db-status.ts +0 -108
- package/src/commands/db.ts +0 -26
- package/src/commands/dm.test.ts +0 -748
- package/src/commands/dm.ts +0 -1226
- package/src/commands/feedback.test.ts +0 -413
- package/src/commands/feedback.ts +0 -169
- package/src/commands/files-browse.test.ts +0 -1249
- package/src/commands/files-browse.ts +0 -1506
- package/src/commands/files-delete.test.ts +0 -484
- package/src/commands/files-recovery.test.ts +0 -370
- package/src/commands/files.test.ts +0 -722
- package/src/commands/files.ts +0 -1446
- package/src/commands/group-grants.test.ts +0 -330
- package/src/commands/group-grants.ts +0 -455
- package/src/commands/groups.test.ts +0 -44
- package/src/commands/groups.ts +0 -368
- package/src/commands/integrations.test.ts +0 -633
- package/src/commands/integrations.ts +0 -507
- package/src/commands/list.ts +0 -85
- package/src/commands/login.ts +0 -52
- package/src/commands/logout.ts +0 -30
- package/src/commands/marketplace-install.test.ts +0 -543
- package/src/commands/marketplace-security.test.ts +0 -646
- package/src/commands/mcp-registration.test.ts +0 -2787
- package/src/commands/mcp-registration.ts +0 -2612
- package/src/commands/mcp-status.test.ts +0 -483
- package/src/commands/mcp-status.ts +0 -575
- package/src/commands/mcp-status.us011.test.ts +0 -243
- package/src/commands/meetings.test.ts +0 -522
- package/src/commands/meetings.ts +0 -789
- package/src/commands/members.test.ts +0 -1474
- package/src/commands/members.ts +0 -1181
- package/src/commands/onboard-identity-guard.test.ts +0 -99
- package/src/commands/onboard-identity-guard.ts +0 -103
- package/src/commands/onboard-join.test.ts +0 -96
- package/src/commands/onboard-join.ts +0 -101
- package/src/commands/onboard-warning.test.ts +0 -26
- package/src/commands/onboard-warning.ts +0 -12
- package/src/commands/onboard.ts +0 -267
- package/src/commands/outposts-heartbeat.test.ts +0 -299
- package/src/commands/outposts-heartbeat.ts +0 -310
- package/src/commands/outposts-replica-sync.test.ts +0 -272
- package/src/commands/outposts-self-deploy.test.ts +0 -243
- package/src/commands/outposts.test.ts +0 -1039
- package/src/commands/outposts.ts +0 -1935
- package/src/commands/pack-install-secret-authorization.test.ts +0 -115
- package/src/commands/pack-install.test.ts +0 -1469
- package/src/commands/pack-install.ts +0 -2256
- package/src/commands/pack-update-cache.test.ts +0 -149
- package/src/commands/packs-update-api-key.test.ts +0 -105
- package/src/commands/packs.test.ts +0 -88
- package/src/commands/packs.ts +0 -622
- package/src/commands/people.test.ts +0 -807
- package/src/commands/people.ts +0 -422
- package/src/commands/pkg-install.dispatch.test.ts +0 -103
- package/src/commands/pkg-install.ts +0 -221
- package/src/commands/pkg-list.test.ts +0 -79
- package/src/commands/pkg-list.ts +0 -13
- package/src/commands/pkg-remove.ts +0 -71
- package/src/commands/pkg-update.ts +0 -189
- package/src/commands/publish.test.ts +0 -650
- package/src/commands/publish.ts +0 -580
- package/src/commands/reindex.test.ts +0 -259
- package/src/commands/reindex.ts +0 -274
- package/src/commands/rescue.test.ts +0 -39
- package/src/commands/rescue.ts +0 -210
- package/src/commands/run.env-local.test.ts +0 -88
- package/src/commands/run.test.ts +0 -45
- package/src/commands/run.ts +0 -190
- package/src/commands/safe-extract.test.ts +0 -459
- package/src/commands/safe-extract.ts +0 -444
- package/src/commands/secrets-scope.test.ts +0 -56
- package/src/commands/secrets-scope.ts +0 -32
- package/src/commands/secrets.parse-destination.test.ts +0 -38
- package/src/commands/secrets.test.ts +0 -2050
- package/src/commands/secrets.ts +0 -2249
- package/src/commands/signals.ts +0 -351
- package/src/commands/skill.test.ts +0 -770
- package/src/commands/skill.ts +0 -796
- package/src/commands/sources.ts +0 -362
- package/src/commands/sync-mode.test.ts +0 -366
- package/src/commands/sync-mode.ts +0 -387
- package/src/commands/sync-narrow.test.ts +0 -633
- package/src/commands/sync-narrow.ts +0 -555
- package/src/commands/sync.ts +0 -165
- package/src/commands/team-sync.ts +0 -628
- package/src/commands/update.ts +0 -71
- package/src/commands/whoami.ts +0 -83
- package/src/commands/workers.test.ts +0 -158
- package/src/commands/workers.ts +0 -301
- package/src/index.test.ts +0 -32
- package/src/index.ts +0 -20
- package/src/lib/db/control-plane.test.ts +0 -59
- package/src/lib/db/control-plane.ts +0 -113
- package/src/lib/db/local.test.ts +0 -81
- package/src/lib/db/local.ts +0 -148
- package/src/lib/db/migrate.test.ts +0 -133
- package/src/lib/db/migrate.ts +0 -137
- package/src/lib/db/paths.test.ts +0 -112
- package/src/lib/db/paths.ts +0 -128
- package/src/lib/db/remote-engine.test.ts +0 -44
- package/src/lib/db/remote-engine.ts +0 -148
- package/src/lib/db/remote-sql.test.ts +0 -32
- package/src/lib/db/remote-sql.ts +0 -62
- package/src/lib/db/sql.test.ts +0 -106
- package/src/lib/db/sql.ts +0 -192
- package/src/lib/hq-cloud-dep.smoke.test.ts +0 -75
- package/src/lib/local-tree-diff.test.ts +0 -301
- package/src/lib/local-tree-diff.ts +0 -362
- package/src/lib/narrow-hint-banner.test.ts +0 -235
- package/src/lib/narrow-hint-banner.ts +0 -212
- package/src/lib/plan-limit-nag.test.ts +0 -317
- package/src/lib/plan-limit-nag.ts +0 -264
- package/src/main.ts +0 -371
- package/src/node-preflight.test.ts +0 -60
- package/src/node-preflight.ts +0 -67
- package/src/outpost/session-heartbeat-bounds.test.ts +0 -195
- package/src/outpost/session-heartbeat-guard.test.ts +0 -105
- package/src/outpost/session-heartbeat-publisher.test.ts +0 -178
- package/src/outpost/session-heartbeat-publisher.ts +0 -186
- package/src/outpost/session-heartbeat-retain-guard.test.ts +0 -126
- package/src/outpost/session-heartbeat.test.ts +0 -459
- package/src/outpost/session-heartbeat.ts +0 -877
- package/src/packaging.test.ts +0 -109
- package/src/run/__fixtures__/discover-schemas/example.env.schema +0 -4
- package/src/run/discover-schemas.test.ts +0 -153
- package/src/run/discover-schemas.ts +0 -79
- package/src/run/hq-plugin.test.ts +0 -371
- package/src/run/hq-plugin.ts +0 -277
- package/src/run/varlock-shape.test.ts +0 -57
- package/src/schemas/hq-package.schema.json +0 -155
- package/src/sentry-before-send.test.ts +0 -359
- package/src/sentry-before-send.ts +0 -221
- package/src/sentry-epipe.test.ts +0 -37
- package/src/sentry-release.test.ts +0 -54
- package/src/sentry.test.ts +0 -24
- package/src/sentry.ts +0 -54
- package/src/strategies/link.ts +0 -62
- package/src/strategies/merge.ts +0 -142
- package/src/types.ts +0 -146
- package/src/utils/__fixtures__/scan-packages.generated-block.sh +0 -23
- package/src/utils/auth-error.test.ts +0 -40
- package/src/utils/auth-error.ts +0 -42
- package/src/utils/billing-gate.test.ts +0 -95
- package/src/utils/billing-gate.ts +0 -228
- package/src/utils/breadcrumb-buffer.ts +0 -18
- package/src/utils/cli-telemetry.test.ts +0 -153
- package/src/utils/cli-telemetry.ts +0 -61
- package/src/utils/cognito-session.machine.test.ts +0 -109
- package/src/utils/cognito-session.refresh.test.ts +0 -84
- package/src/utils/cognito-session.test.ts +0 -328
- package/src/utils/cognito-session.ts +0 -448
- package/src/utils/company-selection-error.test.ts +0 -42
- package/src/utils/company-selection-error.ts +0 -45
- package/src/utils/contribution-table.ts +0 -83
- package/src/utils/environmental-error.test.ts +0 -45
- package/src/utils/environmental-error.ts +0 -39
- package/src/utils/epipe.test.ts +0 -28
- package/src/utils/epipe.ts +0 -29
- package/src/utils/expected-cli-error.test.ts +0 -28
- package/src/utils/expected-cli-error.ts +0 -39
- package/src/utils/feedback-diagnostics.test.ts +0 -183
- package/src/utils/feedback-diagnostics.ts +0 -123
- package/src/utils/feedback-screenshots.test.ts +0 -134
- package/src/utils/feedback-screenshots.ts +0 -124
- package/src/utils/feedback-versions.test.ts +0 -98
- package/src/utils/feedback-versions.ts +0 -68
- package/src/utils/git.ts +0 -74
- package/src/utils/integrity.ts +0 -59
- package/src/utils/intercepted-process-exit.test.ts +0 -37
- package/src/utils/intercepted-process-exit.ts +0 -36
- package/src/utils/login-provider.test.ts +0 -42
- package/src/utils/login-provider.ts +0 -30
- package/src/utils/manifest.test.ts +0 -167
- package/src/utils/manifest.ts +0 -131
- package/src/utils/pack-contributions.test.ts +0 -603
- package/src/utils/pack-contributions.ts +0 -450
- package/src/utils/people.ts +0 -215
- package/src/utils/registry-client.ts +0 -204
- package/src/utils/registry.ts +0 -90
- package/src/utils/resolve-vault-credential.test.ts +0 -69
- package/src/utils/resolve-vault-credential.ts +0 -60
- package/src/utils/sandbox-runner-client.test.ts +0 -279
- package/src/utils/sandbox-runner-client.ts +0 -260
- package/src/utils/secrets-cache.ts +0 -183
- package/src/utils/sentry-identity.ts +0 -45
- package/src/utils/settle-with-timeout.test.ts +0 -21
- package/src/utils/settle-with-timeout.ts +0 -22
- package/src/utils/user-yaml-error.test.ts +0 -24
- package/src/utils/user-yaml-error.ts +0 -30
- package/src/utils/vault-api.test.ts +0 -536
- package/src/utils/vault-api.ts +0 -382
- package/src/utils/version-check.test.ts +0 -176
- package/src/utils/version-check.ts +0 -155
- package/src/utils/version-gate.test.ts +0 -1024
- package/src/utils/version-gate.ts +0 -702
- package/test/commands/db-tenant-isolation.test.ts +0 -94
- package/test/commands/db.test.ts +0 -85
- package/test/commands/signals.test.ts +0 -207
- package/test/commands/sources.test.ts +0 -231
- package/test/e2e/smoke-install-mcp.sh +0 -113
- package/test/fixtures/hq-pack-smoke-mcp/mcp/smoke-http.json +0 -1
- package/test/fixtures/hq-pack-smoke-mcp/package.yaml +0 -11
- package/test/fixtures/signals/action_item/sample.md +0 -16
- package/test/fixtures/signals/summary/sample.md +0 -12
- package/test/fixtures/sources/meetings/sample.md +0 -25
- package/test/helpers/cli-runner.ts +0 -150
- package/test/helpers/s3-list-mock.ts +0 -79
- package/test/helpers/vault-service-mock.ts +0 -295
- package/test/sources-signals/smoke.test.ts +0 -228
- package/tsconfig.json +0 -20
- package/vitest.config.ts +0 -11
- package/vitest.e2e.config.ts +0 -7
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# qmd-reindex-after-sync.sh — incremental qmd reindex after an HQ sync.
|
|
3
|
+
#
|
|
4
|
+
# Why this exists: the qmd index is a per-machine local SQLite store derived
|
|
5
|
+
# from local folder paths. Nothing re-indexed it after `hq-sync` pulled new
|
|
6
|
+
# files in, so search results diverged between teammates depending on who ran
|
|
7
|
+
# `qmd update` most recently. This script makes post-sync indexing automatic
|
|
8
|
+
# and deterministic, so every machine's personal index converges to the same
|
|
9
|
+
# content. The index itself stays personal (it is large, binary, and embeds
|
|
10
|
+
# absolute local paths); only the *freshness* is made automatic.
|
|
11
|
+
#
|
|
12
|
+
# Behavior:
|
|
13
|
+
# 1. Auto-registers any company knowledge dir that isn't yet a qmd
|
|
14
|
+
# collection (fixes the "newly-synced knowledge isn't searchable until I
|
|
15
|
+
# manually map it" gap).
|
|
16
|
+
# 2. Runs an incremental lexical reindex (`qmd update` — fast, skips
|
|
17
|
+
# unchanged files by mtime).
|
|
18
|
+
# 3. Rebuilds embeddings only when called with --embed (slow on a
|
|
19
|
+
# multi-GB index; meant for an idle/interval pass, not every sync).
|
|
20
|
+
#
|
|
21
|
+
# Idempotent and safe: no-op (exit 0) when qmd is absent or the path isn't an
|
|
22
|
+
# HQ root. Never blocks or fails a sync.
|
|
23
|
+
#
|
|
24
|
+
# Usage: qmd-reindex-after-sync.sh [hq_root] [--embed]
|
|
25
|
+
# hq_root Local HQ directory (default: $PWD). Must contain core/core.yaml.
|
|
26
|
+
# --embed Also rebuild embeddings (deferred-cost; omit for fast lexical-only).
|
|
27
|
+
|
|
28
|
+
set -uo pipefail
|
|
29
|
+
|
|
30
|
+
hq_root=""
|
|
31
|
+
embed=0
|
|
32
|
+
for arg in "$@"; do
|
|
33
|
+
case "$arg" in
|
|
34
|
+
--embed) embed=1 ;;
|
|
35
|
+
--*) : ;; # ignore unknown flags
|
|
36
|
+
*) [ -z "$hq_root" ] && hq_root="$arg" ;;
|
|
37
|
+
esac
|
|
38
|
+
done
|
|
39
|
+
[ -z "$hq_root" ] && hq_root="$PWD"
|
|
40
|
+
|
|
41
|
+
command -v qmd >/dev/null 2>&1 || exit 0
|
|
42
|
+
[ -f "$hq_root/core/core.yaml" ] || exit 0
|
|
43
|
+
|
|
44
|
+
cd "$hq_root" || exit 0
|
|
45
|
+
|
|
46
|
+
# 1. Auto-register company knowledge collections that don't exist yet.
|
|
47
|
+
# Convention matches /newcompany: --name <slug> --mask "**/*.md".
|
|
48
|
+
existing="$(qmd collection list 2>/dev/null || true)"
|
|
49
|
+
for kdir in companies/*/knowledge; do
|
|
50
|
+
[ -d "$kdir" ] || continue
|
|
51
|
+
[ -n "$(find "$kdir" -name '*.md' -not -name 'INDEX.md' -print -quit 2>/dev/null)" ] || continue
|
|
52
|
+
slug="$(basename "$(dirname "$kdir")")"
|
|
53
|
+
printf '%s\n' "$existing" | grep -Fq "qmd://$slug/" && continue
|
|
54
|
+
qmd collection add "$hq_root/$kdir" --name "$slug" --mask "**/*.md" >/dev/null 2>&1 || true
|
|
55
|
+
qmd context add "qmd://$slug" "Knowledge base for $slug." >/dev/null 2>&1 || true
|
|
56
|
+
done
|
|
57
|
+
|
|
58
|
+
# 1b. Auto-register company *projects* collections that don't exist yet.
|
|
59
|
+
# Convention matches the HQ-level `hq-projects` collection: --name <slug>-projects
|
|
60
|
+
# --mask "**/*.{md,json}" (so prd.json + project docs are searchable). Without
|
|
61
|
+
# this, company projects/ dirs are indexed by nothing and /startwork's global
|
|
62
|
+
# `qmd search "prd.json"` and /brainstorm's project discovery silently miss them.
|
|
63
|
+
for pdir in companies/*/projects; do
|
|
64
|
+
[ -d "$pdir" ] || continue
|
|
65
|
+
[ -n "$(find "$pdir" -type f \( -name '*.md' -o -name '*.json' \) -print -quit 2>/dev/null)" ] || continue
|
|
66
|
+
slug="$(basename "$(dirname "$pdir")")"
|
|
67
|
+
name="${slug}-projects"
|
|
68
|
+
printf '%s\n' "$existing" | grep -Fq "qmd://$name/" && continue
|
|
69
|
+
qmd collection add "$hq_root/$pdir" --name "$name" --mask "**/*.{md,json}" >/dev/null 2>&1 || true
|
|
70
|
+
qmd context add "qmd://$name" "Project PRDs and documentation for $slug." >/dev/null 2>&1 || true
|
|
71
|
+
done
|
|
72
|
+
|
|
73
|
+
# 1c. Auto-register the personal knowledge collection if it isn't one yet.
|
|
74
|
+
# personal/knowledge is now read DIRECTLY (the reindex symlink mirror into
|
|
75
|
+
# core/knowledge is retired), so it needs its own qmd collection to stay
|
|
76
|
+
# searchable rather than riding in under a core collection.
|
|
77
|
+
if [ -d "personal/knowledge" ] && \
|
|
78
|
+
[ -n "$(find "personal/knowledge" -name '*.md' -not -name 'INDEX.md' -print -quit 2>/dev/null)" ]; then
|
|
79
|
+
printf '%s\n' "$existing" | grep -Fq "qmd://personal-knowledge/" || {
|
|
80
|
+
qmd collection add "$hq_root/personal/knowledge" --name "personal-knowledge" --mask "**/*.md" >/dev/null 2>&1 || true
|
|
81
|
+
qmd context add "qmd://personal-knowledge" "Personal knowledge base (owner overlay)." >/dev/null 2>&1 || true
|
|
82
|
+
}
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
# 2. Incremental lexical reindex (cheap; mtime-incremental inside qmd).
|
|
86
|
+
qmd update >/dev/null 2>&1 || true
|
|
87
|
+
|
|
88
|
+
# 3. Embeddings only on explicit request.
|
|
89
|
+
if [ "$embed" -eq 1 ]; then
|
|
90
|
+
qmd embed >/dev/null 2>&1 || true
|
|
91
|
+
fi
|
|
92
|
+
|
|
93
|
+
exit 0
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# rebuild-all-indexes.sh — fan out to every per-class INDEX.md regenerator.
|
|
3
|
+
#
|
|
4
|
+
# Stdout: JSON array of every INDEX.md path that was actually written
|
|
5
|
+
# (parsed from per-script "wrote {path}" lines on stderr).
|
|
6
|
+
# Stderr: passthrough log from each script, plus a final "all-indexes: ok"
|
|
7
|
+
# or "all-indexes: errors" line.
|
|
8
|
+
#
|
|
9
|
+
# Used by handoff-post.sh / handoff-finalize.sh / /cleanup --reindex.
|
|
10
|
+
# Exit 0 always (handoff must not fail because one INDEX class blew up).
|
|
11
|
+
|
|
12
|
+
set -uo pipefail
|
|
13
|
+
|
|
14
|
+
HQ_ROOT="${HQ_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}"
|
|
15
|
+
cd "$HQ_ROOT"
|
|
16
|
+
|
|
17
|
+
SCRIPTS=(
|
|
18
|
+
"rebuild-threads-index.sh"
|
|
19
|
+
"rebuild-orchestrator-index.sh"
|
|
20
|
+
"rebuild-companies-index.sh"
|
|
21
|
+
"rebuild-projects-index.sh"
|
|
22
|
+
"rebuild-company-knowledge-index.sh"
|
|
23
|
+
"rebuild-public-knowledge-index.sh"
|
|
24
|
+
"rebuild-workers-index.sh"
|
|
25
|
+
"rebuild-reports-index.sh"
|
|
26
|
+
"rebuild-social-drafts-index.sh"
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
TMP_STDERR=$(mktemp /tmp/rebuild-all-indexes.XXXXXX)
|
|
30
|
+
trap 'rm -f "$TMP_STDERR"' EXIT
|
|
31
|
+
|
|
32
|
+
ERRORS=0
|
|
33
|
+
for s in "${SCRIPTS[@]}"; do
|
|
34
|
+
path="core/scripts/${s}"
|
|
35
|
+
if [[ ! -x "$path" ]] && [[ -f "$path" ]]; then
|
|
36
|
+
chmod +x "$path" 2>/dev/null || true
|
|
37
|
+
fi
|
|
38
|
+
if [[ ! -f "$path" ]]; then
|
|
39
|
+
echo "rebuild-all-indexes: skip ${s} (missing)" >&2
|
|
40
|
+
continue
|
|
41
|
+
fi
|
|
42
|
+
if ! bash "$path" 2>>"$TMP_STDERR"; then
|
|
43
|
+
echo "rebuild-all-indexes: ERROR in ${s}" >&2
|
|
44
|
+
ERRORS=$((ERRORS+1))
|
|
45
|
+
fi
|
|
46
|
+
done
|
|
47
|
+
|
|
48
|
+
# Replay each rebuild's stderr to our stderr (so callers see logs)
|
|
49
|
+
cat "$TMP_STDERR" >&2
|
|
50
|
+
|
|
51
|
+
# Parse "wrote {path}" lines to build the JSON output array
|
|
52
|
+
paths_json=$(
|
|
53
|
+
grep -E 'wrote (workspace|companies|knowledge|workers|projects)' "$TMP_STDERR" 2>/dev/null \
|
|
54
|
+
| sed -E 's/.*wrote ([^ ]+).*/\1/' \
|
|
55
|
+
| sort -u \
|
|
56
|
+
| jq -R . \
|
|
57
|
+
| jq -s .
|
|
58
|
+
)
|
|
59
|
+
[[ -z "$paths_json" ]] && paths_json='[]'
|
|
60
|
+
|
|
61
|
+
printf '%s\n' "$paths_json"
|
|
62
|
+
|
|
63
|
+
if [[ "$ERRORS" -gt 0 ]]; then
|
|
64
|
+
echo "all-indexes: errors (${ERRORS})" >&2
|
|
65
|
+
else
|
|
66
|
+
echo "all-indexes: ok" >&2
|
|
67
|
+
fi
|
|
68
|
+
|
|
69
|
+
exit 0
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# rebuild-companies-index.sh — regenerate companies/{co}/INDEX.md for each company.
|
|
3
|
+
#
|
|
4
|
+
# Pure bash + jq. Zero Claude context. Iterates companies/*/ (skips _template,
|
|
5
|
+
# dotfiles), summarizes top-level dirs, scans projects/*/prd.json and
|
|
6
|
+
# workspace/orchestrator/{name}/state.json to populate the Projects table.
|
|
7
|
+
#
|
|
8
|
+
# Schema per knowledge/public/hq-core/index-md-spec.md (Company Root variant):
|
|
9
|
+
# - "# {Company Title}" + "> Auto-generated. Updated: YYYY-MM-DD"
|
|
10
|
+
# - Top-level Name | Description table (dirs and 1-line desc)
|
|
11
|
+
# - "## Projects" table (Project | Status | Description)
|
|
12
|
+
# - "## Deployments" placeholder (None for now — manifest-driven enrichment deferred)
|
|
13
|
+
|
|
14
|
+
set -euo pipefail
|
|
15
|
+
|
|
16
|
+
HQ_ROOT="${HQ_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}"
|
|
17
|
+
cd "$HQ_ROOT"
|
|
18
|
+
|
|
19
|
+
DATE=$(date -u +%Y-%m-%d)
|
|
20
|
+
|
|
21
|
+
# Title-case a slug: "example-co" -> "Example Co"
|
|
22
|
+
titleize() {
|
|
23
|
+
echo "$1" | awk -F'-' '{
|
|
24
|
+
for (i=1; i<=NF; i++) {
|
|
25
|
+
$i = toupper(substr($i,1,1)) substr($i,2)
|
|
26
|
+
}
|
|
27
|
+
print
|
|
28
|
+
}' OFS=' '
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
describe_dir() {
|
|
32
|
+
local co="$1"
|
|
33
|
+
local d="$2"
|
|
34
|
+
local path="companies/${co}/${d}"
|
|
35
|
+
[[ -d "$path" ]] || return 0
|
|
36
|
+
case "$d" in
|
|
37
|
+
data)
|
|
38
|
+
local n
|
|
39
|
+
n=$(find "$path" -mindepth 1 -maxdepth 1 ! -name '.*' 2>/dev/null | wc -l | tr -d ' ')
|
|
40
|
+
echo "${n} item(s)"
|
|
41
|
+
;;
|
|
42
|
+
knowledge)
|
|
43
|
+
if [[ -e "${path}/.git" ]]; then
|
|
44
|
+
echo "Embedded git repo"
|
|
45
|
+
else
|
|
46
|
+
local n
|
|
47
|
+
n=$(find "$path" -mindepth 1 -maxdepth 1 -type d ! -name '.*' 2>/dev/null | wc -l | tr -d ' ')
|
|
48
|
+
echo "Inline knowledge (${n} subdirs)"
|
|
49
|
+
fi
|
|
50
|
+
;;
|
|
51
|
+
settings)
|
|
52
|
+
local n
|
|
53
|
+
n=$(find "$path" -mindepth 1 -maxdepth 1 -type d ! -name '.*' 2>/dev/null | wc -l | tr -d ' ')
|
|
54
|
+
echo "${n} integration(s)"
|
|
55
|
+
;;
|
|
56
|
+
policies)
|
|
57
|
+
local n
|
|
58
|
+
n=$(find "$path" -mindepth 1 -maxdepth 1 -name '*.md' 2>/dev/null | wc -l | tr -d ' ')
|
|
59
|
+
echo "${n} policy file(s)"
|
|
60
|
+
;;
|
|
61
|
+
projects)
|
|
62
|
+
local n
|
|
63
|
+
n=$(find "$path" -mindepth 1 -maxdepth 1 -type d ! -name '_*' ! -name '.*' 2>/dev/null | wc -l | tr -d ' ')
|
|
64
|
+
echo "${n} project(s)"
|
|
65
|
+
;;
|
|
66
|
+
workers)
|
|
67
|
+
local n
|
|
68
|
+
n=$(find "$path" -mindepth 1 -maxdepth 1 -type d ! -name '.*' 2>/dev/null | wc -l | tr -d ' ')
|
|
69
|
+
echo "${n} worker(s)"
|
|
70
|
+
;;
|
|
71
|
+
repos)
|
|
72
|
+
local n
|
|
73
|
+
n=$(find "$path" -mindepth 1 -maxdepth 1 \( -type d -o -type l \) ! -name '.*' 2>/dev/null | wc -l | tr -d ' ')
|
|
74
|
+
echo "${n} repo link(s)"
|
|
75
|
+
;;
|
|
76
|
+
registry)
|
|
77
|
+
local n
|
|
78
|
+
n=$(find "${path}/resources" -mindepth 1 -maxdepth 1 -name '*.yaml' 2>/dev/null | wc -l | tr -d ' ')
|
|
79
|
+
echo "Resource registry (${n} resource(s))"
|
|
80
|
+
;;
|
|
81
|
+
scripts)
|
|
82
|
+
local n
|
|
83
|
+
n=$(find "$path" -mindepth 1 -maxdepth 1 -type f 2>/dev/null | wc -l | tr -d ' ')
|
|
84
|
+
echo "${n} script(s)"
|
|
85
|
+
;;
|
|
86
|
+
*)
|
|
87
|
+
echo "—"
|
|
88
|
+
;;
|
|
89
|
+
esac
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
# Resolve project status: orchestrator state.json wins, else story-pass fallback.
|
|
93
|
+
project_status() {
|
|
94
|
+
local project="$1"
|
|
95
|
+
local prd="$2"
|
|
96
|
+
local state="workspace/orchestrator/${project}/state.json"
|
|
97
|
+
if [[ -f "$state" ]]; then
|
|
98
|
+
local raw
|
|
99
|
+
raw=$(jq -r '.status // "active"' "$state" 2>/dev/null || echo "active")
|
|
100
|
+
case "$raw" in
|
|
101
|
+
completed|complete) echo "complete" ;;
|
|
102
|
+
in_progress|active|started) echo "active" ;;
|
|
103
|
+
archived) echo "archived" ;;
|
|
104
|
+
*) echo "$raw" ;;
|
|
105
|
+
esac
|
|
106
|
+
return
|
|
107
|
+
fi
|
|
108
|
+
if [[ -f "$prd" ]]; then
|
|
109
|
+
local total passes
|
|
110
|
+
total=$(jq '[.userStories[]?] | length' "$prd" 2>/dev/null || echo 0)
|
|
111
|
+
passes=$(jq '[.userStories[]? | select(.passes==true)] | length' "$prd" 2>/dev/null || echo 0)
|
|
112
|
+
if [[ "$total" -gt 0 ]] && [[ "$total" == "$passes" ]]; then
|
|
113
|
+
echo "complete"
|
|
114
|
+
return
|
|
115
|
+
fi
|
|
116
|
+
fi
|
|
117
|
+
echo "active"
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
# Sanitize a string for Markdown table cells (single line, no pipes).
|
|
121
|
+
sanitize_cell() {
|
|
122
|
+
printf '%s' "$1" | tr '\n' ' ' | sed -e 's/|/\\|/g' -e 's/ */ /g' -e 's/^ *//' -e 's/ *$//'
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
# Truncate to N chars.
|
|
126
|
+
trunc() {
|
|
127
|
+
local s="$1"
|
|
128
|
+
local n="$2"
|
|
129
|
+
if [[ ${#s} -le $n ]]; then
|
|
130
|
+
printf '%s' "$s"
|
|
131
|
+
else
|
|
132
|
+
printf '%s…' "${s:0:$((n-1))}"
|
|
133
|
+
fi
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
write_company_index() {
|
|
137
|
+
local co="$1"
|
|
138
|
+
local out="companies/${co}/INDEX.md"
|
|
139
|
+
local title
|
|
140
|
+
title=$(titleize "$co")
|
|
141
|
+
|
|
142
|
+
# Header + top-level dir table
|
|
143
|
+
{
|
|
144
|
+
echo "# ${title}"
|
|
145
|
+
echo ""
|
|
146
|
+
echo "> Auto-generated. Updated: ${DATE}"
|
|
147
|
+
echo ""
|
|
148
|
+
echo "| Name | Description |"
|
|
149
|
+
echo "|------|-------------|"
|
|
150
|
+
# Stable order matching company template.
|
|
151
|
+
for d in data knowledge policies projects registry repos scripts settings workers; do
|
|
152
|
+
if [[ -d "companies/${co}/${d}" ]]; then
|
|
153
|
+
local desc
|
|
154
|
+
desc=$(describe_dir "$co" "$d")
|
|
155
|
+
printf '| `%s/` | %s |\n' "$d" "$(sanitize_cell "$desc")"
|
|
156
|
+
fi
|
|
157
|
+
done
|
|
158
|
+
echo ""
|
|
159
|
+
echo "## Projects"
|
|
160
|
+
echo ""
|
|
161
|
+
|
|
162
|
+
local proj_dir="companies/${co}/projects"
|
|
163
|
+
if [[ -d "$proj_dir" ]]; then
|
|
164
|
+
echo "| Project | Status | Description |"
|
|
165
|
+
echo "|---------|--------|-------------|"
|
|
166
|
+
# List immediate project subdirs, skip _archive and dotfiles.
|
|
167
|
+
while IFS= read -r p; do
|
|
168
|
+
local name
|
|
169
|
+
name=$(basename "$p")
|
|
170
|
+
[[ "$name" == _* ]] && continue
|
|
171
|
+
[[ "$name" == .* ]] && continue
|
|
172
|
+
local prd="${p}/prd.json"
|
|
173
|
+
local desc=""
|
|
174
|
+
if [[ -f "$prd" ]]; then
|
|
175
|
+
desc=$(jq -r '.description // ""' "$prd" 2>/dev/null || echo "")
|
|
176
|
+
fi
|
|
177
|
+
local status
|
|
178
|
+
status=$(project_status "$name" "$prd")
|
|
179
|
+
desc=$(sanitize_cell "$desc")
|
|
180
|
+
desc=$(trunc "$desc" 110)
|
|
181
|
+
[[ -z "$desc" ]] && desc="—"
|
|
182
|
+
printf '| `%s` | %s | %s |\n' "$name" "$status" "$desc"
|
|
183
|
+
done < <(find "$proj_dir" -mindepth 1 -maxdepth 1 -type d 2>/dev/null | sort)
|
|
184
|
+
else
|
|
185
|
+
echo "_No projects directory._"
|
|
186
|
+
fi
|
|
187
|
+
|
|
188
|
+
echo ""
|
|
189
|
+
echo "## Deployments"
|
|
190
|
+
echo ""
|
|
191
|
+
echo "_See \`companies/manifest.yaml\` for deployment targets._"
|
|
192
|
+
} > "$out"
|
|
193
|
+
|
|
194
|
+
echo "rebuild-companies-index: wrote ${out}" >&2
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
COUNT=0
|
|
198
|
+
while IFS= read -r dir; do
|
|
199
|
+
co=$(basename "$dir")
|
|
200
|
+
[[ "$co" == _* ]] && continue
|
|
201
|
+
[[ "$co" == .* ]] && continue
|
|
202
|
+
write_company_index "$co"
|
|
203
|
+
COUNT=$((COUNT+1))
|
|
204
|
+
done < <(find companies -mindepth 1 -maxdepth 1 -type d 2>/dev/null | sort)
|
|
205
|
+
|
|
206
|
+
echo "rebuild-companies-index: regenerated ${COUNT} company INDEX.md file(s)" >&2
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# rebuild-company-knowledge-index.sh — regenerate companies/{co}/knowledge/INDEX.md.
|
|
3
|
+
#
|
|
4
|
+
# Pure bash + jq. One INDEX.md per company knowledge dir, at the top level only
|
|
5
|
+
# (no descent into subdirs — embedded git repos manage their own internals).
|
|
6
|
+
#
|
|
7
|
+
# Description extraction:
|
|
8
|
+
# - .md files → first `#` heading (stripped)
|
|
9
|
+
# - .yaml files → `description:` field if present
|
|
10
|
+
# - .json files → `description` field if present
|
|
11
|
+
# - directories → "{N} item(s)"
|
|
12
|
+
#
|
|
13
|
+
# Most company knowledge dirs are embedded git repos (160000 gitlinks). The
|
|
14
|
+
# generated INDEX.md lives inside the inner repo; HQ git won't track its
|
|
15
|
+
# content directly, but it gets refreshed on every handoff.
|
|
16
|
+
|
|
17
|
+
set -euo pipefail
|
|
18
|
+
|
|
19
|
+
HQ_ROOT="${HQ_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}"
|
|
20
|
+
cd "$HQ_ROOT"
|
|
21
|
+
|
|
22
|
+
DATE=$(date -u +%Y-%m-%d)
|
|
23
|
+
|
|
24
|
+
titleize() {
|
|
25
|
+
echo "$1" | awk -F'-' '{
|
|
26
|
+
for (i=1; i<=NF; i++) { $i = toupper(substr($i,1,1)) substr($i,2) }
|
|
27
|
+
print
|
|
28
|
+
}' OFS=' '
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
sanitize_cell() {
|
|
32
|
+
printf '%s' "$1" | tr '\n' ' ' | sed -e 's/|/\\|/g' -e 's/ */ /g' -e 's/^ *//' -e 's/ *$//'
|
|
33
|
+
}
|
|
34
|
+
trunc() {
|
|
35
|
+
local s="$1" n="$2"
|
|
36
|
+
if [[ ${#s} -le $n ]]; then printf '%s' "$s"; else printf '%s…' "${s:0:$((n-1))}"; fi
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
describe_item() {
|
|
40
|
+
local path="$1"
|
|
41
|
+
local name="$2"
|
|
42
|
+
if [[ -d "$path" ]]; then
|
|
43
|
+
local n
|
|
44
|
+
n=$(find "$path" -mindepth 1 -maxdepth 1 ! -name '.*' 2>/dev/null | wc -l | tr -d ' ')
|
|
45
|
+
echo "${n} item(s)"
|
|
46
|
+
return
|
|
47
|
+
fi
|
|
48
|
+
case "$name" in
|
|
49
|
+
*.md)
|
|
50
|
+
local h
|
|
51
|
+
h=$(awk '/^# / { sub(/^# +/, ""); print; exit }' "$path" 2>/dev/null || true)
|
|
52
|
+
[[ -z "$h" ]] && h="$name"
|
|
53
|
+
echo "$h"
|
|
54
|
+
;;
|
|
55
|
+
*.yaml|*.yml)
|
|
56
|
+
local d
|
|
57
|
+
d=$(awk -F: '/^description:/ { sub(/^description: */, ""); gsub(/^["\x27]|["\x27]$/, ""); print; exit }' "$path" 2>/dev/null || true)
|
|
58
|
+
[[ -z "$d" ]] && d="$name"
|
|
59
|
+
echo "$d"
|
|
60
|
+
;;
|
|
61
|
+
*.json)
|
|
62
|
+
local d
|
|
63
|
+
d=$(jq -r '.description // .name // empty' "$path" 2>/dev/null || true)
|
|
64
|
+
[[ -z "$d" ]] && d="$name"
|
|
65
|
+
echo "$d"
|
|
66
|
+
;;
|
|
67
|
+
*)
|
|
68
|
+
echo "$name"
|
|
69
|
+
;;
|
|
70
|
+
esac
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
write_knowledge_index() {
|
|
74
|
+
local co="$1"
|
|
75
|
+
local kdir="companies/${co}/knowledge"
|
|
76
|
+
[[ -d "$kdir" ]] || return 0
|
|
77
|
+
local out="${kdir}/INDEX.md"
|
|
78
|
+
local title
|
|
79
|
+
title="$(titleize "$co") Knowledge"
|
|
80
|
+
|
|
81
|
+
{
|
|
82
|
+
echo "# ${title}"
|
|
83
|
+
echo ""
|
|
84
|
+
echo "> Auto-generated. Updated: ${DATE}"
|
|
85
|
+
echo ""
|
|
86
|
+
echo "| Name | Description |"
|
|
87
|
+
echo "|------|-------------|"
|
|
88
|
+
|
|
89
|
+
# Directories first (sorted), then files (sorted). Skip dotfiles, INDEX.md.
|
|
90
|
+
while IFS= read -r item; do
|
|
91
|
+
local name
|
|
92
|
+
name=$(basename "$item")
|
|
93
|
+
[[ "$name" == .* ]] && continue
|
|
94
|
+
[[ "$name" == "INDEX.md" ]] && continue
|
|
95
|
+
local desc
|
|
96
|
+
desc=$(describe_item "$item" "$name")
|
|
97
|
+
desc=$(sanitize_cell "$desc")
|
|
98
|
+
desc=$(trunc "$desc" 100)
|
|
99
|
+
[[ -z "$desc" ]] && desc="—"
|
|
100
|
+
if [[ -d "$item" ]]; then
|
|
101
|
+
printf '| `%s/` | %s |\n' "$name" "$desc"
|
|
102
|
+
else
|
|
103
|
+
printf '| `%s` | %s |\n' "$name" "$desc"
|
|
104
|
+
fi
|
|
105
|
+
done < <(
|
|
106
|
+
{
|
|
107
|
+
find -L "$kdir" -mindepth 1 -maxdepth 1 -type d 2>/dev/null | sort
|
|
108
|
+
find -L "$kdir" -mindepth 1 -maxdepth 1 -type f 2>/dev/null | sort
|
|
109
|
+
}
|
|
110
|
+
)
|
|
111
|
+
} > "$out"
|
|
112
|
+
|
|
113
|
+
echo "rebuild-company-knowledge-index: wrote ${out}" >&2
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
COUNT=0
|
|
117
|
+
while IFS= read -r dir; do
|
|
118
|
+
co=$(basename "$dir")
|
|
119
|
+
[[ "$co" == _* ]] && continue
|
|
120
|
+
[[ "$co" == .* ]] && continue
|
|
121
|
+
if [[ -d "companies/${co}/knowledge" ]]; then
|
|
122
|
+
write_knowledge_index "$co"
|
|
123
|
+
COUNT=$((COUNT+1))
|
|
124
|
+
fi
|
|
125
|
+
done < <(find companies -mindepth 1 -maxdepth 1 -type d 2>/dev/null | sort)
|
|
126
|
+
|
|
127
|
+
echo "rebuild-company-knowledge-index: regenerated ${COUNT} knowledge INDEX.md file(s)" >&2
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# rebuild-orchestrator-index.sh — regenerate workspace/orchestrator/INDEX.md.
|
|
3
|
+
#
|
|
4
|
+
# Pure bash + jq. Reads workspace/orchestrator/<project>/state.json files.
|
|
5
|
+
# Tolerates two on-disk schemas: project-run state (run-project.sh — .project,
|
|
6
|
+
# .prd_path, .progress, terminal on .status == "completed") and garden state
|
|
7
|
+
# (/garden — .run_id, .scope, .findings_count, terminal on .phase == "complete").
|
|
8
|
+
# Lists only non-terminal runs; _archive/ and _pipeline/ excluded.
|
|
9
|
+
# Each state.json is parsed independently: a malformed file is reported to stderr
|
|
10
|
+
# and skipped, never silently wiping the rest of the index
|
|
11
|
+
# (see core/policies/hq-never-swallow-errors.md).
|
|
12
|
+
|
|
13
|
+
set -euo pipefail
|
|
14
|
+
|
|
15
|
+
HQ_ROOT="${HQ_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}"
|
|
16
|
+
cd "$HQ_ROOT"
|
|
17
|
+
|
|
18
|
+
OUT="workspace/orchestrator/INDEX.md"
|
|
19
|
+
TS=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
20
|
+
|
|
21
|
+
mkdir -p workspace/orchestrator
|
|
22
|
+
|
|
23
|
+
STATE_FILES=()
|
|
24
|
+
while IFS= read -r line; do
|
|
25
|
+
STATE_FILES+=("$line")
|
|
26
|
+
done < <(
|
|
27
|
+
find workspace/orchestrator -mindepth 2 -maxdepth 2 -name state.json 2>/dev/null \
|
|
28
|
+
| grep -v '/_archive/' \
|
|
29
|
+
| grep -v '/_pipeline/' \
|
|
30
|
+
|| true
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
# Project column: .project (project-run) else .run_id (garden) else "-".
|
|
34
|
+
# Company column: parsed from .prd_path (project-run) or .scope (garden); a bare
|
|
35
|
+
# slug or non-companies/ path yields "-". Progress: only project-run rows carry
|
|
36
|
+
# .progress; garden rows render "-". Terminal exclusion keys off BOTH
|
|
37
|
+
# .status == "completed"/"complete" (project-run + drift guard) AND
|
|
38
|
+
# .phase == "complete" (garden's real terminal marker).
|
|
39
|
+
ROW_FILTER='
|
|
40
|
+
select((.status // "") != "completed" and (.status // "") != "complete")
|
|
41
|
+
| select((.phase // "") != "complete")
|
|
42
|
+
| [
|
|
43
|
+
(.project // .run_id // "-"),
|
|
44
|
+
(((.prd_path // .scope // "") | capture("companies/(?<co>[^/]+)/") | .co) // "-"),
|
|
45
|
+
(.status // "-"),
|
|
46
|
+
(if .progress
|
|
47
|
+
then ((.progress.completed // 0) | tostring) + "/" + ((.progress.total // 0) | tostring)
|
|
48
|
+
else "-" end),
|
|
49
|
+
(.updated_at // "-")
|
|
50
|
+
] | @tsv
|
|
51
|
+
'
|
|
52
|
+
|
|
53
|
+
ERR_FILE=$(mktemp)
|
|
54
|
+
trap 'rm -f "$ERR_FILE"' EXIT
|
|
55
|
+
|
|
56
|
+
NL=$'\n'
|
|
57
|
+
rows=""
|
|
58
|
+
# Guard the array expansion: "${arr[@]}" on an empty array errors under `set -u`
|
|
59
|
+
# on bash 3.2 (macOS). See core/policies/hq-bash-discipline.md rule 4.
|
|
60
|
+
if [[ ${#STATE_FILES[@]} -gt 0 ]]; then
|
|
61
|
+
for sf in "${STATE_FILES[@]}"; do
|
|
62
|
+
row=""
|
|
63
|
+
if row=$(jq -r "$ROW_FILTER" "$sf" 2>"$ERR_FILE"); then
|
|
64
|
+
[ -n "$row" ] && rows="${rows:+$rows$NL}$row"
|
|
65
|
+
else
|
|
66
|
+
echo "rebuild-orchestrator-index: WARNING: skipped unparseable ${sf}: $(tr '\n' ' ' < "$ERR_FILE")" >&2
|
|
67
|
+
fi
|
|
68
|
+
done
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
{
|
|
72
|
+
echo "# Orchestrator Projects"
|
|
73
|
+
echo ""
|
|
74
|
+
echo "Generated: ${TS}"
|
|
75
|
+
echo ""
|
|
76
|
+
echo "Active runs only. Archived runs in \`workspace/orchestrator/_archive/\`."
|
|
77
|
+
echo ""
|
|
78
|
+
echo "| Project | Company | Status | Progress | Last Updated |"
|
|
79
|
+
echo "|---------|---------|--------|----------|--------------|"
|
|
80
|
+
if [[ -n "$rows" ]]; then
|
|
81
|
+
printf "%s\n" "$rows" | awk -F'\t' 'NF>=5 { printf "| %s | %s | %s | %s | %s |\n", $1, $2, $3, $4, $5 }'
|
|
82
|
+
fi
|
|
83
|
+
} > "$OUT"
|
|
84
|
+
|
|
85
|
+
active=$(printf "%s" "$rows" | grep -c . || true)
|
|
86
|
+
echo "rebuild-orchestrator-index: wrote ${OUT} (${active} active)" >&2
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# rebuild-projects-index.sh — regenerate the personal projects INDEX.md.
|
|
3
|
+
#
|
|
4
|
+
# Pure bash + jq. Reads personal/projects/*/prd.json for the Personal/HQ
|
|
5
|
+
# Projects table and lists companies/*/projects directories for cross-reference.
|
|
6
|
+
# Status comes from workspace/orchestrator/{name}/state.json (fallback:
|
|
7
|
+
# passes-all → complete).
|
|
8
|
+
|
|
9
|
+
set -euo pipefail
|
|
10
|
+
|
|
11
|
+
HQ_ROOT="${HQ_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)}"
|
|
12
|
+
cd "$HQ_ROOT"
|
|
13
|
+
|
|
14
|
+
PROJECTS_DIR="personal/projects"
|
|
15
|
+
OUT="${PROJECTS_DIR}/INDEX.md"
|
|
16
|
+
DATE=$(date -u +%Y-%m-%d)
|
|
17
|
+
|
|
18
|
+
[[ -d "$PROJECTS_DIR" ]] || { echo "rebuild-projects-index: ${PROJECTS_DIR}/ missing, skipping" >&2; exit 0; }
|
|
19
|
+
|
|
20
|
+
sanitize_cell() {
|
|
21
|
+
printf '%s' "$1" | tr '\n' ' ' | sed -e 's/|/\\|/g' -e 's/ */ /g' -e 's/^ *//' -e 's/ *$//'
|
|
22
|
+
}
|
|
23
|
+
trunc() {
|
|
24
|
+
local s="$1"
|
|
25
|
+
local n="$2"
|
|
26
|
+
if [[ ${#s} -le $n ]]; then printf '%s' "$s"; else printf '%s…' "${s:0:$((n-1))}"; fi
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
project_status() {
|
|
30
|
+
local project="$1"
|
|
31
|
+
local prd="$2"
|
|
32
|
+
local state="workspace/orchestrator/${project}/state.json"
|
|
33
|
+
if [[ -f "$state" ]]; then
|
|
34
|
+
local raw
|
|
35
|
+
raw=$(jq -r '.status // "active"' "$state" 2>/dev/null || echo "active")
|
|
36
|
+
case "$raw" in
|
|
37
|
+
completed|complete) echo "complete" ;;
|
|
38
|
+
in_progress|active|started) echo "active" ;;
|
|
39
|
+
archived) echo "archived" ;;
|
|
40
|
+
*) echo "$raw" ;;
|
|
41
|
+
esac
|
|
42
|
+
return
|
|
43
|
+
fi
|
|
44
|
+
if [[ -f "$prd" ]]; then
|
|
45
|
+
local total passes
|
|
46
|
+
total=$(jq '[.userStories[]?] | length' "$prd" 2>/dev/null || echo 0)
|
|
47
|
+
passes=$(jq '[.userStories[]? | select(.passes==true)] | length' "$prd" 2>/dev/null || echo 0)
|
|
48
|
+
if [[ "$total" -gt 0 ]] && [[ "$total" == "$passes" ]]; then
|
|
49
|
+
echo "complete"
|
|
50
|
+
return
|
|
51
|
+
fi
|
|
52
|
+
fi
|
|
53
|
+
echo "—"
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
{
|
|
57
|
+
echo "# Projects"
|
|
58
|
+
echo ""
|
|
59
|
+
echo "> Auto-generated. Updated: ${DATE}"
|
|
60
|
+
echo ""
|
|
61
|
+
echo "Personal/HQ projects only. Company-scoped projects live in \`companies/{co}/projects/\`."
|
|
62
|
+
echo ""
|
|
63
|
+
echo "## Company Project Directories"
|
|
64
|
+
echo ""
|
|
65
|
+
echo "| Company | Path |"
|
|
66
|
+
echo "|---------|------|"
|
|
67
|
+
while IFS= read -r dir; do
|
|
68
|
+
co=$(basename "$dir")
|
|
69
|
+
[[ "$co" == _* ]] && continue
|
|
70
|
+
[[ "$co" == .* ]] && continue
|
|
71
|
+
if [[ -d "companies/${co}/projects" ]]; then
|
|
72
|
+
printf '| %s | `companies/%s/projects/` |\n' "$co" "$co"
|
|
73
|
+
fi
|
|
74
|
+
done < <(find companies -mindepth 1 -maxdepth 1 -type d 2>/dev/null | sort)
|
|
75
|
+
|
|
76
|
+
echo ""
|
|
77
|
+
echo "## Personal/HQ Projects"
|
|
78
|
+
echo ""
|
|
79
|
+
echo "Projects here are HQ infrastructure or cross-company tools."
|
|
80
|
+
echo ""
|
|
81
|
+
echo "| Project | Stories | Status | Description |"
|
|
82
|
+
echo "|---------|---------|--------|-------------|"
|
|
83
|
+
|
|
84
|
+
while IFS= read -r p; do
|
|
85
|
+
name=$(basename "$p")
|
|
86
|
+
[[ "$name" == _* ]] && continue
|
|
87
|
+
[[ "$name" == .* ]] && continue
|
|
88
|
+
prd="${p}/prd.json"
|
|
89
|
+
desc=""
|
|
90
|
+
stories="—"
|
|
91
|
+
if [[ -f "$prd" ]]; then
|
|
92
|
+
desc=$(jq -r '.description // ""' "$prd" 2>/dev/null || echo "")
|
|
93
|
+
stories=$(jq '[.userStories[]?] | length' "$prd" 2>/dev/null || echo 0)
|
|
94
|
+
[[ "$stories" == "0" ]] && stories="—"
|
|
95
|
+
fi
|
|
96
|
+
status=$(project_status "$name" "$prd")
|
|
97
|
+
desc=$(sanitize_cell "$desc")
|
|
98
|
+
desc=$(trunc "$desc" 110)
|
|
99
|
+
[[ -z "$desc" ]] && desc="—"
|
|
100
|
+
printf '| `%s/` | %s | %s | %s |\n' "$name" "$stories" "$status" "$desc"
|
|
101
|
+
done < <(find "$PROJECTS_DIR" -mindepth 1 -maxdepth 1 -type d 2>/dev/null | sort)
|
|
102
|
+
} > "$OUT"
|
|
103
|
+
|
|
104
|
+
count=$(find "$PROJECTS_DIR" -mindepth 1 -maxdepth 1 -type d 2>/dev/null | wc -l | tr -d ' ')
|
|
105
|
+
echo "rebuild-projects-index: wrote ${OUT} (${count} HQ project(s))" >&2
|