loki-mode 11.17.37 → 11.17.39
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/SKILL.md +2 -2
- package/VERSION +1 -1
- package/autonomy/lib/chat.sh +3 -2
- package/autonomy/lib/config-map.sh +11 -4
- package/autonomy/lib/secret-scan.sh +1 -0
- package/autonomy/loki +172 -8
- package/autonomy/verify.sh +1 -0
- package/completions/_loki +5 -0
- package/completions/loki.bash +2 -2
- package/dashboard/__init__.py +1 -1
- package/docs/CLI-REFERENCE.md +1 -1
- package/docs/DEPLOYMENT.md +22 -0
- package/docs/INSTALLATION.md +1 -1
- package/docs/v10/BOARD.md +52 -19
- package/docs/v10/PROGRESS.md +6 -0
- package/loki-ts/dist/loki.js +1274 -1257
- package/mcp/__init__.py +1 -1
- package/package.json +2 -2
- package/packages/control-plane/dist/server.js +512 -318
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
- package/web-app/dist/assets/{AdminPage-8Ms4e7v3.js → AdminPage-sMRXVp8V.js} +1 -1
- package/web-app/dist/assets/{Avatar-D-_RMtAF.js → Avatar-sqshsKDj.js} +1 -1
- package/web-app/dist/assets/{Badge-BiTryACM.js → Badge-DVLT6AZl.js} +1 -1
- package/web-app/dist/assets/{Button-D5J90sJA.js → Button-CUGOx2F-.js} +1 -1
- package/web-app/dist/assets/{CockpitPage-CBsCLHsX.js → CockpitPage-_5XpWSyB.js} +1 -1
- package/web-app/dist/assets/{ComparePage-ZU4NYIxk.js → ComparePage-CHybAwF6.js} +1 -1
- package/web-app/dist/assets/{ErrorBoundary-kRsIDD2c.js → ErrorBoundary-yws0dvvJ.js} +1 -1
- package/web-app/dist/assets/{EvidenceReceiptPanel-DV6ZxN0r.js → EvidenceReceiptPanel-DQPXKaYq.js} +1 -1
- package/web-app/dist/assets/{GitHubIssuesPanel-B0uPt2Uy.js → GitHubIssuesPanel-CDnklfFn.js} +1 -1
- package/web-app/dist/assets/{GitHubPRsPanel-DnrIz7Qh.js → GitHubPRsPanel-F1H3q6Mg.js} +1 -1
- package/web-app/dist/assets/{HomePage-SjkWXTYO.js → HomePage-Donxu3UG.js} +2 -2
- package/web-app/dist/assets/{LoginPage-D1XU1UOK.js → LoginPage-vabZaQ4T.js} +1 -1
- package/web-app/dist/assets/{MagicPage-Cg6MzSOR.js → MagicPage-zJiSFKm6.js} +1 -1
- package/web-app/dist/assets/{MetricsPage-Bs4xxEL4.js → MetricsPage-tW1d9Pc4.js} +1 -1
- package/web-app/dist/assets/{NotFoundPage-xoIjTbo3.js → NotFoundPage-DfL2kcAp.js} +1 -1
- package/web-app/dist/assets/{ProjectPage-DtX7g5N3.js → ProjectPage-Bnx3Slii.js} +3 -3
- package/web-app/dist/assets/{ProjectsPage-BZiUAYq4.js → ProjectsPage-C74jNljb.js} +1 -1
- package/web-app/dist/assets/{SettingsPage-BGWiG3O9.js → SettingsPage-FA9_6XvR.js} +1 -1
- package/web-app/dist/assets/{ShowcasePage-DgrnwUsK.js → ShowcasePage-CUYKoPB0.js} +1 -1
- package/web-app/dist/assets/{SystemSettingsPage-cHvinh4M.js → SystemSettingsPage-ClEk_OL-.js} +1 -1
- package/web-app/dist/assets/{TeamsPage-BVCDcah9.js → TeamsPage-CZod1nxw.js} +1 -1
- package/web-app/dist/assets/{TemplatesPage-BVZWaHmc.js → TemplatesPage-ftxcEJ5S.js} +1 -1
- package/web-app/dist/assets/{TerminalOutput-DXipqPhV.js → TerminalOutput-C-ztoDne.js} +1 -1
- package/web-app/dist/assets/{activity-CshhOoCC.js → activity-ClWb6nuh.js} +1 -1
- package/web-app/dist/assets/{bell-C2aVKCgl.js → bell-DSdTj9Kf.js} +1 -1
- package/web-app/dist/assets/{bot-CS4hsHcl.js → bot-DX8ebhTj.js} +1 -1
- package/web-app/dist/assets/{check-C9BOGqR2.js → check-6OAuuO_W.js} +1 -1
- package/web-app/dist/assets/{chevron-left-BBTdOAuW.js → chevron-left-DTdjxSL_.js} +1 -1
- package/web-app/dist/assets/{circle-alert-D7SSuEIf.js → circle-alert-B40DtHik.js} +1 -1
- package/web-app/dist/assets/{clock-CHFYgPU3.js → clock-cVEP2obv.js} +1 -1
- package/web-app/dist/assets/{cloud-cEefzPuf.js → cloud-CmG80ODy.js} +1 -1
- package/web-app/dist/assets/{code-xml-B7St2q5i.js → code-xml-uDISZWZx.js} +1 -1
- package/web-app/dist/assets/{database-irsYoPwy.js → database-BBjrBzZH.js} +1 -1
- package/web-app/dist/assets/{dollar-sign-ChdZBjDE.js → dollar-sign-QuSiEBvi.js} +1 -1
- package/web-app/dist/assets/{file-code-corner-CdnsaqHY.js → file-code-corner-DaYWw_54.js} +1 -1
- package/web-app/dist/assets/{file-plus-Cm5WJLtA.js → file-plus-DBrjgfG0.js} +1 -1
- package/web-app/dist/assets/{globe-itCMNb3u.js → globe-yLg95rUG.js} +1 -1
- package/web-app/dist/assets/{hammer-DpZbHRqZ.js → hammer-Cm_tQ3f7.js} +1 -1
- package/web-app/dist/assets/{index-BY6H3gcR.js → index-WwgJyEgR.js} +3 -3
- package/web-app/dist/assets/{layers-Pja4FEia.js → layers-CVu0QAr_.js} +1 -1
- package/web-app/dist/assets/{loader-circle-CeRQm3kJ.js → loader-circle-C1ByA4HR.js} +1 -1
- package/web-app/dist/assets/{lock-DN-Y7N_K.js → lock-COFCj4kU.js} +1 -1
- package/web-app/dist/assets/{package-xmriszo-.js → package-DPdWCR4l.js} +1 -1
- package/web-app/dist/assets/{plus-_Uj6A6jB.js → plus-CP2Oh8yP.js} +1 -1
- package/web-app/dist/assets/{refresh-cw-BsssvIIM.js → refresh-cw-CR9Wf9cI.js} +1 -1
- package/web-app/dist/assets/{rotate-ccw-BuGEgNBP.js → rotate-ccw-jJugFDir.js} +1 -1
- package/web-app/dist/assets/{scroll-text-D3I5iPxb.js → scroll-text-BiJUO5k9.js} +1 -1
- package/web-app/dist/assets/{server-CmqFqyr6.js → server-US70f4RI.js} +1 -1
- package/web-app/dist/assets/{shield-alert-BDfXzBqa.js → shield-alert-C7ig1ziQ.js} +1 -1
- package/web-app/dist/assets/{thumbs-up-_tO386xs.js → thumbs-up-D3SDwx7o.js} +1 -1
- package/web-app/dist/assets/{trash-2-BY17xDYh.js → trash-2-CikJqAs_.js} +1 -1
- package/web-app/dist/assets/{trending-down-2q53wyOn.js → trending-down-Bcyok37Q.js} +1 -1
- package/web-app/dist/assets/{trending-up-k3BMoWKv.js → trending-up-CFJbw392.js} +1 -1
- package/web-app/dist/assets/{upload-BchR2Xs4.js → upload-BvhLwHkC.js} +1 -1
- package/web-app/dist/assets/{usePolling-DO8v6wKt.js → usePolling-Bck_ydy1.js} +1 -1
- package/web-app/dist/assets/{user-ThJCW69N.js → user-BpuwYFeB.js} +1 -1
- package/web-app/dist/index.html +1 -1
package/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: loki-mode
|
|
|
3
3
|
description: An autonomous software factory that knows what it is supposed to deliver, and proves it did. Use when the user says Loki Mode or asks to build, fix or verify software autonomously.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Loki Mode v11.17.
|
|
6
|
+
# Loki Mode v11.17.39
|
|
7
7
|
|
|
8
8
|
**Current entry points (Loki 10 engine):** `loki "<task>"`, `loki owner/repo#N` and `loki quick "<task>"` run the Loki 10 engine and end with a signed receipt (`loki verify`). `loki backlog owner/repo --all` runs many issues in parallel. Guide: `docs/v10/GUIDE.md`. The skill instructions below, and `loki start`, describe the previous bash loop. PRD-file starts (`loki start ./prd.md`) and the opencode provider still run on it until FC38-SWEEP ports them; the legacy-engine command and the LOKI_ENGINE switch remain removed. Prefer `loki owner/repo#N` for issues.
|
|
9
9
|
|
|
@@ -483,4 +483,4 @@ See `CHANGELOG.md` entries [7.5.7], [7.5.8], [7.5.13] for the per-fix list and r
|
|
|
483
483
|
|
|
484
484
|
---
|
|
485
485
|
|
|
486
|
-
**v11.17.
|
|
486
|
+
**v11.17.39 | [Autonomi](https://www.autonomi.dev/) flagship product | core skill**
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
11.17.
|
|
1
|
+
11.17.39
|
package/autonomy/lib/chat.sh
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# Sourced by autonomy/loki; defines cmd_chat. Free text goes to the provider
|
|
4
4
|
# in the current mode; slash commands delegate to existing loki commands.
|
|
5
5
|
|
|
6
|
-
_LOKI_CHAT_SYSTEM_PROMPT="You are running inside Loki Mode chat. Be concise. Prefer small, verifiable changes. Loki commands available to the user: loki start (also --workspace and --deploy), loki quick, loki verify, loki receipt, loki undo. During a run, /steer sends a mid-run directive via loki steer (applied at the next plan or implement stage); /pause and /resume control the run, and /answer replies to a blocked run."
|
|
6
|
+
_LOKI_CHAT_SYSTEM_PROMPT="You are running inside Loki Mode chat. Be concise. Prefer small, verifiable changes. Loki commands available to the user: loki start (also --workspace and --deploy; deploy takes --destination, --canary, --env-file, --domain and --health-url), loki quick, loki verify (loki verify --url https://host checks a live deploy against its provenance), loki receipt, loki undo. During a run, /steer sends a mid-run directive via loki steer (applied at the next plan or implement stage); /pause and /resume control the run, and /answer replies to a blocked run."
|
|
7
7
|
|
|
8
8
|
_chat_loki_bin() {
|
|
9
9
|
local d="${_LOKI_SCRIPT_DIR:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}"
|
|
@@ -50,7 +50,8 @@ Loki chat commands:
|
|
|
50
50
|
/resume loki resume
|
|
51
51
|
/answer <text> loki answer --text: answer a BLOCKED run with a follow-up run
|
|
52
52
|
/workspace <name> <brief> loki start --workspace (multi-repo run, composite receipt)
|
|
53
|
-
/deploy [--
|
|
53
|
+
/deploy [--destination D] [--canary] [--env-file F] [--domain H] [--health-url U] [--auto-rollback]
|
|
54
|
+
loki deploy --execute after you confirm (gated on a VERIFIED receipt)
|
|
54
55
|
/attach attach to the current or most recent loki start run in this repo
|
|
55
56
|
/quick <task> loki quick
|
|
56
57
|
/edit <change> apply one change (build mode for this turn)
|
|
@@ -749,18 +749,25 @@ loki_maybe_apply_config_file() {
|
|
|
749
749
|
path="$LOKI_CONFIG_FILE"
|
|
750
750
|
fi
|
|
751
751
|
# 2. scan args (explicit flag overrides the env var).
|
|
752
|
-
|
|
753
|
-
local a
|
|
752
|
+
# With --deploy on the line, --env-file is the deploy env file, not config.
|
|
753
|
+
local prev="" a ef_cfg=1
|
|
754
|
+
for a in "$@"; do [ "$a" = "--deploy" ] && ef_cfg=0; done
|
|
754
755
|
for a in "$@"; do
|
|
755
756
|
case "$prev" in
|
|
756
|
-
--config|--vars
|
|
757
|
+
--config|--vars)
|
|
757
758
|
path="$a"
|
|
758
759
|
;;
|
|
760
|
+
--env-file)
|
|
761
|
+
[ "$ef_cfg" = 1 ] && path="$a"
|
|
762
|
+
;;
|
|
759
763
|
esac
|
|
760
764
|
case "$a" in
|
|
761
|
-
--config=*|--vars
|
|
765
|
+
--config=*|--vars=*)
|
|
762
766
|
path="${a#*=}"
|
|
763
767
|
;;
|
|
768
|
+
--env-file=*)
|
|
769
|
+
[ "$ef_cfg" = 1 ] && path="${a#*=}"
|
|
770
|
+
;;
|
|
764
771
|
esac
|
|
765
772
|
prev="$a"
|
|
766
773
|
done
|
|
@@ -43,6 +43,7 @@ _commit_scan_secret_file() {
|
|
|
43
43
|
'github_pat_[A-Za-z0-9_]{60,}' # GitHub fine-grained PAT
|
|
44
44
|
'xox[baprs]-[A-Za-z0-9-]{10,}' # Slack token (xoxb-/xoxp-/...)
|
|
45
45
|
'sk-[A-Za-z0-9]{20,}' # OpenAI-style secret key
|
|
46
|
+
'sk-ant-[A-Za-z0-9_-]{20,}' # Anthropic API key (hyphenated body)
|
|
46
47
|
'AIza[0-9A-Za-z_-]{35}' # Google API key
|
|
47
48
|
'glpat-[A-Za-z0-9_-]{20,}' # GitLab personal access token
|
|
48
49
|
)
|
package/autonomy/loki
CHANGED
|
@@ -1904,6 +1904,9 @@ show_help_all() {
|
|
|
1904
1904
|
echo " --openspec PATH Use OpenSpec change directory as input"
|
|
1905
1905
|
echo " --config PATH Load settings from a config file (.yaml/.json/.env). Alias: --env-file, --vars"
|
|
1906
1906
|
echo " Precedence: CLI flag > env var > --config file > defaults. Secrets via \${VAR}."
|
|
1907
|
+
echo " --deploy After a start that exits 0, run the gated loki deploy --execute. Deploy flags: --destination preview|staging|production,"
|
|
1908
|
+
echo " --canary, --env-file FILE (deploy env, not config, with --deploy), --domain HOST, --github (publish after deploy),"
|
|
1909
|
+
echo " --health-url URL, --health-match STR, --auto-rollback"
|
|
1907
1910
|
echo ""
|
|
1908
1911
|
echo "Deprecated alias 'run': 'loki run <issue-ref>' still works as an alias"
|
|
1909
1912
|
echo "for 'loki start'. See its options with 'loki run --help'."
|
|
@@ -2644,8 +2647,31 @@ cmd_start() {
|
|
|
2644
2647
|
# that ended 0. cmd_deploy owns every gate: no VERIFIED HEAD-anchored
|
|
2645
2648
|
# receipt means a refusal, never a deploy.
|
|
2646
2649
|
local _ps_ws="" _ps_deploy=0 _ps_health="" _ps_hmatch="" _ps_rb=0 _ps_rest=() _ps_brief=() _ps_a
|
|
2650
|
+
local _ps_dest="" _ps_canary=0 _ps_envf="" _ps_domain="" _ps_gh=0 _ps_dep_in=0
|
|
2651
|
+
# --env-file and --github already mean config alias and issue sync for a plain
|
|
2652
|
+
# start; they are deploy flags only when --deploy is on the line.
|
|
2653
|
+
for _ps_a in "$@"; do [ "$_ps_a" = "--deploy" ] && _ps_dep_in=1; done
|
|
2647
2654
|
while [ $# -gt 0 ]; do
|
|
2648
2655
|
case "$1" in
|
|
2656
|
+
--destination)
|
|
2657
|
+
[ -n "${2:-}" ] && [ "${2#-}" = "$2" ] || { echo -e "${RED}--destination requires preview, staging or production${NC}" >&2; exit 2; }
|
|
2658
|
+
_ps_dest="$2"; shift 2 ;;
|
|
2659
|
+
--destination=*) _ps_dest="${1#*=}"; shift ;;
|
|
2660
|
+
--domain)
|
|
2661
|
+
[ -n "${2:-}" ] && [ "${2#-}" = "$2" ] || { echo -e "${RED}--domain requires a hostname${NC}" >&2; exit 2; }
|
|
2662
|
+
_ps_domain="$2"; shift 2 ;;
|
|
2663
|
+
--domain=*) _ps_domain="${1#*=}"; shift ;;
|
|
2664
|
+
--env-file)
|
|
2665
|
+
if [ "$_ps_dep_in" != 1 ]; then _ps_rest+=("$1"); shift; continue; fi
|
|
2666
|
+
[ -n "${2:-}" ] && [ "${2#-}" = "$2" ] || { echo -e "${RED}--env-file requires a file path${NC}" >&2; exit 2; }
|
|
2667
|
+
_ps_envf="$2"; shift 2 ;;
|
|
2668
|
+
--env-file=*)
|
|
2669
|
+
if [ "$_ps_dep_in" = 1 ]; then _ps_envf="${1#*=}"; else _ps_rest+=("$1"); fi
|
|
2670
|
+
shift ;;
|
|
2671
|
+
--canary) _ps_canary=1; shift ;;
|
|
2672
|
+
--github)
|
|
2673
|
+
if [ "$_ps_dep_in" = 1 ]; then _ps_gh=1; else _ps_rest+=("$1"); fi
|
|
2674
|
+
shift ;;
|
|
2649
2675
|
--workspace)
|
|
2650
2676
|
[ -n "${2:-}" ] && [ "${2#-}" = "$2" ] || { echo -e "${RED}--workspace requires a workspace name${NC}" >&2; exit 2; }
|
|
2651
2677
|
_ps_ws="$2"; shift 2 ;;
|
|
@@ -2663,8 +2689,8 @@ cmd_start() {
|
|
|
2663
2689
|
*) _ps_rest+=("$1"); shift ;;
|
|
2664
2690
|
esac
|
|
2665
2691
|
done
|
|
2666
|
-
if { [ -n "$_ps_health" ] || [ -n "$_ps_hmatch" ] || [ "$_ps_rb" = 1 ]; } && [ "$_ps_deploy" != 1 ]; then
|
|
2667
|
-
echo -e "${RED}--health-url, --health-match
|
|
2692
|
+
if { [ -n "$_ps_health" ] || [ -n "$_ps_hmatch" ] || [ "$_ps_rb" = 1 ] || [ -n "$_ps_dest" ] || [ "$_ps_canary" = 1 ] || [ -n "$_ps_domain" ]; } && [ "$_ps_deploy" != 1 ]; then
|
|
2693
|
+
echo -e "${RED}--health-url, --health-match, --auto-rollback, --destination, --canary and --domain apply only with --deploy${NC}" >&2
|
|
2668
2694
|
exit 2
|
|
2669
2695
|
fi
|
|
2670
2696
|
if [ -n "$_ps_ws" ]; then
|
|
@@ -2708,8 +2734,17 @@ cmd_start() {
|
|
|
2708
2734
|
[ -n "$_ps_health" ] && _ps_dargs+=(--health-url "$_ps_health")
|
|
2709
2735
|
[ -n "$_ps_hmatch" ] && _ps_dargs+=(--health-match "$_ps_hmatch")
|
|
2710
2736
|
[ "$_ps_rb" = 1 ] && _ps_dargs+=(--auto-rollback)
|
|
2711
|
-
|
|
2712
|
-
|
|
2737
|
+
[ -n "$_ps_dest" ] && _ps_dargs+=(--destination "$_ps_dest")
|
|
2738
|
+
[ "$_ps_canary" = 1 ] && _ps_dargs+=(--canary)
|
|
2739
|
+
[ -n "$_ps_envf" ] && _ps_dargs+=(--env-file "$_ps_envf")
|
|
2740
|
+
[ -n "$_ps_domain" ] && _ps_dargs+=(--domain "$_ps_domain")
|
|
2741
|
+
local _ps_drc=0
|
|
2742
|
+
cmd_deploy "${_ps_dargs[@]}" || _ps_drc=$?
|
|
2743
|
+
if [ "$_ps_drc" -ne 0 ]; then return "$_ps_drc"; fi
|
|
2744
|
+
if [ "$_ps_gh" = 1 ]; then
|
|
2745
|
+
( cmd_github publish ) || _ps_drc=$?
|
|
2746
|
+
fi
|
|
2747
|
+
return "$_ps_drc"
|
|
2713
2748
|
fi
|
|
2714
2749
|
# P12-07b: a bare `loki start --resume [run-id]` goes to the same engine10
|
|
2715
2750
|
# resume path as `loki resume` (util/run_outputs.ts resumeMain), never into a
|
|
@@ -2841,6 +2876,11 @@ cmd_start() {
|
|
|
2841
2876
|
echo " --quiet Suppress [INFO]/[STEP]; warnings and errors still print"
|
|
2842
2877
|
echo " --log-level LEVEL debug | info | warn | error (default: info)"
|
|
2843
2878
|
echo " --max-duration DUR Wall-clock cap: seconds, or 90m / 2h (default: none)"
|
|
2879
|
+
echo " --deploy After a start that exits 0, run the gated loki deploy --execute. Deploy flags:"
|
|
2880
|
+
echo " --destination preview|staging|production, --canary, --domain HOST,"
|
|
2881
|
+
echo " --env-file FILE (the deploy env file, not config, when --deploy is set),"
|
|
2882
|
+
echo " --health-url URL, --health-match STR, --auto-rollback,"
|
|
2883
|
+
echo " and, with --deploy, the flag --github runs loki github publish after a good deploy"
|
|
2844
2884
|
echo ""
|
|
2845
2885
|
echo "Issue-mode options (used when input is an ISSUE-REF or a --brief):"
|
|
2846
2886
|
echo " --dry-run Preview generated PRD without starting"
|
|
@@ -10009,7 +10049,7 @@ _deploy_latest_receipt() {
|
|
|
10009
10049
|
return 0
|
|
10010
10050
|
}
|
|
10011
10051
|
|
|
10012
|
-
# _deploy_record <dir> <command> <exit_code> <run_id> <anchor_sha> [state] [health_status] [health_url] [rb_attempted] [rb_exit] [receipt_sha256] [started_at] [finished_at] [target] [canary] [post_rollback_health] [health_http_code] [health_match] [tree_sha] [destination] [deployed_url] [health_url_source] [env_keys_csv] [env_source]
|
|
10052
|
+
# _deploy_record <dir> <command> <exit_code> <run_id> <anchor_sha> [state] [health_status] [health_url] [rb_attempted] [rb_exit] [receipt_sha256] [started_at] [finished_at] [target] [canary] [post_rollback_health] [health_http_code] [health_match] [tree_sha] [destination] [deployed_url] [health_url_source] [env_keys_csv] [env_source] [domain] [domain_status] [tls_status] [tls_not_after] [domain_provenance]
|
|
10013
10053
|
# Writes the executed deploy's own record, then signs it (loki.deploy/1, Ed25519 via the
|
|
10014
10054
|
# receipt signer in loki-ts/src/util/receipt_signer.ts) so it is bound to the receipt that
|
|
10015
10055
|
# authorized it; `loki verify <record>` re-checks it offline. An unsigned record is reported
|
|
@@ -10037,6 +10077,8 @@ _deploy_record() {
|
|
|
10037
10077
|
# --env-file: key NAMES only (comma-joined, validated identifiers) and the file
|
|
10038
10078
|
# path. A value is never passed here, so the signed record cannot carry one.
|
|
10039
10079
|
local env_keys_csv="${23:-}" env_source="${24:-}"
|
|
10080
|
+
# --domain: tls_status is "unchecked" unless the openssl proof ran and said otherwise.
|
|
10081
|
+
local domain_rec="${25:-}" domain_status="${26:-}" tls_status="${27:-unchecked}" tls_not_after="${28:-}" domain_prov="${29:-}"
|
|
10040
10082
|
local ddir="$dir/.loki/deploys"
|
|
10041
10083
|
[ -d "${LOKI_DIR:-}" ] && ddir="${LOKI_DIR}/deploys"
|
|
10042
10084
|
mkdir -p "$ddir" 2>/dev/null || return 0
|
|
@@ -10046,6 +10088,7 @@ _deploy_record() {
|
|
|
10046
10088
|
DR_RBA="$rb_attempted" DR_RBX="$rb_exit" DR_RSHA="$receipt_sha" DR_T0="$started_at" \
|
|
10047
10089
|
DR_T1="$finished_at" DR_TGT="$target" DR_CAN="$canary" DR_PRB="$post_rb" DR_HC="$hcode_rec" DR_HM="$hmatch" DR_TREE="$tree_sha" DR_DEST="$dest_rec" DR_DURL="$deployed_url" DR_HSRC="$hsrc" \
|
|
10048
10090
|
DR_ENVK="$env_keys_csv" DR_ENVS="$env_source" \
|
|
10091
|
+
DR_DOM="$domain_rec" DR_DOMS="$domain_status" DR_TLS="$tls_status" DR_TLSA="$tls_not_after" DR_DOMP="$domain_prov" \
|
|
10049
10092
|
python3 -c '
|
|
10050
10093
|
import json, os, datetime
|
|
10051
10094
|
state = os.environ.get("DR_STATE") or "anchored"
|
|
@@ -10079,6 +10122,11 @@ json.dump({
|
|
|
10079
10122
|
"health_url_source": os.environ.get("DR_HSRC", ""),
|
|
10080
10123
|
"env_keys": sorted(k for k in os.environ.get("DR_ENVK", "").split(",") if k),
|
|
10081
10124
|
"env_source": os.environ.get("DR_ENVS", ""),
|
|
10125
|
+
"domain": os.environ.get("DR_DOM", ""),
|
|
10126
|
+
"domain_status": os.environ.get("DR_DOMS", ""),
|
|
10127
|
+
"tls_status": os.environ.get("DR_TLS") or "unchecked",
|
|
10128
|
+
"tls_not_after": os.environ.get("DR_TLSA", ""),
|
|
10129
|
+
"domain_provenance": os.environ.get("DR_DOMP", ""),
|
|
10082
10130
|
"health_http_code": int(os.environ["DR_HC"]) if os.environ.get("DR_HC", "").isdigit() else None,
|
|
10083
10131
|
}, open(os.environ["DR_OUT"], "w"), indent=2)
|
|
10084
10132
|
' 2>/dev/null || return 0
|
|
@@ -10300,6 +10348,80 @@ out("__LOKI_ENV_OK__")
|
|
|
10300
10348
|
PYEOF
|
|
10301
10349
|
}
|
|
10302
10350
|
|
|
10351
|
+
# _deploy_domain_step <dir> <command> <domain> <deployed_url> <head_sha>
|
|
10352
|
+
# --domain: attach <domain> with the provider's documented verb, then PROVE TLS with
|
|
10353
|
+
# openssl. Sets _DD_STATUS (attached|manual|failed), _DD_TLS (valid|expiring|invalid|
|
|
10354
|
+
# unchecked), _DD_NOTAFTER and _DD_PROV (match|mismatch|unchecked). Returns 6 when the
|
|
10355
|
+
# attach failed or the TLS handshake/cert is invalid, else 0. tls_status is "valid" ONLY
|
|
10356
|
+
# when the handshake gave a cert and 'openssl x509 -checkend 604800' accepted it.
|
|
10357
|
+
_deploy_domain_step() {
|
|
10358
|
+
local dir="$1" command="$2" domain="$3" durl="$4" head="$5"
|
|
10359
|
+
local arc=0 hint="" pem="" xout="" xrc=0 tmo="" na="" body="" psha=""
|
|
10360
|
+
_DD_STATUS="" _DD_TLS="unchecked" _DD_NOTAFTER="" _DD_PROV="unchecked"
|
|
10361
|
+
echo "Attaching domain: ${domain}"
|
|
10362
|
+
case "$command" in
|
|
10363
|
+
"vercel --prod")
|
|
10364
|
+
hint="Vercel needs DNS for ${domain}: A 76.76.21.21 (apex) or CNAME cname.vercel-dns.com"
|
|
10365
|
+
if [ -z "$durl" ]; then
|
|
10366
|
+
echo " The deploy printed no URL, so 'vercel alias set' has nothing to alias." >&2
|
|
10367
|
+
_DD_STATUS=failed
|
|
10368
|
+
else
|
|
10369
|
+
_DD_STATUS=attached
|
|
10370
|
+
( cd "$dir" && vercel alias set "$durl" "$domain" ) || arc=$?
|
|
10371
|
+
[ "$arc" -eq 0 ] || _DD_STATUS=failed
|
|
10372
|
+
fi
|
|
10373
|
+
;;
|
|
10374
|
+
"fly deploy")
|
|
10375
|
+
hint="Fly needs DNS for ${domain}: the A/AAAA or CNAME records 'fly certs show ${domain}' prints"
|
|
10376
|
+
_DD_STATUS=attached
|
|
10377
|
+
( cd "$dir" && fly certs add "$domain" ) || arc=$?
|
|
10378
|
+
[ "$arc" -eq 0 ] || _DD_STATUS=failed
|
|
10379
|
+
;;
|
|
10380
|
+
*)
|
|
10381
|
+
_DD_STATUS=manual
|
|
10382
|
+
hint="${command%% *} has no wired domain verb: add ${domain} in its dashboard, then point DNS at the record it shows"
|
|
10383
|
+
echo " Manual step: ${hint}."
|
|
10384
|
+
;;
|
|
10385
|
+
esac
|
|
10386
|
+
[ "$_DD_STATUS" != failed ] || echo -e "${RED}Domain attach failed (exit ${arc}).${NC}" >&2
|
|
10387
|
+
|
|
10388
|
+
if ! command -v openssl >/dev/null 2>&1; then
|
|
10389
|
+
echo "TLS: openssl not found. tls_status=unchecked (never a claim of valid)."
|
|
10390
|
+
else
|
|
10391
|
+
command -v timeout >/dev/null 2>&1 && tmo="timeout 15"
|
|
10392
|
+
# shellcheck disable=SC2086
|
|
10393
|
+
pem="$($tmo openssl s_client -servername "$domain" -connect "${domain}:443" </dev/null 2>/dev/null)" || true
|
|
10394
|
+
case "$pem" in
|
|
10395
|
+
*"BEGIN CERTIFICATE"*)
|
|
10396
|
+
xout="$(printf '%s\n' "$pem" | openssl x509 -noout -enddate -checkend 604800 2>/dev/null)" || xrc=$?
|
|
10397
|
+
na="$(sed -n 's/^notAfter=//p' <<<"$xout" | head -n 1)"
|
|
10398
|
+
if [ -z "$na" ]; then _DD_TLS=invalid
|
|
10399
|
+
elif [ "$xrc" -eq 0 ]; then _DD_TLS=valid
|
|
10400
|
+
else _DD_TLS=expiring; fi
|
|
10401
|
+
[ -z "$na" ] || _DD_NOTAFTER="$(python3 -c 'import sys,datetime
|
|
10402
|
+
try: print(datetime.datetime.strptime(sys.argv[1].strip(), "%b %d %H:%M:%S %Y GMT").strftime("%Y-%m-%dT%H:%M:%SZ"))
|
|
10403
|
+
except Exception: print(sys.argv[1].strip())' "$na" 2>/dev/null || printf '%s' "$na")"
|
|
10404
|
+
;;
|
|
10405
|
+
*) _DD_TLS=invalid ;;
|
|
10406
|
+
esac
|
|
10407
|
+
echo "TLS: ${domain} tls_status=${_DD_TLS}${_DD_NOTAFTER:+ (not after ${_DD_NOTAFTER})}"
|
|
10408
|
+
[ "$_DD_TLS" != expiring ] || echo -e "${YELLOW} The certificate expires within 7 days.${NC}" >&2
|
|
10409
|
+
fi
|
|
10410
|
+
|
|
10411
|
+
if [ "$_DD_TLS" = invalid ]; then
|
|
10412
|
+
echo -e "${RED}TLS invalid for ${domain}: no usable certificate was served. DNS may not point at the provider yet.${NC}" >&2
|
|
10413
|
+
[ -z "$hint" ] || echo " ${hint}." >&2
|
|
10414
|
+
elif command -v curl >/dev/null 2>&1; then
|
|
10415
|
+
body="$(curl -fsS --max-time 5 "https://${domain}/.well-known/loki-provenance.json" 2>/dev/null)" || body=""
|
|
10416
|
+
psha="$(python3 -c 'import json,sys;print(json.loads(sys.stdin.read()).get("head_sha") or "")' <<<"$body" 2>/dev/null || true)"
|
|
10417
|
+
if [ -n "$psha" ] && [ -n "$head" ] && [ "$psha" = "$head" ]; then _DD_PROV=match
|
|
10418
|
+
elif [ -n "$psha" ]; then _DD_PROV=mismatch; echo -e "${YELLOW}Provenance head_sha ${psha:0:12} differs from the deployed ${head:0:12}.${NC}" >&2; fi
|
|
10419
|
+
echo "Provenance: ${_DD_PROV}"
|
|
10420
|
+
fi
|
|
10421
|
+
if [ "$_DD_STATUS" = failed ] || [ "$_DD_TLS" = invalid ]; then return 6; fi
|
|
10422
|
+
return 0
|
|
10423
|
+
}
|
|
10424
|
+
|
|
10303
10425
|
# _deploy_try_execute <dir> <type>
|
|
10304
10426
|
# The ONLY place a deploy command is ever run. Evaluates the gate, and either
|
|
10305
10427
|
# executes + records, or REFUSES naming every failed check. Returns the deploy
|
|
@@ -10592,12 +10714,21 @@ _deploy_try_execute() {
|
|
|
10592
10714
|
fi
|
|
10593
10715
|
fi
|
|
10594
10716
|
|
|
10717
|
+
# --domain: only after a deploy that exited 0 and did not fail its health probe.
|
|
10718
|
+
local domain="${_LOKI_DEPLOY_DOMAIN:-}" dom_rc=0
|
|
10719
|
+
_DD_STATUS="" _DD_TLS="unchecked" _DD_NOTAFTER="" _DD_PROV=""
|
|
10720
|
+
if [ -n "$domain" ] && [ "$rc" -eq 0 ] && [ "$health_status" != "FAILED_HEALTH" ]; then
|
|
10721
|
+
_deploy_domain_step "$dir" "$command" "$domain" "$deployed_url" "$anchor" || dom_rc=$?
|
|
10722
|
+
[ "$_DD_STATUS" != attached ] || exec_disp="${exec_disp}; domain ${domain}"
|
|
10723
|
+
fi
|
|
10724
|
+
|
|
10595
10725
|
local rec rsha
|
|
10596
10726
|
finished_at="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
10597
10727
|
rsha="$(python3 -c 'import json,sys;print((json.load(open(sys.argv[1])).get("verification") or {}).get("hash") or "")' "$pj" 2>/dev/null || printf '')"
|
|
10598
10728
|
rec="$(_deploy_record "$dir" "$exec_disp" "$rc" "${run_id:-unknown}" "${anchor:-unknown}" \
|
|
10599
10729
|
"$anchor_state" "$health_status" "$health_url" "$rb_attempted" "$rb_exit" \
|
|
10600
|
-
"$rsha" "$started_at" "$finished_at" "${command%% *}" "$canary" "$post_rb" "$hcode" "$health_match" "$(git -C "$dir" rev-parse 'HEAD^{tree}' 2>/dev/null || true)" "$dest" "$deployed_url" "$health_src" "$env_keys" "$env_file"
|
|
10730
|
+
"$rsha" "$started_at" "$finished_at" "${command%% *}" "$canary" "$post_rb" "$hcode" "$health_match" "$(git -C "$dir" rev-parse 'HEAD^{tree}' 2>/dev/null || true)" "$dest" "$deployed_url" "$health_src" "$env_keys" "$env_file" \
|
|
10731
|
+
"$domain" "$_DD_STATUS" "$_DD_TLS" "$_DD_NOTAFTER" "$_DD_PROV")"
|
|
10601
10732
|
echo ""
|
|
10602
10733
|
if [ "$rc" -eq 0 ]; then
|
|
10603
10734
|
echo -e "${GREEN}Deploy command exited 0.${NC}"
|
|
@@ -10628,6 +10759,8 @@ _deploy_try_execute() {
|
|
|
10628
10759
|
[ "$post_rb" = "FAILED_HEALTH" ] && return 5
|
|
10629
10760
|
return 4
|
|
10630
10761
|
fi
|
|
10762
|
+
# 6: the domain could not be attached or its TLS is invalid.
|
|
10763
|
+
if [ "$rc" -eq 0 ] && [ "$dom_rc" -ne 0 ]; then return 6; fi
|
|
10631
10764
|
return "$rc"
|
|
10632
10765
|
}
|
|
10633
10766
|
|
|
@@ -10746,7 +10879,7 @@ cmd_deploy() {
|
|
|
10746
10879
|
local LOKI_DEPLOY_ALLOW_UNANCHORED=false
|
|
10747
10880
|
# Per-invocation like --execute; local so an ambient env var cannot set them.
|
|
10748
10881
|
local _LOKI_DEPLOY_HEALTH_URL="" _LOKI_DEPLOY_HEALTH_MATCH="" _LOKI_DEPLOY_AUTO_ROLLBACK=false _LOKI_DEPLOY_CANARY=false _LOKI_DEPLOY_DESTINATION=""
|
|
10749
|
-
local _LOKI_DEPLOY_ENV_FILE=""
|
|
10882
|
+
local _LOKI_DEPLOY_ENV_FILE="" _LOKI_DEPLOY_DOMAIN=""
|
|
10750
10883
|
|
|
10751
10884
|
# Arg parse (mirror cmd_preview: lenient on unknown args -> no behavior drift).
|
|
10752
10885
|
while [ $# -gt 0 ]; do
|
|
@@ -10754,7 +10887,7 @@ cmd_deploy() {
|
|
|
10754
10887
|
--help|-h|help)
|
|
10755
10888
|
echo -e "${BOLD}Loki Mode -- deploy command advisory (print-only by default)${NC}"
|
|
10756
10889
|
echo ""
|
|
10757
|
-
echo "Usage: loki deploy [--dir <path>] [--no-clip] [--execute [--canary] [--env-file FILE]] [--destination preview|staging|production] [--health-url URL [--health-match STR] [--auto-rollback]]"
|
|
10890
|
+
echo "Usage: loki deploy [--dir <path>] [--no-clip] [--execute [--canary] [--env-file FILE] [--domain HOST]] [--destination preview|staging|production] [--health-url URL [--health-match STR] [--auto-rollback]]"
|
|
10758
10891
|
echo ""
|
|
10759
10892
|
echo "Detects your project type and your installed cloud CLI (and any"
|
|
10760
10893
|
echo "CI/CD pipeline), then PRINTS the exact deploy command for YOU to run."
|
|
@@ -10854,6 +10987,15 @@ cmd_deploy() {
|
|
|
10854
10987
|
echo " step fails the deploy is not run. Values are masked as K=*** in"
|
|
10855
10988
|
echo " output; the deploy record stores env_keys (names) and env_source,"
|
|
10856
10989
|
echo " never values."
|
|
10990
|
+
echo " --domain HOST With --execute, after a deploy that exited 0 and is not FAILED_HEALTH:"
|
|
10991
|
+
echo " attach HOST (Vercel: 'vercel alias set <deployed_url> HOST'; Fly:"
|
|
10992
|
+
echo " 'fly certs add HOST'; Netlify and Cloudflare print the manual dashboard"
|
|
10993
|
+
echo " step, domain_status=manual). Then prove TLS with openssl s_client and"
|
|
10994
|
+
echo " 'openssl x509 -checkend 604800' and re-probe"
|
|
10995
|
+
echo " https://HOST/.well-known/loki-provenance.json. The record stores domain,"
|
|
10996
|
+
echo " domain_status, tls_status (valid|expiring|invalid|unchecked) and"
|
|
10997
|
+
echo " tls_not_after; no openssl means unchecked, never valid. An invalid TLS"
|
|
10998
|
+
echo " handshake or a failed attach exits 6 and prints the DNS record needed."
|
|
10857
10999
|
echo " --allow-unanchored"
|
|
10858
11000
|
echo " Proceed when the receipt records NO baseline (nothing"
|
|
10859
11001
|
echo " about this tree is proven). Never bypasses a recorded"
|
|
@@ -10914,6 +11056,16 @@ cmd_deploy() {
|
|
|
10914
11056
|
_LOKI_DEPLOY_ENV_FILE="${1#--env-file=}"
|
|
10915
11057
|
[ -n "$_LOKI_DEPLOY_ENV_FILE" ] || { echo "loki deploy --env-file requires a file path" >&2; return 1; }
|
|
10916
11058
|
;;
|
|
11059
|
+
--domain)
|
|
11060
|
+
case "${2:-}" in
|
|
11061
|
+
-*|"") echo "loki deploy --domain requires a hostname" >&2; return 1 ;;
|
|
11062
|
+
*) _LOKI_DEPLOY_DOMAIN="$2"; shift ;;
|
|
11063
|
+
esac
|
|
11064
|
+
;;
|
|
11065
|
+
--domain=*)
|
|
11066
|
+
_LOKI_DEPLOY_DOMAIN="${1#--domain=}"
|
|
11067
|
+
[ -n "$_LOKI_DEPLOY_DOMAIN" ] || { echo "loki deploy --domain requires a hostname" >&2; return 1; }
|
|
11068
|
+
;;
|
|
10917
11069
|
esac
|
|
10918
11070
|
shift
|
|
10919
11071
|
done
|
|
@@ -10931,6 +11083,18 @@ cmd_deploy() {
|
|
|
10931
11083
|
_LOKI_DEPLOY_ENV_FILE="$(cd "$(dirname -- "$_LOKI_DEPLOY_ENV_FILE")" && pwd -P)/$(basename -- "$_LOKI_DEPLOY_ENV_FILE")"
|
|
10932
11084
|
fi
|
|
10933
11085
|
|
|
11086
|
+
if [ -n "$_LOKI_DEPLOY_DOMAIN" ]; then
|
|
11087
|
+
if [ "$do_execute" != true ]; then
|
|
11088
|
+
echo "loki deploy --domain requires --execute (the advisory run attaches nothing)" >&2
|
|
11089
|
+
return 1
|
|
11090
|
+
fi
|
|
11091
|
+
_LOKI_DEPLOY_DOMAIN="$(printf '%s' "$_LOKI_DEPLOY_DOMAIN" | tr '[:upper:]' '[:lower:]')"
|
|
11092
|
+
if ! printf '%s' "$_LOKI_DEPLOY_DOMAIN" | grep -Eq '^([a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,}$'; then
|
|
11093
|
+
echo "loki deploy --domain: not a valid hostname: $_LOKI_DEPLOY_DOMAIN" >&2
|
|
11094
|
+
return 1
|
|
11095
|
+
fi
|
|
11096
|
+
fi
|
|
11097
|
+
|
|
10934
11098
|
if [ "$_LOKI_DEPLOY_AUTO_ROLLBACK" = true ] && [ -z "$_LOKI_DEPLOY_HEALTH_URL" ]; then
|
|
10935
11099
|
echo "loki deploy --auto-rollback requires --health-url (no health signal, no rollback)" >&2
|
|
10936
11100
|
return 1
|
package/autonomy/verify.sh
CHANGED
|
@@ -1175,6 +1175,7 @@ verify_secret_scan_file() {
|
|
|
1175
1175
|
'github_pat_[A-Za-z0-9_]{60,}' # GitHub fine-grained PAT
|
|
1176
1176
|
'xox[baprs]-[A-Za-z0-9-]{10,}' # Slack token (xoxb-/xoxp-/...)
|
|
1177
1177
|
'sk-[A-Za-z0-9]{20,}' # OpenAI-style secret key
|
|
1178
|
+
'sk-ant-[A-Za-z0-9_-]{20,}' # Anthropic API key (hyphenated body)
|
|
1178
1179
|
'AIza[0-9A-Za-z_-]{35}' # Google API key
|
|
1179
1180
|
'glpat-[A-Za-z0-9_-]{20,}' # GitLab personal access token
|
|
1180
1181
|
)
|
package/completions/_loki
CHANGED
|
@@ -179,6 +179,7 @@ function _loki {
|
|
|
179
179
|
'--execute[Run the deploy command if the receipt gate passes]' \
|
|
180
180
|
'--canary[With --execute: staged rollout (Vercel promote, Fly canary)]' \
|
|
181
181
|
'--env-file[With --execute: push KEY=VALUE env via Vercel, Fly, Netlify or Cloudflare (names-only record)]:env file:_files' \
|
|
182
|
+
'--domain[With --execute: attach a custom domain and prove TLS with openssl]:hostname:' \
|
|
182
183
|
'--allow-unanchored[Proceed when the receipt records no baseline]' \
|
|
183
184
|
'--health-url[Health probe URL]:url:' \
|
|
184
185
|
'--auto-rollback[Roll back on a failed health probe]' \
|
|
@@ -364,6 +365,10 @@ function _loki_start {
|
|
|
364
365
|
'--deploy[Deploy after a VERIFIED run via loki deploy --execute]' \
|
|
365
366
|
'--health-url[With --deploy: health probe URL]:url:' \
|
|
366
367
|
'--auto-rollback[With --deploy: roll back on a failed health probe]' \
|
|
368
|
+
'--destination[With --deploy: preview, staging or production]:destination:(preview staging production)' \
|
|
369
|
+
'--canary[With --deploy: canary rollout]' \
|
|
370
|
+
'--domain[With --deploy: attach this domain and prove TLS]:hostname:' \
|
|
371
|
+
'--env-file[With --deploy: env file pushed to the provider]:file:_files' \
|
|
367
372
|
'--background[Background mode]' \
|
|
368
373
|
'--bg[Background mode]' \
|
|
369
374
|
'--simple[Force simple complexity]' \
|
package/completions/loki.bash
CHANGED
|
@@ -28,7 +28,7 @@ _loki_completion() {
|
|
|
28
28
|
# If the word starts with a dash, show flags
|
|
29
29
|
# Rule: list every flag bin/loki routes (Bun/engine10 ones such as --model, --max-cost, --spec, --no-pr too), not only cmd_start's own.
|
|
30
30
|
if [[ "$cur" == -* ]]; then
|
|
31
|
-
local flags="--provider --max-iterations --parallel --background --bg --simple --complex --github --no-dashboard --sandbox --skip-memory --cost --spec --spec-first --yes --budget --attempts --model --isolation --max-cost --no-pr --explain-route --brief --worktree --pr --ship --detach --workspace --deploy --health-url --auto-rollback --resume --help"
|
|
31
|
+
local flags="--provider --max-iterations --parallel --background --bg --simple --complex --github --no-dashboard --sandbox --skip-memory --cost --spec --spec-first --yes --budget --attempts --model --isolation --max-cost --no-pr --explain-route --brief --worktree --pr --ship --detach --workspace --deploy --health-url --auto-rollback --destination --canary --domain --env-file --resume --help"
|
|
32
32
|
COMPREPLY=( $(compgen -W "${flags}" -- "$cur") )
|
|
33
33
|
return 0
|
|
34
34
|
fi
|
|
@@ -150,7 +150,7 @@ _loki_completion() {
|
|
|
150
150
|
|
|
151
151
|
deploy)
|
|
152
152
|
if [[ "$cur" == -* ]]; then
|
|
153
|
-
COMPREPLY=( $(compgen -W "--execute --destination --canary --env-file --health-url --health-match --auto-rollback --dir --no-clip --allow-unanchored --help" -- "$cur") )
|
|
153
|
+
COMPREPLY=( $(compgen -W "--execute --destination --canary --env-file --domain --health-url --health-match --auto-rollback --dir --no-clip --allow-unanchored --help" -- "$cur") )
|
|
154
154
|
return 0
|
|
155
155
|
fi
|
|
156
156
|
;;
|
package/dashboard/__init__.py
CHANGED
package/docs/CLI-REFERENCE.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# CLI reference
|
|
2
2
|
|
|
3
|
-
Generated from `loki-ts/src/cli/registry.ts` by `scripts/generate-stale-zero.sh` for v11.17.
|
|
3
|
+
Generated from `loki-ts/src/cli/registry.ts` by `scripts/generate-stale-zero.sh` for v11.17.39. Do not edit by hand.
|
|
4
4
|
Hidden and legacy-only commands are omitted; see `docs/v10/CLI-MODERN.md` for the full inventory.
|
|
5
5
|
|
|
6
6
|
| Command | Description |
|
package/docs/DEPLOYMENT.md
CHANGED
|
@@ -523,6 +523,28 @@ deliberately.
|
|
|
523
523
|
|
|
524
524
|
---
|
|
525
525
|
|
|
526
|
+
## From brief to verified URL
|
|
527
|
+
|
|
528
|
+
One command builds from a brief, deploys the result and proves what is live.
|
|
529
|
+
|
|
530
|
+
```bash
|
|
531
|
+
loki start "a todo app with login" --deploy \
|
|
532
|
+
--destination production --domain todo.example.com --env-file .env.production \
|
|
533
|
+
--health-url https://todo.example.com/health --auto-rollback --github
|
|
534
|
+
loki verify --url https://todo.example.com
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
- `loki start` runs first. Only a start that exits 0 reaches the deploy; a non-zero start prints `not deploying` and returns its own code.
|
|
538
|
+
- `--deploy` runs `loki deploy --execute` with `--destination`, `--canary`, `--env-file`, `--domain`, `--health-url`, `--health-match` and `--auto-rollback` passed through. The deploy still refuses without a VERIFIED receipt for this exact HEAD.
|
|
539
|
+
- With `--deploy`, `--env-file` is the deploy env file (key names are recorded, values are not), not a config file.
|
|
540
|
+
- `--github` runs `loki github publish` after a deploy that exited 0. A failed deploy skips it.
|
|
541
|
+
- A flag value that starts with `-` exits 2. The deploy-only flags without `--deploy` exit 2.
|
|
542
|
+
- `loki verify --url` fetches `/.well-known/loki-provenance.json` from the live host and is VERIFIED only when its signature and cited receipt both check out.
|
|
543
|
+
|
|
544
|
+
In `loki chat`, `/deploy` takes the same deploy flags, prints the full argv and waits for a y before running.
|
|
545
|
+
|
|
546
|
+
---
|
|
547
|
+
|
|
526
548
|
## Reference
|
|
527
549
|
|
|
528
550
|
| Env var | Where | Meaning |
|
package/docs/INSTALLATION.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Loki Mode, by [Autonomi](https://www.autonomi.dev/), turns a spec or an issue into a verified pull request with a receipt you can check. This page covers installing it, a first run, and the options around it.
|
|
4
4
|
|
|
5
|
-
**Version:** v11.17.
|
|
5
|
+
**Version:** v11.17.39
|
|
6
6
|
|
|
7
7
|
**Engine note:** `loki start` is the primary command. `loki start`, `loki "<task>"`, `loki owner/repo#N` and `loki quick` all run the Loki 10 engine, whatever the flag order or input form (PRD file, issue ref, task or one-word brief). The previous loop runs only on `--engine legacy`, `LOKI_ENGINE=legacy`, or for one call when a flag Loki 10 cannot honor is present. See the [user guide](v10/GUIDE.md) and the [5-minute quickstart](QUICKSTART.md).
|
|
8
8
|
|