Skip to content

wiki: ingest JobFilter product knowledge base - #31

Open
manazoid4 wants to merge 304 commits into
AgriciDaniel:mainfrom
manazoid4:main
Open

wiki: ingest JobFilter product knowledge base#31
manazoid4 wants to merge 304 commits into
AgriciDaniel:mainfrom
manazoid4:main

Conversation

@manazoid4

Copy link
Copy Markdown

Summary

  • Adds 11 new concept pages covering JobFilter's full product, design, and build context
  • Updates wiki/index.md with all new entries
  • Adds session log entry to wiki/log.md

New pages

Page Description
JobFilter Hub Central nav node for all JobFilter wiki pages
JobFilter Status Hot cache: current build state, branches, priorities
JobFilter Design System V3 tokens, typography, spacing, buttons, copy rules
JobFilter Product overview Full product map and strategy
Intake Engine Core £49/mo product detail
Vantage / Vicinity / Codex Three advantage modules
Free Tools Top-of-funnel calculator suite
JobFilter Onboarding Stages 6-stage funnel, activation = first WhatsApp ping
JobFilter Product Features Intake form, scoring engine, WhatsApp alerts, roadmap

Reviewer notes

Personal knowledge base content — no code changes, wiki markdown only.

🤖 Generated with Claude Code

@manazoid4
manazoid4 requested a review from AgriciDaniel as a code owner May 28, 2026 17:04
AgriciDaniel and others added 29 commits June 5, 2026 20:19
Two badges showed broken/stale state on the AI-Marketing-Hub private mirror:

- `public release` resolved to v1.6.0 because that is the AgriciDaniel
  public-repo state. Truthful for the public, misleading on the private
  mirror which is at v1.9.0.
- `public CI` returned shields.io "repo or workflow not found" because
  test.yml only exists on the private mirror; the public canonical has
  no workflow file yet.

Swap both for static badges anchored to private-repo URLs:

- release: static v1.9.0 -> private releases/latest
- CI: static passing -> private actions (verified: 3/3 recent runs green)

Update the footnote to make the dual-repo badge strategy explicit:
star count tracks public (shields.io constraint); release + CI are
pinned static for the private mirror until v1.7+ work promotes to the
public canonical.
Three changes to improve readability and remove dead links for anyone who
is not an AI Marketing Hub Pro member:

1. Two-versions callout: replace the technical `AI-Marketing-Hub/claude-obsidian`
   repo path (which 404s for non-members) with a link to the public org page
   github.com/AI-Marketing-Hub. The org page is publicly reachable and lets
   prospective members see the org profile + community link. Also rephrase
   both bullets in parallel ("Public open-source build" / "Community
   early-access build") and drop the path-style label in favor of a human
   anchor ("Daniel Agrici's GitHub" / "AI Marketing Hub").

2. Quick Start opening note: insert a one-line disclaimer BEFORE Option 1
   so public users see the URL swap from the start, not just under Option 2.
   Pro members can ignore the note and use the commands as-is.

3. Related Projects: fix the claude-ads link to point at the public
   github.com/AgriciDaniel/claude-ads mirror (which exists) instead of the
   private AI-Marketing-Hub/claude-ads (which 404s for non-members).
scripts/contextual-prefix.py:376 used a direct write_text() to the chunk
JSON file. A crash, SIGKILL, or ENOSPC mid-write left a half-written
chunk-NNN.json which discover_chunks() then silently skipped via the
JSONDecodeError catch at line 134. Result: silent loss of that chunk
from BM25 + embed index until the page was re-ingested.

Switch to tmp+rename using os.replace(), matching the pattern already
established in scripts/bm25-index.py:178-186 for write_index(). The
chunk JSON is now atomic at the filesystem boundary; crashes leave
either the old chunk intact or the new chunk fully written.

Verification: kill -9 of an in-flight contextual-prefix --build now
leaves zero corrupted JSON files in .vault-meta/chunks/.

Findings closed: B2 from docs/audits/v1.9.0-pre-public-promotion-audit-2026-05-18.md.
…dius (B1+H1)

The PostToolUse auto-commit hook used:
  git add wiki/ .raw/ .vault-meta/
  git diff --cached --quiet
  git commit -m "wiki: auto-commit ..."

When the user had something else manually staged (TEST.md), the diff-cached
check returned non-empty and the commit swept TEST.md into the "wiki:
auto-commit" message. User intent buried under generic commit. The bug
self-demonstrated during this very fix cycle: the prior commit
(workspace-visual.json untracking, ought to have stayed staged for an
explicit chore commit) was swept up by the OLD hook under a wiki:
auto-commit message before this fix landed.

New hook command:
  git add -- wiki/ .raw/ .vault-meta/
  git diff --cached --quiet -- wiki/ .raw/ .vault-meta/
  git commit -m "..." -- wiki/ .raw/ .vault-meta/

Three scoping changes:
1. add: explicit -- separator (H1, defends against a future wiki/-flag.md
   filename being interpreted as a flag).
2. diff-cached: scoped pathspec, so the check only fires when wiki/-class
   paths have staged changes.
3. commit: explicit -- pathspec, so only wiki/-class staged changes are
   committed; anything else the user staged stays staged for their own
   commit.

H3 (logged-error retry/surface) was previously addressed in v1.7.1 via
the .vault-meta/hook.log line that survives this change. The audit's
recommended counter + wiki-lint surface is deferred to v1.9.1.

Verification: python3 -c "import json; json.load(open('hooks/hooks.json'))"
parses OK; grep confirms the 3 critical pathspec changes.

Findings closed: B1 + H1 from docs/audits/v1.9.0-pre-public-promotion-audit-2026-05-18.md.
The 548d294 commit fixed README's two-versions callout, Quick Start
disclaimer, and Related Projects claude-ads link to be reachable by
public viewers (whose private repo URLs 404). The fix did NOT cascade
to other user-facing surfaces. This commit completes the cascade.

Files updated:
- docs/install-guide.md: version 1.6.0 -> 1.9.0; top-line public canonical
  + early-access mirror split; new line-6 disclaimer mirroring README's
  Quick Start pattern; Support section bullets repointed to public.
- CONTRIBUTING.md: clone command repointed to user fork of public
  canonical; Pro-member backport note added.
- AGENTS.md: plugin homepage split into public canonical + community
  early-access mirror.
- GEMINI.md: same split as AGENTS.md.
- ATTRIBUTION.md: Repository field split into public canonical +
  community early-access mirror.
- .claude-plugin/plugin.json: homepage + repository repointed to public
  canonical (these surface in Claude plugin UI; public visitors must
  click through, not 404).
- .claude-plugin/marketplace.json: plugins[0].homepage + repository same
  swap as plugin.json. The marketplace catalog slug name (line 2,
  ai-marketing-hub-claude-obsidian) is the Pro marketplace identifier
  and stays.
- docs/releases/v1.6.0.md: 3 raw.githubusercontent.com image URLs
  swapped from AI-Marketing-Hub/claude-obsidian to AgriciDaniel/claude-obsidian
  (verified all 3 images exist on the public main branch via gh api
  before swap; sizes 138752, 102970, 175190 bytes).

Acceptance: rg -n 'AI-Marketing-Hub/claude-obsidian' across these 8 files
returns only matches inside explicit private-mirror disclaimers (the
top-of-file callout in install-guide.md, the Pro-member note in
CONTRIBUTING.md). Bare canonical references: zero. raw.githubusercontent
private-URL refs: zero.

Findings closed: F1, F2, F3, F4, F5 from docs/audits/v1.9.0-pre-public-promotion-audit-2026-05-18.md.
…ut (W3)

Two parts:

1. Add .obsidian/workspace-visual.json to .gitignore. The file is
   host-specific UI state (panel positions, last-open file) that
   creates noisy diffs at clone time and post-edit. workspace-mobile.json
   was already gitignored on the same rationale; workspace-visual.json
   had been overlooked. The file was untracked from the index in an
   earlier auto-commit (bc41e29) before the hook fix landed; this commit
   ensures it stays untracked.

2. Append the fix-cycle closeout section to docs/audits/v1.9.0-pre-public-promotion-audit-2026-05-18.md.
   Records: per-finding status table, re-scored dimensions
   (Security 94/Privacy 94/Data 88/References 96/Files 86; raw avg
   91.6; ship verdict GREEN), 4-commit plan, acceptance verification
   commands, and v1.9.1 + v1.9.2 follow-up rationale for deferred
   findings (H2, H4, S1-S4, Data M1-M4, References M1-M2, Files M1-M4,
   W1 wiki/meta relocation).

W1 was reassessed and DEFERRED with rationale: 9 of 12 release-session
notes have incoming wikilinks; moving them would create 6+ new dead
links. The Privacy agent's "intentional case-study material" framing
was the right lens. v1.9.2 will handle relocation alongside the wiki
dead-link cleanup (References M1+M2) so the wikilink graph is updated
in one pass.

W2 was reassessed: 3 of 4 flagged files contained only legitimate author
self-reference (agricidaniel.com blog, @AgriciDaniel YouTube, github.com/AgriciDaniel
profile — canonical public identity, not leaks). The 4th file
(wiki/canvases/youtube-explainer.canvas) had 2 AI-Marketing-Hub
private-URL refs that were swapped under the canonical-URL cascade
(committed via the auto-commit hook as bf4d94b + d2afcbf).

Findings closed: W3.
Findings deferred-with-rationale: W1 (v1.9.2), W2 reassessed as non-leak.
… (H4+S2)

Two safety polish items from v1.9.0 audit closure.

H4 — stale-lock reaper between sessions:
SessionStart now runs `bash scripts/wiki-lock.sh clear-stale --max-age 3600`
on every startup/resume. Locks orphaned by a crashed batch ingest get
reaped automatically on the next session, not just on operator demand.
The 3600s default is intentionally conservative (matches the admin
reaper threshold per wiki-lock.sh header docs) so it cannot accidentally
release a lock held by another in-flight session.

S2 — opt-out gate for PostToolUse auto-commit:
The hook now exits early if `.vault-meta/auto-commit.disabled` exists.
Default behavior unchanged for existing users; per-vault opt-out is one
`touch` away. Useful for shared repos, CI runs, or any scenario where
the operator wants to commit manually.

Verification: JSON parses; live test of clear-stale on a missing
LOCK_DIR is a no-op via ensure_dirs(); opt-out gate test:
`touch .vault-meta/auto-commit.disabled` then trigger a Write — no
auto-commit fires.

Findings closed: H4, S2 from docs/audits/v1.9.0-pre-public-promotion-audit-2026-05-18.md.
Two lock-primitive hardening items.

Data M3 — symlink canonicalization in validate_path():
Previously the function rejected literal `..` segments and absolute
paths, but did not canonicalize symlinks. A symlink inside wiki/
resolving outside VAULT_ROOT could escape the lock-namespace check
and (combined with downstream filesystem operations) reach outside
the vault. Now resolves via python3 os.path.realpath and rejects any
path whose canonical form is outside commonpath(VAULT_ROOT, target).

Cross-platform: uses python3 not realpath because GNU coreutils and
macOS BSD `realpath` have incompatible flag semantics. Only runs the
check if python3 is on PATH (graceful no-op fallback otherwise — the
literal `..` reject is the floor).

Live test: `ln -s /tmp/foo ./escape && bash scripts/wiki-lock.sh
acquire escape/x.md` correctly errors with "path resolves outside
vault via symlink: escape/x.md".

Data M4 — `.vault-meta/locks/.gitkeep`:
The directory existed lazily via `ensure_dirs()` on first acquire,
which meant fresh clones had no visible locks/ dir until the first
wiki-lock invocation. Discoverability gap, not a correctness one.

Two changes:
1. `.gitignore` pattern changed from `.vault-meta/locks/` (which
   excludes the directory itself, preventing negation patterns from
   re-including children) to `.vault-meta/locks/*` (excludes only
   contents). This is the documented git workaround for the "cannot
   re-include a file if its parent is excluded" constraint.
2. `!.vault-meta/locks/.gitkeep` whitelist + the .gitkeep file itself
   (with a comment explaining the purpose).

Net: .lock files still ignored, .gitkeep tracked, dir visible on
fresh clone.

Findings closed: Data M3, Data M4 from docs/audits/v1.9.0-pre-public-promotion-audit-2026-05-18.md.
…ost assert (Data M1+S4)

Data M1 — rerank.py warning routes to hook.log:
When the embed-cache lock is unavailable after 3 tries, the WARN line
now also appends to .vault-meta/hook.log with a UTC timestamp, in
addition to the existing stderr line. Stderr alone is invisible to most
callers (subprocess captures, hook contexts); hook.log is the canonical
operator-visible log already used by the auto-commit hook.

The append-to-hook.log is wrapped in `try: ... except OSError: pass` so
a logging failure never blocks the rerank from completing — the temp +
os.replace pattern provides write atomicity even without the embed-cache
lock or the audit log.

S4 — setup-retrieve.sh refuses off-localhost ollama:
If $OLLAMA_URL is overridden to point off-localhost, refuse to probe
unless --allow-remote-ollama is passed. Mirrors the existing
scripts/tiling-check.py:351 gate. Closes a defense-in-depth gap where
a malicious env var could redirect probes to an attacker-controlled
endpoint. The case statement allows http://127.0.0.1:*,
http://localhost:*, and http://[::1]:* without consent; everything else
falls through to the consent check.

Verification: rerank.py compiles; setup-retrieve.sh bash -n clean;
grep confirms both gates in place.

Findings closed: Data M1, S4 from docs/audits/v1.9.0-pre-public-promotion-audit-2026-05-18.md.
…ANGELOG (H2+S3)

SECURITY.md gains a "Threat model: single-tenant vault" section
documenting three intentional design choices and the mitigations for
shared-host deployments:

1. wiki-lock.sh release is unconditional (acquire/release typically
   from separate bash invocations on the same host; PID-binding would
   fail in normal use). Shared-host mitigation: restrict filesystem
   permissions on .vault-meta/locks/ to the vault owner.

2. PostToolUse auto-commit hook runs as the user invoking Claude Code
   and commits wiki/, .raw/, .vault-meta/ to the local repo on every
   Write/Edit. Per-vault opt-out: touch .vault-meta/auto-commit.disabled.

3. Cross-process resource access (lockfiles, transport snapshots,
   embed cache) governed by filesystem permissions, not application-
   layer identity. Standard Linux/macOS permissions are the trust
   boundary.

Closes the documentation gap the v1.9.0 audit flagged: the design
choices are correct for single-tenant, but operators in shared-host
or shared-CI scenarios deserve explicit notice. Folds together H2
(cross-process lock release documentation) and S3 (multi-tenant
caveat) into one coherent section.

Version bump 1.9.0 → 1.9.1 across plugin.json + marketplace.json.
CHANGELOG entry summarizes the 6 closed HIGH/MEDIUM + 3 closed LOW
items, with rescore (91.6 → ~94 raw average) and explicit list of
items deferred to v1.9.2 (Data M2 GC, W1 wiki/meta relocation, S1
Excalidraw checksum, GROW note 7th verifier cut).

Findings closed: H2, S3 from docs/audits/v1.9.0-pre-public-promotion-audit-2026-05-18.md.
Pre-push verifier on the v1.9.1 audit-closure delta returned FIX-AND-SHIP
with 2 MEDIUM findings. Both closed in this commit.

V1 — IPv6 loopback bash glob pattern was broken:
`http://[::1]:*` in a case statement treats `[::1]` as a POSIX character
class (matching a single character that is `:` or `1`), not a literal
URL prefix. Legit IPv6 loopback URLs would have fallen through to the
"remote, require --allow-remote-ollama" branch — usability bug, not a
security regression (safe default still safe).

Fix: quote the bracket-bearing pattern as `"http://[::1]:"*`. Verified
all three localhost variants (127.0.0.1, localhost, [::1]) now match
LOCAL; non-localhost (203.0.113.5) still matches REMOTE.

V2 — README static badges still at v1.9.0:
5 occurrences in README.md (release badge, Two-versions callout latest,
badge-pinning footnote, architecture-tree skill count, references
section). The v1.9.1 version bump in plugin.json + marketplace.json +
CHANGELOG.md didn't cascade to the static README badges that don't get
their data live from shields.io.

Fix: bump all 5 to v1.9.1. This is precisely the class of bug the v1.9.0
audit GROW note proposed adding to agents/verifier.md as a 7th always-
check cut (cross-file string consistency). Catching it pre-push instead
of post-push confirms the proposed verifier upgrade has real value;
that upgrade is still tracked for v1.9.2.

Verifier-deferred findings (V3 substring grep tightening, V4 TOCTOU
comment) ride into v1.9.2.

Verification: bash -n + live case-pattern test for V1; rg "v1\.9\.0"
README.md returns empty for V2; make test green.
…tness (v1.9.2)

Prompt caching (the only Anthropic API call site):
- attach cache_control only above the Haiku 4.5 floor (HAIKU_CACHE_MIN_CHARS=16384,
  ~4096 tokens); below it the API ignores the marker, so the prior unconditional
  marker was a no-op that misled the reader. Extracted as pure cache_control_for().
- add per-call cache telemetry (cache_creation/read_input_tokens; integers only,
  never page content -- preserves the v1.7.1 data-egress posture).
- document the sequential-loop invariant that cache reads depend on.

Path-handling robustness:
- explicit missing page path now exits 3 (was: silent exit 0); out-of-vault path
  exits 2 with a message (was: a raw ValueError traceback). --all unaffected.
- remove dead EXIT_NO_ADDRESS constant + docstring; rename shadowed prefix->progress.

Tests/docs:
- replace a tautological test with a mocked payload-shape integration test
  (cache_control by body size + one-line truncation). make test = 9 suites green.
- CHANGELOG [1.9.2]; bump plugin.json + marketplace.json to 1.9.2; README badge +
  early-access version + CONTRIBUTING suite count updated.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Flip README/docs framing so the public build (AgriciDaniel/claude-obsidian)
is the default install everywhere; reposition AI Marketing Hub Pro as
early-access to in-development features rather than the default.

- marketplace.json -> public form: add $schema, name agricidaniel-claude-obsidian,
  drop "private mirror / early access" text, remove load-ignored
  recommendedCompanions field. Passes `claude plugin validate` clean.
- Correct the plugin install slug to claude-obsidian@agricidaniel-claude-obsidian
  everywhere (matches marketplace.json name; verified against `claude plugin list`,
  which shows slugs derive from the marketplace name field, not owner-repo casing).
  Pro swap notes invert to claude-obsidian@ai-marketing-hub-claude-obsidian.
- README: live Release + CI badges on AgriciDaniel public; two-ways callout,
  Quick Start, Option 2, FAQ, uninstall all present public as default; Skool Pro
  link added; test-suite count fixed (8 -> 9); SECURITY.md wording clarified.
- install-guide.md, CONTRIBUTING.md, .cursor/.windsurf/.github copilot configs:
  public canonical as primary; PRs target public.
- Add SSS+ files: CITATION.cff, PRIVACY.md, CODEOWNERS, .github/FUNDING.yml.
- Neutralize internal tone in .raw ecosystem research.
- SEO/GEO pass (from RESEARCH-MASTER, DataForSEO-backed): H1 leads with
  "Self-Organizing AI Second Brain"; intro captures "AI second brain", "AI
  notetaker", "AI note-taking", "PKM", "Notion alternative" naturally; 4 verbatim
  GEO Q&As added to the FAQ (best AI second brain / build a second brain with AI /
  connect Claude to Obsidian / Notion alternative) for AI Overview + Perplexity
  citation. No keyword stuffing; brand "claude obsidian" already ranks #1.

Gates: secret scan clean (tree + 55-commit history), make test 9/9 suites,
plugin validate clean, fresh verifier agent SHIP (0 BLOCKER / 0 HIGH).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Branded pixel-arcade social preview (GitHub recommended 1280x640, 360KB)
derived from the existing cover. Upload via repo Settings -> Social preview.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants