aid-installer 1.1.0 → 2.0.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.
@@ -1695,6 +1695,8 @@ _prune_tool_dirs() {
1695
1695
 
1696
1696
  # ------------------------------------------------------------------
1697
1697
  # Per-tool scoping: which native dirs + which aid/ root to walk.
1698
+ # New layout (work-005/delivery-001): codex is unified under .codex/;
1699
+ # cursor and antigravity no longer ship rules/ dirs.
1698
1700
  # ------------------------------------------------------------------
1699
1701
  case "$tool" in
1700
1702
  claude-code)
@@ -1703,15 +1705,15 @@ _prune_tool_dirs() {
1703
1705
  _prune_aid_subtree "${target}/.claude/aid"
1704
1706
  ;;
1705
1707
  codex)
1706
- # .codex ships only agents/; .agents ships skills/ + aid/ subtree.
1708
+ # New unified layout: everything under .codex/ (agents, skills, aid).
1707
1709
  _prune_native_dir "${target}/.codex/agents"
1708
- _prune_native_dir "${target}/.agents/skills"
1709
- _prune_aid_subtree "${target}/.agents/aid"
1710
+ _prune_native_dir "${target}/.codex/skills"
1711
+ _prune_aid_subtree "${target}/.codex/aid"
1710
1712
  ;;
1711
1713
  cursor)
1714
+ # rules/ dir removed from new layout; agents/skills/aid remain.
1712
1715
  _prune_native_dir "${target}/.cursor/agents"
1713
1716
  _prune_native_dir "${target}/.cursor/skills"
1714
- _prune_native_dir "${target}/.cursor/rules"
1715
1717
  _prune_aid_subtree "${target}/.cursor/aid"
1716
1718
  ;;
1717
1719
  copilot-cli)
@@ -1721,7 +1723,8 @@ _prune_tool_dirs() {
1721
1723
  _prune_aid_subtree "${target}/.github/aid"
1722
1724
  ;;
1723
1725
  antigravity)
1724
- _prune_native_dir "${target}/.agent/rules"
1726
+ # rules/ dir removed from new layout; agents/skills/aid remain.
1727
+ _prune_native_dir "${target}/.agent/agents"
1725
1728
  _prune_native_dir "${target}/.agent/skills"
1726
1729
  _prune_aid_subtree "${target}/.agent/aid"
1727
1730
  ;;
@@ -1735,6 +1738,138 @@ _prune_tool_dirs() {
1735
1738
  unset -f _in_set _prune_native_dir _prune_aid_subtree
1736
1739
  }
1737
1740
 
