Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .vault/hooks/lib-hook-utils.sh
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ get_approved_tags() {
warn "Tags file not found at ${TAGS_FILE}. Skipping tag validation."
return
fi
grep -E '^\- `[a-z]+/[a-z0-9-]+`' "${VAULT_ROOT}/${TAGS_FILE}" | sed 's/^- `//' | sed 's/`.*//'
grep -E '^\- `[a-z][a-z0-9-]*/[a-z0-9-]+`' "${VAULT_ROOT}/${TAGS_FILE}" | sed 's/^- `//' | sed 's/`.*//'
}

# ==============================================================================
Expand Down
6 changes: 5 additions & 1 deletion .vault/scripts/audits/audit-tags.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ cmd_tag_audit() {
local approved_tags_file
approved_tags_file=$(mktemp)
if [[ -f "${TAGS_FILE}" ]]; then
grep -oE '`[a-z][a-z0-9-]*/[a-z][a-z0-9-]*`' "${TAGS_FILE}" | sed 's/`//g' | sort -u > "$approved_tags_file"
# Anchored to bullet-list lines only, matching the hook's loader —
# an unanchored grep also picks up `prefix/value` in this file's
# own descriptive prose as if it were a real approved tag.
grep -E '^\- `[a-z][a-z0-9-]*/[a-z0-9-]+`' "${TAGS_FILE}" \
| sed 's/^- `//' | sed 's/`.*//' | sort -u > "$approved_tags_file"
local approved_count
approved_count=$(wc -l < "$approved_tags_file" | tr -d ' ')
ok "Loaded ${approved_count} approved tags"
Expand Down
114 changes: 114 additions & 0 deletions .vault/scripts/tests/test-tag-regex.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#!/usr/bin/env bash
# Regression test for HR-003 rejecting the entire source-type/ tag category.
#
# get_approved_tags() in .vault/hooks/lib-hook-utils.sh required the tag
# prefix to match [a-z]+ (letters only), so no bullet under a hyphenated
# prefix heading (source-type/ is the only one in the taxonomy) ever
# entered the approved set. A page tagged only source-type/article was
# rejected by the pre-commit hook with "No approved tags found", despite
# the tag being documented in tags.md and passing HR-009's own notation
# check (issue #39).
#
# Also covers the secondary bug: audit-tags.sh's approved-tag count was
# inflated by an unanchored grep matching the `prefix/value` example in
# this file's own descriptive prose.
#
# Run: bash .vault/scripts/tests/test-tag-regex.sh
# Exit: 0 on PASS, non-zero on any FAIL.

set -euo pipefail

VAULT_ROOT="$(git rev-parse --show-toplevel)"
FIXTURE_DIR="$(mktemp -d)"
trap 'rm -rf "$FIXTURE_DIR"' EXIT

fail() {
echo "FAIL: $*" >&2
exit 1
}

TODAY="$(date +%Y-%m-%d)"

# ------------------------------------------------------------------
# Build a minimal vault clone with its own git repo and the real
# pre-commit hook installed.
# ------------------------------------------------------------------
mkdir -p "$FIXTURE_DIR/wiki/concepts" "$FIXTURE_DIR/memory/notes" \
"$FIXTURE_DIR/memory/logs" "$FIXTURE_DIR/memory/decisions"
cp -r "$VAULT_ROOT/.vault" "$FIXTURE_DIR/.vault"

cat > "$FIXTURE_DIR/wiki/index.md" <<EOF
---
title: "Vault Index"
type: index
created: ${TODAY}
updated: ${TODAY}
status: active
tags:
- type/index
---

# Vault Index
EOF
printf '## [%s] init | Vault Initialized\n' "$TODAY" > "$FIXTURE_DIR/wiki/log.md"

git -C "$FIXTURE_DIR" init -q
git -C "$FIXTURE_DIR" config user.name "Tag Regex Tester"
git -C "$FIXTURE_DIR" config user.email "tag-regex-tester@example.com"
git -C "$FIXTURE_DIR" add -A
git -C "$FIXTURE_DIR" -c core.hooksPath=/dev/null commit -q -m seed
bash "$FIXTURE_DIR/.vault/scripts/vault-tools.sh" init-hooks >/dev/null

# ------------------------------------------------------------------
# Assert: a page tagged only source-type/article commits successfully
# through the real pre-commit hook.
# ------------------------------------------------------------------
cat > "$FIXTURE_DIR/wiki/concepts/hyphen-prefix.md" <<EOF
---
title: "Hyphenated Prefix Tag Page"
type: concept
created: ${TODAY}
updated: ${TODAY}
status: draft
tags:
- source-type/article
---

# Hyphenated Prefix Tag Page
EOF
(
cd "$FIXTURE_DIR" || exit 1
bash .vault/scripts/vault-tools.sh index-update >/dev/null
)

rc=0
output="$(cd "$FIXTURE_DIR" && git add -A && git commit -m "test: source-type tag" 2>&1)" || rc=$?
[[ "$rc" -eq 0 ]] || fail "commit with only a source-type/* tag was blocked (rc=${rc}): ${output}"
echo "$output" | grep -qE '\[HR-003\]|No approved tags found' \
&& fail "HR-003 violation reported for an approved source-type/* tag"

# ------------------------------------------------------------------
# Assert: get_approved_tags() in the real vault recognizes every
# documented source-type/* tag.
# ------------------------------------------------------------------
approved="$(
cd "$VAULT_ROOT" || exit 1
VAULT_ROOT="$VAULT_ROOT" TAGS_FILE=".vault/rules/tags.md" bash -c '
source .vault/hooks/lib-hook-utils.sh
get_approved_tags
'
)"
echo "$approved" | grep -qx "source-type/article" \
|| fail "get_approved_tags() does not recognize source-type/article"

