← back to Tk 10965 Zero Price Analysis
make zero-price canary scheduler-visible
2a6ecb4e03e1e56a86d3622658366c23a64a8225 · 2026-08-30 14:31:26 -0700 · Steve Abrams
Files touched
M tk10964-canary-guard/README.mdM tk10964-canary-guard/check.mjsA tk10964-canary-guard/com.steve.zero-price-orderable-canary.plistM tk10964-canary-guard/test.mjs
Diff
commit 2a6ecb4e03e1e56a86d3622658366c23a64a8225
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Sun Aug 30 14:31:26 2026 -0700
make zero-price canary scheduler-visible
---
tk10964-canary-guard/README.md | 4 ++++
tk10964-canary-guard/check.mjs | 10 +++++++-
.../com.steve.zero-price-orderable-canary.plist | 28 ++++++++++++++++++++++
tk10964-canary-guard/test.mjs | 5 +++-
4 files changed, 45 insertions(+), 2 deletions(-)
diff --git a/tk10964-canary-guard/README.md b/tk10964-canary-guard/README.md
index 3bb528f..d17c6cf 100644
--- a/tk10964-canary-guard/README.md
+++ b/tk10964-canary-guard/README.md
@@ -8,3 +8,7 @@ the cause.
Use `--fixture fixtures/mixed.json` for a network-free end-to-end output test.
Live mode performs GraphQL queries only and writes one local JSON status file.
+
+Exit codes are scheduler-visible: `0` PASS, `2` WARN, `3` FAIL, and `1` for
+transport/runtime failure. The installed LaunchAgent runs daily at 06:35 local
+time under `com.steve.zero-price-orderable-canary`.
diff --git a/tk10964-canary-guard/check.mjs b/tk10964-canary-guard/check.mjs
index a1b9e39..8a93b81 100644
--- a/tk10964-canary-guard/check.mjs
+++ b/tk10964-canary-guard/check.mjs
@@ -56,6 +56,12 @@ function writeResult(result) {
console.log(`${result.verdict}: ${result.zero_price_orderable} zero-price-orderable of ${result.searched_active_unique} uniquely searched active`);
}
+export function exitCodeFor(result) {
+ if (result.verdict === 'PASS') return 0;
+ if (result.verdict === 'WARN') return 2;
+ return 3;
+}
+
async function liveProducts() {
const env = fs.readFileSync('/Users/macstudio3/Projects/secrets-manager/.env', 'utf8');
const val = key => (env.match(new RegExp(`^${key}=(.*)$`, 'm')) || [])[1]?.trim();
@@ -86,7 +92,9 @@ async function liveProducts() {
async function main() {
const fixtureArg = process.argv.indexOf('--fixture');
const products = fixtureArg >= 0 ? JSON.parse(fs.readFileSync(process.argv[fixtureArg + 1], 'utf8')) : await liveProducts();
- writeResult(summarize(products));
+ const result = summarize(products);
+ writeResult(result);
+ process.exitCode = exitCodeFor(result);
}
if (process.argv[1] && path.resolve(process.argv[1]) === path.resolve(new URL(import.meta.url).pathname)) {
diff --git a/tk10964-canary-guard/com.steve.zero-price-orderable-canary.plist b/tk10964-canary-guard/com.steve.zero-price-orderable-canary.plist
new file mode 100644
index 0000000..99f275e
--- /dev/null
+++ b/tk10964-canary-guard/com.steve.zero-price-orderable-canary.plist
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>Label</key>
+ <string>com.steve.zero-price-orderable-canary</string>
+ <key>ProgramArguments</key>
+ <array>
+ <string>/opt/homebrew/bin/node</string>
+ <string>/Users/macstudio3/.claude/skills/zero-price-orderable-canary/check.mjs</string>
+ </array>
+ <key>RunAtLoad</key>
+ <false/>
+ <key>StartCalendarInterval</key>
+ <dict>
+ <key>Hour</key>
+ <integer>6</integer>
+ <key>Minute</key>
+ <integer>35</integer>
+ </dict>
+ <key>ProcessType</key>
+ <string>Background</string>
+ <key>StandardOutPath</key>
+ <string>/tmp/zero-price-orderable-canary.log</string>
+ <key>StandardErrorPath</key>
+ <string>/tmp/zero-price-orderable-canary.err</string>
+</dict>
+</plist>
diff --git a/tk10964-canary-guard/test.mjs b/tk10964-canary-guard/test.mjs
index 0b6b353..6d316ae 100644
--- a/tk10964-canary-guard/test.mjs
+++ b/tk10964-canary-guard/test.mjs
@@ -1,7 +1,7 @@
#!/usr/bin/env node
import assert from 'node:assert/strict';
import fs from 'node:fs';
-import { SEARCHES, inScope, summarize } from './check.mjs';
+import { SEARCHES, exitCodeFor, inScope, summarize } from './check.mjs';
const products = JSON.parse(fs.readFileSync(new URL('./fixtures/mixed.json', import.meta.url)));
const result = summarize(products, '2026-08-30T00:00:00.000Z');
@@ -14,4 +14,7 @@ assert.equal(result.zero_price_orderable, 2);
assert.deepEqual(result.by_vendor, { 'Fentucci Naturals': 1, 'Phillipe Romano': 1 });
assert.deepEqual(result.mechanism, { qty_2026: 2, deny: 2, tracked: 2 });
assert.equal(result.verdict, 'WARN');
+assert.equal(exitCodeFor({ verdict: 'PASS' }), 0);
+assert.equal(exitCodeFor({ verdict: 'WARN' }), 2);
+assert.equal(exitCodeFor({ verdict: 'FAIL' }), 3);
console.log('PASS: broad searches, Fentucci blind spot, dedupe, defect predicate, and controls');
← db7f993 snapshot live zero-price evidence before canary install
·
back to Tk 10965 Zero Price Analysis
·
auto-data-snapshot: 2026-08-30T14:42:48 (4 data files) — tk1 7e1dd31 →