1741
+ # ---------------------------------------------------------------------------
1742
+ # Retired-root migration sweep (FR7/FR7a)
1743
+ # ---------------------------------------------------------------------------
1744
+
1745
+ # _migrate_retired_layout <target> <tool>
1746
+ #
1747
+ # Complete-replacement migration: removes AID-owned content from the static
1748
+ # list of retired AID roots that no longer exist in the new bundle layout.
1749
+ # Called from install_tool BEFORE _prune_tool_dirs (same aid update pass).
1750
+ #
1751
+ # Retired roots swept per tool:
1752
+ # codex: .agents/ (split layout retired)
1753
+ # cursor: .cursor/rules/ (rules dir retired)
1754
+ # antigravity: .agent/rules/ (rules dir retired)
1755
+ # all tools: .cursor/rules/, .agent/rules/ are cursor/antigravity only
1756
+ #
1757
+ # Ownership markers applied (content-isolation.md rules 1+2):
1758
+ # Marker 1: filename starts with "aid-" (tool-native dir files)
1759
+ # Marker 2: lives inside an "aid/" subtree
1760
+ #
1761
+ # Marker 3 (AID:BEGIN/END region in root files) is NOT touched here;
1762
+ # that is handled by _copy_root_agent_file exclusively.
1763
+ #
1764
+ # User content (no marker) is NEVER removed.
1765
+ # Idempotent: a no-op when the retired path is already absent.
1766
+ # Returns count of retired items removed (written to _MIGRATE_RETIRED_COUNT).
1767
+ _migrate_retired_layout() {
1768
+ local target="$1"
1769
+ local tool="$2"
1770
+ local list_only="${3:-0}" # 1 = dry-run enumeration only (no removals)
1771
+ _MIGRATE_RETIRED_COUNT=0
1772
+
1773
+ # Return 1 if a file is AID-owned (marker 1 or 2); 0 if user content.
1774
+ _is_aid_owned_file() {
1775
+ local f="$1"
1776
+ local base
1777
+ base="$(basename "$f")"
1778
+ # Marker 1: aid- prefix.
1779
+ if [[ "$base" == aid-* ]]; then return 0; fi
1780
+ # Marker 2: lives inside an aid/ folder (any path component named "aid").
1781
+ local dir
1782
+ dir="$(dirname "$f")"
1783
+ while [[ "$dir" != "$target" && "$dir" != "/" && "$dir" != "." ]]; do
1784
+ if [[ "$(basename "$dir")" == "aid" ]]; then return 0; fi
1785
+ dir="$(dirname "$dir")"
1786
+ done
1787
+ # No marker -- user content.
1788
+ return 1
1789
+ }
1790
+
1791
+ # Move one AID-owned file (marker 1 or 2) to <target>/.aid/.trash/<rel-path>.
1792
+ # In list_only mode: print the path instead of moving it (no writes).
1793
+ _retire_file() {
1794
+ local f="$1"
1795
+ [[ -f "$f" ]] || return 0
1796
+ if _is_aid_owned_file "$f"; then
1797
+ if [[ "$list_only" -eq 1 ]]; then
1798
+ echo " move to trash: ${f}"
1799
+ _MIGRATE_RETIRED_COUNT=$((_MIGRATE_RETIRED_COUNT + 1))
1800
+ else
1801
+ # Compute path relative to $target and move to the trash dir.
1802
+ local rel dest
1803
+ rel="${f#${target}/}"
1804
+ dest="${target}/.aid/.trash/${rel}"
1805
+ mkdir -p "$(dirname "$dest")"
1806
+ mv -f "$f" "$dest"
1807
+ _MIGRATE_RETIRED_COUNT=$((_MIGRATE_RETIRED_COUNT + 1))
1808
+ if [[ "${AID_VERBOSE:-0}" -eq 1 ]]; then echo "Trashed: ${f} -> ${dest}"; fi
1809
+ fi
1810
+ fi
1811
+ return 0
1812
+ }
1813
+
1814
+ # Sweep one retired root directory: remove AID-owned files, then prune
1815
+ # now-empty subdirs, then remove the root dir itself if now empty.
1816
+ # In list_only mode: enumerate would-be-removed files, make no changes.
1817
+ _sweep_retired_root() {
1818
+ local rdir="$1"
1819
+ [[ -d "$rdir" ]] || return 0
1820
+ # Walk all files under the retired root.
1821
+ local fpath
1822
+ while IFS= read -r -d '' fpath; do
1823
+ _retire_file "$fpath"
1824
+ done < <(find "$rdir" -type f -print0 2>/dev/null | sort -z)
1825
+ if [[ "$list_only" -eq 1 ]]; then return 0; fi
1826
+ # Prune now-empty subdirs (deepest first).
1827
+ local dpath
1828
+ while IFS= read -r dpath; do
1829
+ if [[ -d "$dpath" ]]; then
1830
+ local rem
1831
+ rem="$(find "$dpath" -mindepth 1 2>/dev/null | head -1)"
1832
+ if [[ -z "$rem" ]]; then
1833
+ rmdir "$dpath" 2>/dev/null || true
1834
+ if [[ "${AID_VERBOSE:-0}" -eq 1 ]]; then echo "Retired dir: ${dpath}"; fi
1835
+ fi
1836
+ fi
1837
+ done < <(find "$rdir" -mindepth 1 -type d 2>/dev/null | sort -r)
1838
+ # Remove the retired root itself if now empty.
1839
+ if [[ -d "$rdir" ]]; then
1840
+ local rem
1841
+ rem="$(find "$rdir" -mindepth 1 2>/dev/null | head -1)"
1842
+ if [[ -z "$rem" ]]; then
1843
+ rmdir "$rdir" 2>/dev/null || true
1844
+ if [[ "${AID_VERBOSE:-0}" -eq 1 ]]; then echo "Retired root dir: ${rdir}"; fi
1845
+ fi
1846
+ fi
1847
+ return 0
1848
+ }
1849
+
1850
+ case "$tool" in
1851
+ codex)
1852
+ # Retired root: .agents/ (old split layout -- skills/ + aid/ lived here).
1853
+ _sweep_retired_root "${target}/.agents"
1854
+ ;;
1855
+ cursor)
1856
+ # Retired root: .cursor/rules/ (rules dir no longer in new layout).
1857
+ _sweep_retired_root "${target}/.cursor/rules"
1858
+ ;;
1859
+ antigravity)
1860
+ # Retired root: .agent/rules/ (rules dir no longer in new layout).
1861
+ _sweep_retired_root "${target}/.agent/rules"
1862
+ ;;
1863
+ # claude-code and copilot-cli have no retired roots in this migration.
1864
+ esac
1865
+
1866
+ if [[ "$list_only" -eq 0 && "$_MIGRATE_RETIRED_COUNT" -gt 0 ]]; then
1867
+ echo " ${_MIGRATE_RETIRED_COUNT} retired AID file(s) moved to .aid/.trash/"
1868
+ fi
1869
+
1870
+ unset -f _is_aid_owned_file _retire_file _sweep_retired_root
1871
+ }
1872
+
1738
1873
  # ---------------------------------------------------------------------------
1739
1874
  # Version marker
1740
1875
  # ---------------------------------------------------------------------------
@@ -1786,7 +1921,8 @@ install_tool() {
1786
1921
  fi
1787
1922
  ;;
1788
1923
  codex)
1789
- # .codex/ + .agents/ + AGENTS.md
1924
+ # New unified layout: .codex/ only (agents, skills, aid all under .codex/).
1925
+ # .agents/ is the RETIRED split layout -- handled by _migrate_retired_layout.
1790
1926
  if [[ -d "${staging}/.codex" ]]; then
1791
1927
  copy_dir "${staging}/.codex" "${target}/.codex" "$force"
1792
1928
  while IFS= read -r -d '' f; do
@@ -1794,13 +1930,6 @@ install_tool() {
1794
1930
  install_paths+=("$rel")
1795
1931
  done < <(find "${staging}/.codex" -type f -print0 2>/dev/null | sort -z)
1796
1932
  fi
1797
- if [[ -d "${staging}/.agents" ]]; then
1798
- copy_dir "${staging}/.agents" "${target}/.agents" "$force"
1799
- while IFS= read -r -d '' f; do
1800
- local rel="${f#${staging}/}"
1801
- install_paths+=("$rel")
1802
- done < <(find "${staging}/.agents" -type f -print0 2>/dev/null | sort -z)
1803
- fi
1804
1933
  ;;
1805
1934
  cursor)
1806
1935
  # .cursor/ + AGENTS.md
@@ -1852,9 +1981,37 @@ install_tool() {
1852
1981
  fi
1853
1982
  fi
1854
1983
 
1984
+ # Manifest-seam entry gate (PLAN risk #3, delivery-001->002 seam).
1985
+ # Runs BEFORE manifest_write so a contaminated bundle never writes to disk.
1986
+ # Assert that the new bundle's path set does NOT contain any retired roots.
1987
+ # If a retired path leaked into the new manifest, fail loudly -- do not prune
1988
+ # against a contaminated manifest (content-isolation cornerstone).
1989
+ local _retired_roots=(".agents/" ".cursor/rules/" ".agent/rules/")
1990
+ local _rr _leaked
1991
+ for _rr in "${_retired_roots[@]}"; do
1992
+ for _p in "${install_paths[@]+"${install_paths[@]}"}"; do
1993
+ if [[ "$_p" == "${_rr}"* ]]; then
1994
+ _leaked="$_p"
1995
+ break
1996
+ fi
1997
+ done
1998
+ if [[ -n "${_leaked:-}" ]]; then
1999
+ echo "ERROR: aid-install-core: manifest-seam violation: retired root '${_rr}' leaked into the new bundle manifest (path: ${_leaked}). Aborting install to protect user content." >&2
2000
+ return 1
2001
+ fi
2002
+ done
2003
+ unset _rr _leaked
2004
+
1855
2005
  # Write manifest (merge).
1856
2006
  manifest_write "$manifest" "$tool" "$version" "install_paths" "root_entries"
1857
2007
 
2008
+ # Retired-root migration sweep (FR7/FR7a).
2009
+ # Remove AID-owned content from retired layout dirs BEFORE the normal prune,
2010
+ # so that old .agents/, .cursor/rules/, .agent/rules/ trees are cleaned up.
2011
+ # A non-zero rc from install_tool is treated as a mid-commit failure (caller
2012
+ # prints the "re-run to heal" message); this function returns 0 (WARN-not-fail).
2013
+ _migrate_retired_layout "$target" "$tool"
2014
+
1858
2015
  # Prune stale AID-owned files (Pillar 2, R7).
1859
2016
  # Build an associative array from the new manifest path set for O(1) lookup.
1860
2017
  declare -A _prune_manifest_set=()
package/package.json CHANGED
@@ -1,7 +1,9 @@
1
1
  {
2
2
  "name": "aid-installer",
3
- "version": "1.1.0",
4
- "description": "AID CLI installer - puts the persistent aid command on PATH via npm",
3
+ "version": "2.0.0",
4
+ "description": "AID (AI Integrated Development) CLI installer - puts the persistent aid command on PATH via npm",
5
+ "author": "Andre Vianna",
6
+ "homepage": "https://aid.casuloailabs.com",
5
7
  "bin": {
6
8
  "aid": "bin/aid.js"
7
9
  },
@@ -18,18 +20,19 @@
18
20
  "bin/",
19
21
  "lib/",
20
22
  "dashboard/",
21
- "scripts/",
23
+ "scripts/postinstall.js",
22
24
  "VERSION",
23
25
  "README.md",
24
26
  "LICENSE"
25
27
  ],
26
28
  "keywords": [
27
29
  "aid",
28
- "agentic",
29
- "iterative",
30
+ "AI",
31
+ "integrated",
30
32
  "development",
31
33
  "cli",
32
- "installer"
34
+ "installer",
35
+ "methodology"
33
36
  ],
34
37
  "license": "MIT",
35
38
  "repository": {
package/scripts/vendor.js DELETED
@@ -1,98 +0,0 @@
1
- #!/usr/bin/env node
2
- // vendor.js - Copy the aid-cli source files from the repo root into the npm package.
3
- //
4
- // Run automatically as the `prepack` npm script so `npm pack` and
5
- // `npm publish` always ship the current source.
6
- //
7
- // Source of truth is the repo root (two levels above packages/npm/).
8
- // Destination is packages/npm/{bin,lib,dashboard/,VERSION} (gitignored; generated at pack time).
9
- //
10
- // Files copied (mirrors release.sh Step-5 aid-cli bundle):
11
- // bin/aid -> packages/npm/bin/aid
12
- // bin/aid.ps1 -> packages/npm/bin/aid.ps1
13
- // bin/aid.cmd -> packages/npm/bin/aid.cmd
14
- // lib/aid-install-core.sh -> packages/npm/lib/aid-install-core.sh
15
- // lib/AidInstallCore.psm1 -> packages/npm/lib/AidInstallCore.psm1
16
- // VERSION -> packages/npm/VERSION
17
- //
18
- // Dashboard server+reader unit (12 files, curated -- excludes tests/ __pycache__ *.pyc README):
19
- // dashboard/home.html -> packages/npm/dashboard/home.html
20
- // dashboard/index.html -> packages/npm/dashboard/index.html
21
- // dashboard/reader/__init__.py -> packages/npm/dashboard/reader/__init__.py
22
- // dashboard/reader/reader.py -> packages/npm/dashboard/reader/reader.py
23
- // dashboard/reader/models.py -> packages/npm/dashboard/reader/models.py
24
- // dashboard/reader/parsers.py -> packages/npm/dashboard/reader/parsers.py
25
- // dashboard/reader/derivation.py -> packages/npm/dashboard/reader/derivation.py
26
- // dashboard/reader/locator.py -> packages/npm/dashboard/reader/locator.py
27
- // dashboard/server/server.py -> packages/npm/dashboard/server/server.py
28
- // dashboard/server/server.mjs -> packages/npm/dashboard/server/server.mjs
29
- // dashboard/server/reader.mjs -> packages/npm/dashboard/server/reader.mjs
30
- // dashboard/server/__init__.py -> packages/npm/dashboard/server/__init__.py
31
-
32
- 'use strict';
33
-
34
- var fs = require('fs');
35
- var path = require('path');
36
-
37
- // packages/npm/scripts/vendor.js is three levels below repo root.
38
- var repoRoot = path.join(__dirname, '..', '..', '..');
39
- var pkgRoot = path.join(__dirname, '..');
40
-
41
- var copies = [
42
- ['bin/aid', 'bin/aid'],
43
- ['bin/aid.ps1', 'bin/aid.ps1'],
44
- ['bin/aid.cmd', 'bin/aid.cmd'],
45
- ['lib/aid-install-core.sh', 'lib/aid-install-core.sh'],
46
- ['lib/AidInstallCore.psm1', 'lib/AidInstallCore.psm1'],
47
- ['VERSION', 'VERSION'],
48
- // Dashboard server+reader unit (12 files, curated).
49
- ['dashboard/home.html', 'dashboard/home.html'],
50
- ['dashboard/index.html', 'dashboard/index.html'],
51
- ['dashboard/reader/__init__.py', 'dashboard/reader/__init__.py'],
52
- ['dashboard/reader/reader.py', 'dashboard/reader/reader.py'],
53
- ['dashboard/reader/models.py', 'dashboard/reader/models.py'],
54
- ['dashboard/reader/parsers.py', 'dashboard/reader/parsers.py'],
55
- ['dashboard/reader/derivation.py', 'dashboard/reader/derivation.py'],
56
- ['dashboard/reader/locator.py', 'dashboard/reader/locator.py'],
57
- ['dashboard/server/server.py', 'dashboard/server/server.py'],
58
- ['dashboard/server/server.mjs', 'dashboard/server/server.mjs'],
59
- ['dashboard/server/reader.mjs', 'dashboard/server/reader.mjs'],
60
- ['dashboard/server/__init__.py', 'dashboard/server/__init__.py'],
61
- ];
62
-
63
- // Clean slate: remove any prior vendored payload (lib/ dir, dashboard/ dir, the vendored
64
- // bin scripts, VERSION) so stray runtime artifacts or files from an older version never
65
- // ship. Keep the committed shim bin/aid.js.
66
- try { fs.rmSync(path.join(pkgRoot, 'lib'), { recursive: true, force: true }); } catch (e) {}
67
- try { fs.rmSync(path.join(pkgRoot, 'dashboard'), { recursive: true, force: true }); } catch (e) {}
68
- ['bin/aid', 'bin/aid.ps1', 'bin/aid.cmd', 'VERSION'].forEach(function (f) {
69
- try { fs.rmSync(path.join(pkgRoot, f), { force: true }); } catch (e) {}
70
- });
71
-
72
- // Ensure destination directories exist.
73
- var dirs = ['bin', 'lib', 'dashboard/reader', 'dashboard/server'];
74
- for (var i = 0; i < dirs.length; i++) {
75
- var d = path.join(pkgRoot, dirs[i]);
76
- if (!fs.existsSync(d)) {
77
- fs.mkdirSync(d, { recursive: true });
78
- }
79
- }
80
-
81
- var ok = true;
82
- for (var j = 0; j < copies.length; j++) {
83
- var src = path.join(repoRoot, copies[j][0]);
84
- var dest = path.join(pkgRoot, copies[j][1]);
85
- try {
86
- fs.copyFileSync(src, dest);
87
- console.log('vendor: copied ' + copies[j][0] + ' -> packages/npm/' + copies[j][1]);
88
- } catch (e) {
89
- console.error('vendor: ERROR copying ' + src + ': ' + e.message);
90
- ok = false;
91
- }
92
- }
93
-
94
- if (!ok) {
95
- process.exit(1);
96
- }
97
-
98
- console.log('vendor: done. 18 files vendored into packages/npm/.');