# ------------------------------------------------------------------
# Assert: tag-audit's approved count matches a hand count of taxonomy
# bullets (not inflated by the unanchored-grep prose match).
# ------------------------------------------------------------------
hand_count="$(grep -cE '^\- `[a-z][a-z0-9-]*/[a-z0-9-]+`' "$VAULT_ROOT/.vault/rules/tags.md")"
audit_output="$(cd "$VAULT_ROOT" && bash .vault/scripts/vault-tools.sh tag-audit 2>&1)"
reported_count="$(echo "$audit_output" | grep -oE 'Loaded [0-9]+ approved tags' | grep -oE '[0-9]+')"
[[ "$reported_count" == "$hand_count" ]] \
|| fail "tag-audit reported ${reported_count} approved tags, hand count is ${hand_count}"

echo "PASS: source-type/* tags are approved and tag-audit's count is accurate"
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

- **Vault Name**: `{{VAULT_NAME}}`
- **Organization**: `{{ORG_NAME}}`
- **Vault Version**: `0.5.0`
- **Vault Version**: `0.6.0`
- **Initialized**: `{{INIT_DATE}}`

## Architecture
Expand Down
14 changes: 13 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.6.0] - 2026-07-08

### Added

- `vault-tools.sh index-update` — incremental index maintenance: parses the
Expand Down Expand Up @@ -93,6 +95,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
`set -o pipefail` the resulting 141 turned a successful match into a false
HR-008 violation. Registration is now checked with a bash literal substring
match — deterministic and fork-free.
- `get_approved_tags()` in `.vault/hooks/lib-hook-utils.sh` required the tag
prefix to be pure letters, so HR-003 rejected the entire documented
`source-type/` category — the only hyphenated prefix in the taxonomy — even
though the tags pass HR-009's own notation check. A page tagged only
`source-type/article` was blocked with "No approved tags found." The
prefix pattern now matches hyphens, consistent with HR-009. Also fixed
`audit-tags.sh`'s unanchored tag-extraction grep, which inflated its
approved-tag count by matching the `` `prefix/value` `` example in the
taxonomy file's own descriptive prose (#39).

## [0.5.0] - 2026-07-07

Expand Down Expand Up @@ -321,7 +332,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `docs/rules-customization.md` — creating new rules, industry-specific templates
- Architecture diagrams embedded in README (`docs/architecture.png`, `docs/vaults.png`)

[Unreleased]: https://github.com/galimba/agentic-memory-vault/compare/v0.5.0...HEAD
[Unreleased]: https://github.com/galimba/agentic-memory-vault/compare/v0.6.0...HEAD
[0.6.0]: https://github.com/galimba/agentic-memory-vault/compare/v0.5.0...v0.6.0
[0.5.0]: https://github.com/galimba/agentic-memory-vault/compare/v0.4.0...v0.5.0
[0.4.0]: https://github.com/galimba/agentic-memory-vault/compare/v0.3.0...v0.4.0
[0.3.0]: https://github.com/galimba/agentic-memory-vault/compare/v0.2.0...v0.3.0
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

- **Vault Name**: `{{VAULT_NAME}}` <!-- Replace during initialization -->
- **Organization**: `{{ORG_NAME}}` <!-- Replace during initialization -->
- **Vault Version**: `0.5.0`
- **Vault Version**: `0.6.0`
- **Initialized**: `{{INIT_DATE}}` <!-- Replace during initialization -->
- **Primary Agent Platform**: `{{PLATFORM}}` <!-- claude-code | codex | copilot | cursor | custom -->

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
A structured, agent-first knowledge base template for organizations using AI agents alongside human teams.

[![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE)
![Version](https://img.shields.io/badge/version-0.5.0-green)
![Version](https://img.shields.io/badge/version-0.6.0-green)

## What Is This

Expand Down
1 change: 1 addition & 0 deletions docs/roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ community input on design questions before implementation begins.

| Version | Highlights |
|---------|-----------|
| v0.6.0 | Index maintenance (`index-update`, `index-split`), `verify-sources`, `blame`, `consolidate`, the `MEMORY.md` root pointer with `memory-refresh`, SR-016 multi-agent namespacing, RFC 2119 rule-language pass, and a freshness-model decision record closing decay scoring and lifecycle tiers as adopter customizations |
| v0.5.0 | Working CI (fixed a workflow that failed GitHub's validation and had failed every run since v0.4.0), honest `doctor` exit codes, a script test suite wired into CI, the `index-rebuild` "Other" section fix, `evaluation` type schema alignment, a documentation drift sweep, and the first shipped agent skill (`vault-ops`) with its `skill-manifest` generator |
| v0.4.0 | Instance scaffolding: `init.sh` instance phase, instance README and onboarding templates, 7 init placeholders, `.vault/.initialized` idempotency guard |
| v0.3.0 | HR-014: No file deletion — agents must archive instead of delete |
Expand Down
Loading