@yukioa2z/visa-apply 3.0.1 → 3.0.3

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/README.md CHANGED
@@ -5,7 +5,14 @@ Research, prepare, review, and track visa applications with current official sou
5
5
  [Website](https://yukioa2z.github.io/visa-apply/) · [Source](https://github.com/Yukioa2z/visa-apply)
6
6
 
7
7
  ```sh
8
- npx --yes @yukioa2z/visa-apply
8
+ npx @yukioa2z/visa-apply
9
+ ```
10
+
11
+ Run in a terminal and pick your agent when prompted. To skip the prompt, pass your agent's skills directory:
12
+
13
+ ```sh
14
+ npx @yukioa2z/visa-apply -- --dest ~/.claude/skills # Claude Code
15
+ npx @yukioa2z/visa-apply -- --dest ~/.codex/skills # Codex
9
16
  ```
10
17
 
11
18
  Then invoke. To just check whether you need a visa:
@@ -20,11 +27,7 @@ Many trips end there with a visa-free or ETA answer. To prepare a full applicati
20
27
  Use $visa-apply to help me prepare a visa application for my destination and visa type.
21
28
  ```
22
29
 
23
- The installer copies the skill to `~/.codex/skills/visa-apply`. For Claude Code, Hermes, OpenClaw, or another agent with a different skill directory:
24
-
25
- ```sh
26
- npx --yes @yukioa2z/visa-apply -- --dest ~/.claude/skills
27
- ```
30
+ `--dest` is your agent's skills root; the installer copies the skill into `<dest>/visa-apply`. Point it at whatever directory your agent scans — Claude Code, Codex, Hermes, OpenClaw, or another agent. Run with `--help` to see the target paths.
28
31
 
29
32
  ## Pipeline
30
33
 
@@ -44,6 +47,12 @@ No cached source stores a visa-free or visa-required answer. Every case must be
44
47
 
45
48
  Government immigration, foreign-ministry, and embassy pages are the rule authority. Delegated visa application centres are used only for appointment and submission logistics.
46
49
 
50
+ ## Weekly source monitoring
51
+
52
+ Every Monday at 00:00 Asia/Shanghai, GitHub Actions compares normalized content fingerprints for every registered official visa source. All 250 destinations appear in the generated monitor: destinations with registered sources receive a change status, while destinations without a source seed are explicitly marked as requiring live official-source discovery.
53
+
54
+ A new fingerprint is first recorded as a review candidate and is only confirmed as changed when the same fingerprint appears in the next run. Either state is a review signal, not a visa-policy verdict. The workflow records the result in `skill/references/policy-monitor.json`, increments the package patch version, commits the report, and dispatches the npm trusted-publishing workflow. This keeps the installable skill current without turning an arbitrary webpage edit into legal guidance.
55
+
47
56
  The applicant model is global. It keeps citizenship, travel-document issuer, legal residence, current location, consular application location, and transit route separate, including dual nationals, third-country applicants, minors, and holders of refugee or other non-passport travel documents.
48
57
 
49
58
  This skill is not legal advice. The applicant must review all information and handle applicant-only declarations, signatures, certifications, CAPTCHA, and submission.
package/bin/install.js CHANGED
@@ -3,20 +3,32 @@
3
3
  const fs = require("fs");
4
4
  const os = require("os");
5
5
  const path = require("path");
6
+ const readline = require("readline");
6
7
 
7
8
  const skillName = "visa-apply";
8
9
  const packageRoot = path.resolve(__dirname, "..");
9
10
  const sourceDir = path.join(packageRoot, "skill");
10
11
 
12
+ // Known agents and the skills directory each one scans.
13
+ const AGENTS = [
14
+ { label: "Claude Code", dir: "~/.claude/skills" },
15
+ { label: "Codex", dir: "~/.codex/skills" },
16
+ ];
17
+
11
18
  function usage() {
19
+ const lines = AGENTS.map(
20
+ (a) => ` ${a.label.padEnd(13)} npx @yukioa2z/visa-apply -- --dest ${a.dir}`
21
+ ).join("\n");
12
22
  console.log(`Install ${skillName}
13
23
 
14
- Usage:
15
- npx @yukioa2z/visa-apply
16
- npx @yukioa2z/visa-apply -- --dest ~/.claude/skills
24
+ Pick your agent's skills directory with --dest:
25
+ ${lines}
26
+ Other agent npx @yukioa2z/visa-apply -- --dest <your agent's skills dir>
27
+
28
+ Run with no --dest in a terminal to choose interactively.
17
29
 
18
30
  Options:
19
- --dest <path> Skill root directory. Defaults to $CODEX_HOME/skills or ~/.codex/skills.
31
+ --dest <path> Skill root directory.
20
32
  --dry-run Print the destination without copying files.
21
33
  --help Show this help message.
22
34
  `);
@@ -36,32 +48,75 @@ function readOption(name) {
36
48
  return args[index + 1];
37
49
  }
38
50
 
39
- const args = process.argv.slice(2);
40
- if (args.includes("--help") || args.includes("-h")) {
41
- usage();
42
- process.exit(0);
51
+ function install(destRoot, dryRun) {
52
+ const destDir = path.join(destRoot, skillName);
53
+ if (dryRun) {
54
+ console.log(destDir);
55
+ return;
56
+ }
57
+ fs.mkdirSync(destRoot, { recursive: true });
58
+ fs.rmSync(destDir, { recursive: true, force: true });
59
+ fs.cpSync(sourceDir, destDir, { recursive: true });
60
+ console.log(`Installed ${skillName} to ${destDir}`);
61
+ console.log(
62
+ `Try: Use $${skillName} to check your visa need and prepare an application dossier.`
63
+ );
43
64
  }
44
65
 
45
- if (!fs.existsSync(sourceDir)) {
46
- console.error(`Skill source not found: ${sourceDir}`);
47
- process.exit(1);
66
+ function promptAgent() {
67
+ return new Promise((resolve) => {
68
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
69
+ console.log("Which agent are you installing for?\n");
70
+ AGENTS.forEach((a, i) => console.log(` ${i + 1}) ${a.label} (${a.dir})`));
71
+ console.log(` ${AGENTS.length + 1}) Other (enter a path)\n`);
72
+ rl.question("Choice: ", (answer) => {
73
+ rl.close();
74
+ const n = parseInt(answer.trim(), 10);
75
+ if (n >= 1 && n <= AGENTS.length) {
76
+ resolve(AGENTS[n - 1].dir);
77
+ } else if (n === AGENTS.length + 1) {
78
+ const rl2 = readline.createInterface({ input: process.stdin, output: process.stdout });
79
+ rl2.question("Skills directory path: ", (p) => {
80
+ rl2.close();
81
+ resolve(p.trim() || null);
82
+ });
83
+ } else {
84
+ resolve(null);
85
+ }
86
+ });
87
+ });
48
88
  }
49
89
 
50
- const defaultRoot = process.env.CODEX_HOME
51
- ? path.join(process.env.CODEX_HOME, "skills")
52
- : path.join(os.homedir(), ".codex", "skills");
90
+ async function main() {
91
+ const args = process.argv.slice(2);
92
+ if (args.includes("--help") || args.includes("-h")) {
93
+ usage();
94
+ return;
95
+ }
96
+ if (!fs.existsSync(sourceDir)) {
97
+ console.error(`Skill source not found: ${sourceDir}`);
98
+ process.exitCode = 1;
99
+ return;
100
+ }
53
101
 
54
- const destRoot = path.resolve(expandHome(readOption("--dest") || defaultRoot));
55
- const destDir = path.join(destRoot, skillName);
102
+ const dryRun = args.includes("--dry-run");
103
+ let dest = readOption("--dest");
56
104
 
57
- if (args.includes("--dry-run")) {
58
- console.log(destDir);
59
- process.exit(0);
60
- }
105
+ if (!dest) {
106
+ // No target given. Ask interactively when attached to a terminal;
107
+ // otherwise (agent/CI) print guidance and exit without guessing.
108
+ if (process.stdin.isTTY && process.stdout.isTTY) {
109
+ dest = await promptAgent();
110
+ }
111
+ if (!dest) {
112
+ console.error("No skills directory chosen.\n");
113
+ usage();
114
+ process.exitCode = 1;
115
+ return;
116
+ }
117
+ }
61
118
 
62
- fs.mkdirSync(destRoot, { recursive: true });
63
- fs.rmSync(destDir, { recursive: true, force: true });
64
- fs.cpSync(sourceDir, destDir, { recursive: true });
119
+ install(path.resolve(expandHome(dest)), dryRun);
120
+ }
65
121
 
66
- console.log(`Installed ${skillName} to ${destDir}`);
67
- console.log(`Try: Use $${skillName} to check your visa need and prepare an application dossier.`);
122
+ main();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yukioa2z/visa-apply",
3
- "version": "3.0.1",
3
+ "version": "3.0.3",
4
4
  "description": "Install a global visa-need research and application filing skill.",
5
5
  "license": "MIT",
6
6
  "keywords": [
package/skill/SKILL.md CHANGED
@@ -23,6 +23,7 @@ This skill is not legal advice. The applicant must review every answer and handl
23
23
  3. Run the mandatory live visa-need check before detailed intake.
24
24
  - Read `references/live-route-check.md`.
25
25
  - Resolve the destination in `references/jurisdictions.json`; cached starting sources are in `references/official-sources.json`.
26
+ - Consult `references/policy-monitor.json` when present. A changed fingerprint means the official page needs review; it is never a visa verdict and never replaces the live check.
26
27
  - Run `python3 scripts/source_registry.py live-check-plan <country> ...` when useful.
27
28
  - Browse current destination-government and responsible-mission sources for the exact passport, residence, purpose, dates, duration, entries, arrival mode, and transit itinerary.
28
29
  - Cross-check IATA Travel Centre/Timatic or the operating carrier for boarding requirements. Treat it as operational evidence, not legal authority.
@@ -42,6 +43,7 @@ This skill is not legal advice. The applicant must review every answer and handl
42
43
  - No chat note or scratch file may become more authoritative than the HTML.
43
44
  8. Run `references/quality-gates.md`, then stop at the applicant review gate before portal entry. Call out inferred values, stale sources, missing documents, expiring evidence, and unresolved conflicts.
44
45
  9. Assist with form entry using Browser or Computer Use after review.
46
+ - Before filling anything, make sure the dossier HTML is open in the user's default viewer (open it if it is not) so they can follow progress while you enter the form. Keep updating that file as each field is filled; the user refreshes to see the latest.
45
47
  - In non-Codex environments, use the equivalent browser/computer capability, such as Peekaboo or the runtime's supported automation skill.
46
48
  - Never bypass CAPTCHA or security controls, invent data, or perform an applicant-only signature/certification.
47
49
  10. Backfill application IDs, receipts, appointments/biometrics, document requests, decision status, and passport/visa return details into the HTML.
@@ -68,6 +70,8 @@ python3 scripts/create_dossier.py /path/to/visa-dossier.html \
68
70
  --transit "Singapore, airside"
69
71
  ```
70
72
 
73
+ Immediately open the dossier in the user's default viewer so they can watch it fill in as the interview proceeds. Use the platform opener: `open <path>` on macOS, `xdg-open <path>` on Linux, `start "" <path>` on Windows. Open it once; each later HTML update lands in the same file, so the user just refreshes the tab. If no opener is available (headless/remote), tell the user the local path to open manually.
74
+
71
75
  ## References
72
76
 
73
77
  - Full pipeline and source freshness rules: `references/pipeline.md`
@@ -77,4 +81,5 @@ python3 scripts/create_dossier.py /path/to/visa-dossier.html \
77
81
  - Submission, document, timing, and privacy gates: `references/quality-gates.md`
78
82
  - Searchable destination directory: `references/jurisdictions.json`
79
83
  - Official source registry: `references/official-sources.json`
84
+ - Weekly official-source change signals: `references/policy-monitor.json` (source health only, never a visa verdict)
80
85
  - Full country adapters: `references/countries/` — United States DS-160 (`us.md`), Schengen Type C (`schengen.md`), Canada IRCC (`ca.md`), United Kingdom (`uk.md`), Australia (`au.md`), Japan (`jp.md`). Every other destination uses a source-seeded or live-discovered adapter.